Esempio n. 1
0
def test_rate_limiting_on_form_posts(client, msend):
    # confirm a form
    client.post(
        "/[email protected]",
        headers={"referer": "http://somewhere.com"},
        data={"name": "john"},
    )
    form = Form.get_with(host="somewhere.com", email="*****@*****.**")
    form.confirmed = True
    DB.session.add(form)
    DB.session.commit()

    # submit form many times
    replies = []
    for _ in range(1000):
        r = client.post(
            "/[email protected]",
            headers={"referer": "http://somewhere.com"},
            data={"name": "attacker"},
        )
        replies.append(r.status_code)

    limit = int(settings.RATE_LIMIT.split(" ")[0])

    # the number of submissions should not be more than the rate limit
    form = Form.get_with(host="somewhere.com", email="*****@*****.**")
    assert form.counter < limit

    # should have gotten some 302 and then many 429 responses
    assert replies.count(302) <= limit
    assert replies.count(429) >= 900 - limit
Esempio n. 2
0
def test_a_confusing_case(client, msend):
    """
    Final boss.
    """

    prepare()
    try:
        _, uf = create_user_and_form(client)
        DB.session.add(
            Form(email=uf.email, confirmed=False, host="example.com"))
        DB.session.add(
            Form(email=uf.email, confirmed=True, host="example.com/contact"))
        DB.session.add(
            Form(email=uf.email, confirmed=True, host="www.example.com/"))
        DB.session.commit()

        assert Form.query.count() == 4

        form = Form.get_with(email=uf.email, host="example.com/")
        assert form
        assert form.confirmed
        assert form.host == "www.example.com/"

        form2 = Form.get_with(email=uf.email, host="www.example.com")
        assert form2
        assert form2.confirmed
        assert form.host == "www.example.com/"

        contact = form.get_with(email=uf.email,
                                host="www.example.com/contact/")
        assert contact
        assert contact.host == "example.com/contact"

        assert form.id != contact.id
        assert form.id == form2.id

        r = client.post(
            "/" + uf.email,
            headers={"Referer": "http://example.com/"},
            data={"name": "example"},
        )
        assert r.status_code == 302
        assert "next" in r.location

        r = client.post(
            "/" + uf.email,
            headers={"Referer": "www.example.com"},
            data={"name": "example"},
        )
        assert r.status_code == 302
        assert "next" in r.location

        assert msend.call_count == 2
        assert Form.query.count() == 4
        form3 = Form.get_with(email=uf.email, host="example.com")
        assert 2 == form.submissions.count()
        assert form3.id == form2.id == form.id

    finally:
        revert()
Esempio n. 3
0
def test_a_confusing_case(client, msend):
    """
    Final boss.
    """

    prepare()
    try:
        _, uf = create_user_and_form(client)
        DB.session.add(Form(email=uf.email, confirmed=False, host="example.com"))
        DB.session.add(Form(email=uf.email, confirmed=True, host="example.com/contact"))
        DB.session.add(Form(email=uf.email, confirmed=True, host="www.example.com/"))
        DB.session.commit()

        assert Form.query.count() == 4

        form = Form.get_with(email=uf.email, host="example.com/")
        assert form
        assert form.confirmed
        assert form.host == "www.example.com/"

        form2 = Form.get_with(email=uf.email, host="www.example.com")
        assert form2
        assert form2.confirmed
        assert form.host == "www.example.com/"

        contact = form.get_with(email=uf.email, host="www.example.com/contact/")
        assert contact
        assert contact.host == "example.com/contact"

        assert form.id != contact.id
        assert form.id == form2.id

        r = client.post(
            "/" + uf.email,
            headers={"Referer": "http://example.com/"},
            data={"name": "example"},
        )
        assert r.status_code == 302
        assert "next" in r.location

        r = client.post(
            "/" + uf.email,
            headers={"Referer": "www.example.com"},
            data={"name": "example"},
        )
        assert r.status_code == 302
        assert "next" in r.location

        assert msend.call_count == 2
        assert Form.query.count() == 4
        form3 = Form.get_with(email=uf.email, host="example.com")
        assert 2 == form.submissions.count()
        assert form3.id == form2.id == form.id

    finally:
        revert()
Esempio n. 4
0
def test_backwards_none_confirmed(client, msend):
    """
    This time no form is confirmed.
    """

    prepare()
    try:
        for host in hosts:
            f = Form(email=email, confirmed=False, host=host)
            DB.session.add(f)
            DB.session.commit()

        for referer in hosts:
            r = client.post(
                "/" + email,
                headers={"Referer": "http://" + referer},
                data={"name": "example"},
            )

            assert r.status_code == 200
            assert b"confirm" in r.get_data()
            assert Form.get_with(email=email, host=referer).host == hosts[0]

        assert Form.query.count() == len(hosts)
        assert Form.query.filter_by(confirmed=True).count() == 0
        assert Submission.query.count() == 0

    finally:
        revert()
Esempio n. 5
0
def test_backwards_none_confirmed(client, msend):
    """
    This time no form is confirmed.
    """

    prepare()
    try:
        for host in hosts:
            f = Form(email=email, confirmed=False, host=host)
            DB.session.add(f)
            DB.session.commit()

        for referer in hosts:
            r = client.post(
                "/" + email,
                headers={"Referer": "http://" + referer},
                data={"name": "example"},
            )

            assert r.status_code == 200
            assert b"confirm" in r.get_data()
            assert Form.get_with(email=email, host=referer).host == hosts[0]

        assert Form.query.count() == len(hosts)
        assert Form.query.filter_by(confirmed=True).count() == 0
        assert Submission.query.count() == 0

    finally:
        revert()
Esempio n. 6
0
def google_call(hashid):
    form = Form.get_with(hashid=hashid)
    session["ggl:form"] = form.hashid

    hint = form.email
    if not form.email.endswith("@gmail.com") and current_user.email.endswith(
        "@gmail.com"
    ):
        hint = current_user.email

    flow = google_auth_oauthlib.flow.Flow.from_client_config(
        settings.GOOGLE_CLIENT_CONFIG,
        scopes=["https://www.googleapis.com/auth/drive.file"],
    )
    flow.redirect_uri = url_for(
        "google_callback",
        _external=True,
        _scheme="https",  # can't figure out how to get this to honor PREFERRED_URL_SCHEME
    )
    authorization_url, _ = flow.authorization_url(
        access_type="offline",
        login_hint=hint,
        prompt="consent",
        state=hashid,
        include_granted_scopes="true",
    )
    return redirect(authorization_url)
Esempio n. 7
0
def google_callback():
    hashid = session["ggl:form"]
    del session["ggl:form"]
    if hashid != request.args.get("state"):
        return script_error("oauth-failed")

    form = Form.get_with(hashid=hashid)

    flow = google_auth_oauthlib.flow.Flow.from_client_config(
        settings.GOOGLE_CLIENT_CONFIG,
        state=hashid,
        scopes=["https://www.googleapis.com/auth/drive.file"],
    )

    flow.redirect_uri = url_for("google_callback", _external=True, _scheme="https")

    flow.fetch_token(authorization_response=request.url.replace("http://", "https://"))

    plugin = Plugin(form_id=form.id, kind=PluginKind.google_sheets)
    plugin.access_token = json.dumps(
        {
            "token": flow.credentials.token,
            "refresh_token": flow.credentials.refresh_token,
            "token_uri": flow.credentials.token_uri,
            "id_token": flow.credentials.id_token,
            "client_id": flow.credentials.client_id,
            "client_secret": flow.credentials.client_secret,
        }
    )

    spreadsheet_title = (
        form.name
        if form.name
        else f"{settings.SERVICE_NAME} submissions for {form.hashid}"
    )[:128]

    google_creds = json.loads(plugin.access_token)
    credentials = google.oauth2.credentials.Credentials(**google_creds)
    spreadsheet_id, worksheet_id = create_google_sheet(
        form, spreadsheet_title, credentials
    )

    plugin.plugin_data = {
        "spreadsheet_id": spreadsheet_id,
        "worksheet_id": worksheet_id,
    }
    DB.session.add(plugin)
    DB.session.commit()

    return script_data({"spreadsheet_id": spreadsheet_id})
Esempio n. 8
0
def validate_user_form(hashid):
    """
    Gets a form from a hashid, created on the dashboard.
    Checks to make sure the submission can be accepted by this form.
    """

    form = Form.get_with(hashid=hashid)

    if not form:
        raise SubmitFormError(errors.bad_hashid_error(hashid))

    if form.disabled:
        raise SubmitFormError(errors.disabled_error())

    return form
Esempio n. 9
0
def mailchimp_call(hashid):
    form = Form.get_with(hashid=hashid)
    session["mcp:form"] = form.hashid

    return redirect(
        "https://login.mailchimp.com/oauth2/authorize?"
        + urlencode(
            {
                "response_type": "code",
                "client_id": settings.MAILCHIMP_CLIENT_ID,
                "redirect_uri": url_for(
                    "mailchimp_callback", _external=True, _scheme="https"
                ),
                "state": form.hashid,
            }
        )
    )
Esempio n. 10
0
def mailchimp_callback():
    error = request.args.get("error")
    if error:
        return script_error(error if error == "access-denied" else "oauth-failed")

    hashid = session["mcp:form"]
    del session["mcp:form"]
    if hashid != request.args.get("state"):
        return script_error("oauth-failed")

    code = request.args.get("code")
    r = requests.post(
        "https://login.mailchimp.com/oauth2/token",
        data={
            "grant_type": "authorization_code",
            "client_id": settings.MAILCHIMP_CLIENT_ID,
            "client_secret": settings.MAILCHIMP_CLIENT_SECRET,
            "code": code,
            "redirect_uri": url_for(
                "mailchimp_callback", _external=True, _scheme="https"
            ),
        },
    )
    if not r.ok:
        return script_error("oauth-failed")

    data = r.json()
    form = Form.get_with(hashid=hashid)
    plugin = Plugin(form_id=form.id, kind=PluginKind.mailchimp)

    r = requests.get(
        "https://login.mailchimp.com/oauth2/metadata",
        headers={"Authorization": "OAuth " + data["access_token"]},
    )
    if not r.ok:
        return script_error("oauth-failed")

    meta = r.json()

    plugin.access_token = data["access_token"]
    plugin.plugin_data = {"api_endpoint": meta["api_endpoint"], "dc": meta["dc"]}
    plugin.enabled = False
    DB.session.add(plugin)
    DB.session.commit()

    return script_data({"ok": True})
Esempio n. 11
0
def slack_call(hashid):
    form = Form.get_with(hashid=hashid)
    session["slk:form"] = form.hashid

    return redirect(
        "https://slack.com/oauth/authorize?"
        + urlencode(
            {
                "client_id": settings.SLACK_CLIENT_ID,
                "scope": "incoming-webhook",
                "redirect_uri": url_for(
                    "slack_callback", _external=True, _scheme="https"
                ),
                "state": form.hashid,
            }
        )
    )
Esempio n. 12
0
def export_submissions(hashid, format=None):
    if not current_user.has_feature("dashboard"):
        return jsonify({"error": "Please upgrade your account."}), 402

    form = Form.get_with(hashid=hashid)
    if not form.controlled_by(current_user):
        return abort(401)

    submissions, fields = form.submissions_with_fields(with_ids=False)

    if format == "json":
        return Response(
            json.dumps(
                {
                    "host": form.host,
                    "email": form.email,
                    "fields": fields,
                    "submissions": submissions,
                },
                sort_keys=True,
                indent=2,
            ),
            mimetype="application/json",
            headers={
                "Content-Disposition":
                "attachment; filename=form-%s-submissions-%s.json" %
                (hashid, datetime.datetime.now().isoformat().split(".")[0])
            },
        )
    elif format == "csv":
        out = io.BytesIO()

        w = csv.DictWriter(out, fieldnames=fields, encoding="utf-8")
        w.writeheader()
        for sub in submissions:
            w.writerow(sub)

        return Response(
            out.getvalue(),
            mimetype="text/csv",
            headers={
                "Content-Disposition":
                "attachment; filename=form-%s-submissions-%s.csv" %
                (hashid, datetime.datetime.now().isoformat().split(".")[0])
            },
        )
Esempio n. 13
0
def export_submissions(hashid, format=None):
    if not current_user.has_feature("dashboard"):
        return jsonify({"error": "Please upgrade your account."}), 402

    form = Form.get_with(hashid=hashid)
    if not form.controlled_by(current_user):
        return abort(401)

    submissions, fields = form.submissions_with_fields(with_ids=False)

    if format == "json":
        return Response(
            json.dumps(
                {
                    "host": form.host,
                    "email": form.email,
                    "fields": fields,
                    "submissions": submissions,
                },
                sort_keys=True,
                indent=2,
            ),
            mimetype="application/json",
            headers={
                "Content-Disposition": "attachment; filename=form-%s-submissions-%s.json"
                % (hashid, datetime.datetime.now().isoformat().split(".")[0])
            },
        )
    elif format == "csv":
        out = io.BytesIO()

        w = csv.DictWriter(out, fieldnames=fields, encoding="utf-8")
        w.writeheader()
        for sub in submissions:
            w.writerow(sub)

        return Response(
            out.getvalue(),
            mimetype="text/csv",
            headers={
                "Content-Disposition": "attachment; filename=form-%s-submissions-%s.csv"
                % (hashid, datetime.datetime.now().isoformat().split(".")[0])
            },
        )
Esempio n. 14
0
def get_or_create_form(email, host):
    """
    Gets the form if it already exits, otherwise checks to ensure
    that this is a valid new form submission. If so, creates a
    new form.
    """

    form = Form.get_with(email=email, host=host)

    if not form:
        if request_wants_json():
            # Can't create a new ajax form unless from the dashboard
            ajax_error_str = (
                "To prevent spam, only "
                + settings.UPGRADED_PLAN_NAME
                + " accounts may create AJAX forms."
            )
            raise SubmitFormError((jsonify({"error": ajax_error_str}), 400))

        if (
            url_domain(settings.SERVICE_URL) in host
            and host.rstrip("/") != settings.TEST_URL
        ):
            # Bad user is trying to submit a form spoofing formspree.io
            g.log.info(
                "User attempting to create new form spoofing SERVICE_URL. Ignoring."
            )
            raise SubmitFormError(
                (
                    render_template(
                        "error.html", title="Unable to submit form", text="Sorry."
                    ),
                    400,
                )
            )

        # all good, create form
        form = Form(email, host=host, confirmed=False, normalize=True)

    if form.disabled:
        raise SubmitFormError(errors.disabled_error())

    return form
Esempio n. 15
0
def trello_call(hashid):
    form = Form.get_with(hashid=hashid)
    session["trl:form"] = form.hashid

    return redirect(
        "https://trello.com/1/authorize?{}".format(
            urlencode(
                {
                    "return_url": url_for(
                        "fragment_postmessage", _external=True, _scheme="https"
                    ),
                    "expiration": "never",
                    "scope": "read,write",
                    "name": settings.SERVICE_NAME,
                    "key": settings.TRELLO_API_KEY,
                    "callback_method": "fragment",
                    "response_type": "fragment",
                }
            )
        )
    )
Esempio n. 16
0
def slack_callback():
    error = request.args.get("error")
    if error:
        return script_error(error if error == "access-denied" else "oauth-failed")

    hashid = session["slk:form"]
    del session["slk:form"]
    if hashid != request.args.get("state"):
        return script_error("oauth-failed")

    code = request.args.get("code")
    r = requests.get(
        "https://slack.com/api/oauth.access",
        params={
            "client_id": settings.SLACK_CLIENT_ID,
            "client_secret": settings.SLACK_CLIENT_SECRET,
            "code": code,
            "redirect_uri": url_for("slack_callback", _external=True, _scheme="https"),
        },
    )
    if not r.ok:
        return script_error("oauth-failed")

    data = r.json()

    form = Form.get_with(hashid=hashid)
    plugin = Plugin(form_id=form.id, kind=PluginKind.slack)
    plugin.access_token = data["access_token"]
    plugin.plugin_data = {
        "team_name": data["team_name"],
        "team_id": data["team_id"],
        "incoming_webhook": data["incoming_webhook"],
    }
    plugin.enabled = True
    DB.session.add(plugin)
    DB.session.commit()

    return script_data(
        {"channel": data["incoming_webhook"]["channel"], "team": data["team_name"]}
    )
def test_user_gets_previous_forms_assigned_to_him(client, msend):
    # verify a form for márkö@example.com
    client.post(
        u"/márkö@example.com",
        headers={"Referer": "tomatoes.com"},
        data={"name": "alice"},
    )
    f = Form.get_with(host="tomatoes.com", email="márkö@example.com")
    f.confirm_sent = True
    f.confirmed = True
    DB.session.add(f)
    DB.session.commit()

    # register márkö@example.com
    r = client.post("/register",
                    data={
                        "email": "márkö@example.com",
                        "password": "******"
                    })

    # confirm that the user account doesn't have access to the form
    r = client.get(
        "/api-int/forms",
        headers={
            "Accept": "application/json",
            "Referer": settings.SERVICE_URL
        },
    )
    forms = json.loads(r.data.decode("utf-8"))["forms"]
    assert 0 == len(forms)

    # verify user email
    link, qs = parse_confirmation_link_sent(msend.call_args[1]["text"])
    client.get(link, query_string=qs)

    # confirm that the user has no access to the form since he is not gold
    r = client.get(
        "/api-int/forms",
        headers={
            "Accept": "application/json",
            "Referer": settings.SERVICE_URL
        },
    )
    forms = json.loads(r.data.decode("utf-8"))["forms"]
    assert 0 == len(forms)

    # upgrade user
    user = User.query.filter_by(email="márkö@example.com").first()
    user.plan = Plan.gold
    DB.session.add(user)
    DB.session.commit()

    # confirm that the user account has access to the form
    r = client.get(
        "/api-int/forms",
        headers={
            "Accept": "application/json",
            "Referer": settings.SERVICE_URL
        },
    )
    forms = json.loads(r.data.decode("utf-8"))["forms"]
    assert 1 == len(forms)
    assert forms[0]["email"] == "márkö@example.com"
    assert forms[0]["host"] == "tomatoes.com"

    # verify a form for another address
    r = client.post("/[email protected]",
                    headers={"Referer": "mark.com"},
                    data={"name": "luke"})
    f = Form.get_with(host="mark.com", email="*****@*****.**")
    f.confirm_sent = True
    f.confirmed = True
    DB.session.add(f)
    DB.session.commit()

    # confirm that the user account doesn't have access to the form
    r = client.get(
        "/api-int/forms",
        headers={
            "Accept": "application/json",
            "Referer": settings.SERVICE_URL
        },
    )
    forms = json.loads(r.data.decode("utf-8"))["forms"]
    assert 1 == len(forms)

    # add this other email address to user account
    client.post(
        "/api-int/account/emails",
        headers={
            "Content-Type": "application/json",
            "Referer": settings.SERVICE_URL
        },
        data=json.dumps({"address": "*****@*****.**"}),
    )

    link, qs = parse_confirmation_link_sent(msend.call_args[1]["text"])
    client.get(link, query_string=qs)

    # confirm that the user account now has access to the form
    r = client.get(
        "/api-int/forms",
        headers={
            "Accept": "application/json",
            "Referer": settings.SERVICE_URL
        },
    )
    forms = json.loads(r.data.decode("utf-8"))["forms"]
    assert 2 == len(forms)
    assert (forms[0]["email"] == "*****@*****.**"
            )  # forms are sorted by -id, so the newer comes first
    assert forms[0]["host"] == "mark.com"

    # create a new form spontaneously with an email already verified
    r = client.post(
        u"/márkö@example.com",
        headers={"Referer": "elsewhere.com"},
        data={"name": "luke"},
    )
    f = Form.get_with(host="elsewhere.com", email="márkö@example.com")
    f.confirm_sent = True
    f.confirmed = True
    DB.session.add(f)
    DB.session.commit()

    # confirm that the user has already accessto that form
    r = client.get(
        "/api-int/forms",
        headers={
            "Accept": "application/json",
            "Referer": settings.SERVICE_URL
        },
    )
    forms = json.loads(r.data.decode("utf-8"))["forms"]
    assert 3 == len(forms)
    assert forms[0]["email"] == "márkö@example.com"
    assert forms[0]["host"] == "elsewhere.com"
Esempio n. 18
0
def test_form_creation(client, msend):
    # register user
    r = client.post(
        "/register", data={"email": "*****@*****.**", "password": "******"}
    )
    assert r.status_code == 302
    assert 1 == User.query.count()

    email = Email.query.first()
    email.verified = True
    DB.session.add(email)
    DB.session.commit()

    # fail to create form
    r = client.post(
        "/api-int/forms",
        headers={"Content-type": "application/json", "Referer": settings.SERVICE_URL},
        data={"email": "*****@*****.**"},
    )
    assert r.status_code == 402
    assert "error" in json.loads(r.data.decode("utf-8"))
    assert 0 == Form.query.count()

    # upgrade user manually
    user = User.query.first()
    user.plan = Plan.gold
    DB.session.add(user)
    DB.session.commit()

    # successfully create form
    r = client.post(
        "/api-int/forms",
        headers={"Content-type": "application/json", "Referer": settings.SERVICE_URL},
        data=json.dumps({"email": "*****@*****.**"}),
    )
    resp = json.loads(r.data.decode("utf-8"))
    assert r.status_code == 201
    assert "submission_url" in resp
    assert "hashid" in resp
    form_endpoint = resp["hashid"]
    assert resp["hashid"] in resp["submission_url"]
    assert 1 == Form.query.count()
    assert Form.query.first().id == Form.get_with(hashid=resp["hashid"]).id

    # post to form, already confirmed because it was created from the dashboard
    r = client.post(
        "/" + form_endpoint,
        headers={
            "Referer": "http://formspree.io",
            "Content-Type": "application/x-www-form-urlencoded",
        },
        data=urllib.parse.urlencode({"name": "bruce"}),
        follow_redirects=True,
    )
    assert "Thanks!" in r.data.decode("utf-8")
    assert (
        "Someone just submitted your form on {}".format("formspree.io")
        in msend.call_args[1]["text"]
    )
    assert 1 == Form.query.count()

    # send 5 forms (monthly limits should not apply to the gold user)
    assert settings.MONTHLY_SUBMISSIONS_LIMIT == 2
    for i in range(5):
        r = client.post(
            "/" + form_endpoint,
            headers={"Referer": "formspree.io"},
            data={"name": "ana", "submission": "__%s__" % i},
        )
    form = Form.query.first()
    assert form.counter == 6
    assert form.get_monthly_counter() == 6
    assert "ana" in msend.call_args[1]["text"]
    assert "__4__" in msend.call_args[1]["text"]
    assert "past the limit" not in msend.call_args[1]["text"]

    # submit from a different host
    r = client.post(
        "/" + form_endpoint,
        headers={"Referer": "http://different.com"},
        data={"name": "ignored"},
        follow_redirects=True,
    )
    assert r.status_code == 200
    assert "Thanks!" in r.data.decode("utf-8")
    assert (
        "Someone just submitted your form on {}".format("different.com")
        in msend.call_args[1]["text"]
    )
    assert 1 == Form.query.count()

    # test submissions endpoint with the user downgraded
    user.plan = Plan.free
    DB.session.add(user)
    DB.session.commit()
    r = client.get(
        "/api-int/forms/" + form_endpoint, headers={"Referer": settings.SERVICE_URL}
    )
    assert r.status_code == 402  # it should fail

    # test submissions endpoint without a logged user
    client.get("/logout")
    r = client.get(
        "/api-int/forms/" + form_endpoint, headers={"Referer": settings.SERVICE_URL}
    )
    assert r.status_code == 401  # should return a json error (via flask login)
    assert "error" in r.json
Esempio n. 19
0
def resend_confirmation(email):
    g.log = g.log.bind(email=email, host=request.form.get("host"))
    g.log.info("Resending confirmation.")

    if verify_captcha(request.form, request.remote_addr):
        # check if this email is listed on SendGrid's bounces
        r = requests.get(
            "https://api.sendgrid.com/api/bounces.get.json",
            params={
                "email": email,
                "api_user": settings.SENDGRID_USERNAME,
                "api_key": settings.SENDGRID_PASSWORD,
            },
        )
        if r.ok and len(r.json()) and "reason" in r.json()[0]:
            # tell the user to verify his mailbox
            reason = r.json()[0]["reason"]
            g.log.info("Email is blocked on SendGrid. Telling the user.")
            if request_wants_json():
                resp = jsonify({
                    "error": "Verify your mailbox, we can't reach it.",
                    "reason": reason,
                })
            else:
                resp = make_response(
                    render_template(
                        "info.html",
                        title="Verify the availability of your mailbox",
                        text=
                        "We encountered an error when trying to deliver the confirmation message to <b>"
                        + email +
                        "</b> at the first time we tried. For spam reasons, we will not try again until we are sure the problem is fixed. Here's the reason:</p><p><center><i>"
                        + reason +
                        "</i></center></p><p>Please make sure this problem is not happening still, then go to <a href='/unblock/"
                        + email +
                        "'>this page</a> to unblock your address.</p><p>After you have unblocked the address, please try to resend the confirmation again.</p>",
                    ))
            return resp
        # ~~~
        # if there's no bounce, we proceed to resend the confirmation.

        # BUG: What if this is an owned form with hashid??

        form = Form.get_with(email=email, host=request.form["host"])
        if not form:
            if request_wants_json():
                return jsonify({"error": "This form does not exist."}), 400
            else:
                return (
                    render_template(
                        "error.html",
                        title="Check email address",
                        text="This form does not exist.",
                    ),
                    400,
                )
        form.confirm_sent = False
        status = form.send_confirmation()
        if status["code"] == Form.STATUS_CONFIRMATION_SENT:
            if request_wants_json():
                return jsonify({"success": "confirmation email sent"})
            else:
                return render_template(
                    "forms/confirmation_sent.html",
                    email=email,
                    host=request.form["host"],
                    resend=status["code"] ==
                    Form.STATUS_CONFIRMATION_DUPLICATED,
                )

    # fallback response -- should happen only when the recaptcha is failed.
    g.log.warning("Failed to resend confirmation.")
    return (
        render_template(
            "error.html",
            title="Unable to send email",
            text=
            "Please make sure you pass the <i>reCaptcha</i> test before submitting.",
        ),
        500,
    )
Esempio n. 20
0
def test_automatically_created_forms(client,
                                     host="somewhere.com",
                                     email="*****@*****.**"):

    form = create_and_activate_form(client,
                                    host="somewhere.com",
                                    email="*****@*****.**")

    # add four filler submissions
    DB.session.add(Submission(form.id))
    DB.session.add(Submission(form.id))
    DB.session.add(Submission(form.id))
    DB.session.commit()

    # submit again
    client.post(
        "/[email protected]",
        headers={"referer": "http://somewhere.com"},
        data={
            "_replyto": "*****@*****.**",
            "_next": "http://google.com",
            "name": "johannes",
            "message": "yahoo!",
        },
    )

    form = Form.query.first()
    assert form.submissions.count() == 4

    # check archived values
    submissions = form.submissions.all()

    assert 4 == len(submissions)
    assert "message" in submissions[0].data
    assert "_next" not in submissions[0].data

    # check if submissions over the limit are correctly deleted
    assert settings.ARCHIVED_SUBMISSIONS_LIMIT == 4

    client.post(
        "/[email protected]",
        headers={"referer": "http://somewhere.com"},
        data={"which-submission-is-this": "the fifth!"},
    )

    form = Form.query.first()
    assert 4 == form.submissions.count()
    newest = form.submissions.first()  # first should be the newest
    assert newest.data["which-submission-is-this"] == "the fifth!"

    client.post(
        "/[email protected]",
        headers={"referer": "http://somewhere.com"},
        data={"which-submission-is-this": "the sixth!"},
    )
    client.post(
        "/[email protected]",
        headers={"referer": "http://somewhere.com"},
        data={"which-submission-is-this": "the seventh!"},
    )

    form = Form.query.first()
    assert 4 == form.submissions.count()
    submissions = form.submissions.all()
    assert submissions[0].data["which-submission-is-this"] == "the seventh!"
    assert submissions[3].data["message"] == "yahoo!"

    #
    # try another form (to ensure that a form is not deleting wrong submissions)
    client.post(
        "/[email protected]",
        headers={"referer": "http://here.com"},
        data={"name": "send me the confirmation!"},
    )
    secondform = Form.get_with(host="here.com", email="*****@*****.**")
    assert secondform is not None

    # this form wasn't confirmed, so it still has no submissions
    assert secondform.submissions.count() == 0

    # confirm
    secondform.confirmed = True
    DB.session.add(form)
    DB.session.commit()

    # submit more times and test
    client.post(
        "/[email protected]",
        headers={"referer": "http://here.com"},
        data={"name": "leibniz"},
    )

    secondform = Form.query.filter_by(host="here.com",
                                      email="*****@*****.**").first()
    assert 1 == secondform.submissions.count()
    assert secondform.submissions.first().data["name"] == "leibniz"

    client.post(
        "/[email protected]",
        headers={"referer": "http://here.com"},
        data={"name": "schelling"},
    )

    secondform = Form.query.filter_by(host="here.com",
                                      email="*****@*****.**").first()
    assert 2 == secondform.submissions.count()
    newest, last = secondform.submissions.all()
    assert newest.data["name"] == "schelling"
    assert last.data["name"] == "leibniz"

    client.post(
        "/[email protected]",
        headers={"referer": "http://here.com"},
        data={"name": "husserl"},
    )
    client.post(
        "/[email protected]",
        headers={"referer": "http://here.com"},
        data={"name": "barban"},
    )
    client.post(
        "/[email protected]",
        headers={"referer": "http://here.com"},
        data={"name": "gliffet"},
    )

    secondform = Form.query.filter_by(host="here.com",
                                      email="*****@*****.**").first()
    assert 4 == secondform.submissions.count()
    last = secondform.submissions.order_by(Submission.id.desc()).first()
    assert last.data["name"] == "gliffet"

    # now check the previous form again
    form = Form.query.first()
    submissions = form.submissions.all()
    assert submissions[0].data["which-submission-is-this"] == "the seventh!"
    assert submissions[3].data["message"] == "yahoo!"
Esempio n. 21
0
def resend_confirmation(email):
    g.log = g.log.bind(email=email, host=request.form.get("host"))
    g.log.info("Resending confirmation.")

    if verify_captcha(request.form, request.remote_addr):
        # check if this email is listed on SendGrid's bounces
        r = requests.get(
            "https://api.sendgrid.com/api/bounces.get.json",
            params={
                "email": email,
                "api_user": settings.SENDGRID_USERNAME,
                "api_key": settings.SENDGRID_PASSWORD,
            },
        )
        if r.ok and len(r.json()) and "reason" in r.json()[0]:
            # tell the user to verify his mailbox
            reason = r.json()[0]["reason"]
            g.log.info("Email is blocked on SendGrid. Telling the user.")
            if request_wants_json():
                resp = jsonify(
                    {
                        "error": "Verify your mailbox, we can't reach it.",
                        "reason": reason,
                    }
                )
            else:
                resp = make_response(
                    render_template(
                        "info.html",
                        title="Verify the availability of your mailbox",
                        text="We encountered an error when trying to deliver the confirmation message to <b>"
                        + email
                        + "</b> at the first time we tried. For spam reasons, we will not try again until we are sure the problem is fixed. Here's the reason:</p><p><center><i>"
                        + reason
                        + "</i></center></p><p>Please make sure this problem is not happening still, then go to <a href='/unblock/"
                        + email
                        + "'>this page</a> to unblock your address.</p><p>After you have unblocked the address, please try to resend the confirmation again.</p>",
                    )
                )
            return resp
        # ~~~
        # if there's no bounce, we proceed to resend the confirmation.

        # BUG: What if this is an owned form with hashid??

        form = Form.get_with(email=email, host=request.form["host"])
        if not form:
            if request_wants_json():
                return jsonify({"error": "This form does not exist."}), 400
            else:
                return (
                    render_template(
                        "error.html",
                        title="Check email address",
                        text="This form does not exist.",
                    ),
                    400,
                )
        form.confirm_sent = False
        status = form.send_confirmation()
        if status["code"] == Form.STATUS_CONFIRMATION_SENT:
            if request_wants_json():
                return jsonify({"success": "confirmation email sent"})
            else:
                return render_template(
                    "forms/confirmation_sent.html",
                    email=email,
                    host=request.form["host"],
                    resend=status["code"] == Form.STATUS_CONFIRMATION_DUPLICATED,
                )

    # fallback response -- should happen only when the recaptcha is failed.
    g.log.warning("Failed to resend confirmation.")
    return (
        render_template(
            "error.html",
            title="Unable to send email",
            text="Please make sure you pass the <i>reCaptcha</i> test before submitting.",
        ),
        500,
    )
Esempio n. 22
0
def test_form_creation(client, msend):
    # register user
    r = client.post("/register",
                    data={
                        "email": "*****@*****.**",
                        "password": "******"
                    })
    assert r.status_code == 302
    assert 1 == User.query.count()

    # fail to create form
    r = client.post(
        "/api-int/forms",
        headers={
            "Content-type": "application/json",
            "Referer": settings.SERVICE_URL
        },
        data=json.dumps({"email": "*****@*****.**"}),
    )
    assert r.status_code == 402
    assert "error" in json.loads(r.data.decode("utf-8"))
    assert 0 == Form.query.count()

    # upgrade user manually
    user = User.query.filter_by(email="*****@*****.**").first()
    user.plan = Plan.gold
    DB.session.add(user)
    DB.session.commit()

    # verify email
    email = Email.query.filter_by(address="*****@*****.**",
                                  owner_id=user.id).first()
    email.verified = True
    DB.session.add(email)
    DB.session.commit()

    # successfully create form
    msend.reset_mock()
    r = client.post(
        "/api-int/forms",
        headers={
            "Accept": "application/json",
            "Content-type": "application/json",
            "Referer": settings.SERVICE_URL,
        },
        data=json.dumps({"email": "*****@*****.**"}),
    )

    # no email should have been sent
    assert not msend.called

    # should return success payload
    resp = json.loads(r.data.decode("utf-8"))
    assert r.status_code == 201
    assert "submission_url" in resp
    assert "hashid" in resp
    form_endpoint = resp["hashid"]
    assert resp["hashid"] in resp["submission_url"]

    # a form should now exist in the db
    assert 1 == Form.query.count()
    assert Form.query.first().id == Form.get_with(hashid=resp["hashid"]).id
    assert Form.query.first().confirmed

    # post to the form
    r = client.post(
        "/" + form_endpoint,
        headers={"Referer": "http://testsite.com"},
        data={"name": "bruce"},
        follow_redirects=True,
    )

    # Should get thank-you page
    assert "Thanks!" in r.data.decode("utf-8")
    assert "You're only one step away" not in msend.call_args[1]["text"]

    # send 5 forms (monthly limits should not apply to the gold user)
    assert settings.MONTHLY_SUBMISSIONS_LIMIT == 2
    for i in range(5):
        r = client.post(
            "/" + form_endpoint,
            headers={"Referer": "http://testsite.com"},
            data={
                "name": "ana",
                "submission": "__%s__" % i
            },
        )

    # form should now have 6 submissions
    form = Form.query.first()
    assert form.counter == 6

    # check last submission email
    assert "ana" in msend.call_args[1]["text"]
    assert "__4__" in msend.call_args[1]["text"]
    assert "past the limit" not in msend.call_args[1]["text"]

    # submit form from a different host -- this is OK now
    r = client.post(
        "/" + form_endpoint,
        headers={"Referer": "http://different.com"},
        data={"name": "permitted"},
        follow_redirects=True,
    )
    assert r.status_code == 200
    assert "permitted" in msend.call_args[1]["text"]

    # submit form without a Referer -- this is OK now
    r = client.post("/" + form_endpoint,
                    data={"name": "permitted"},
                    follow_redirects=True)
    assert r.status_code == 200
    assert "permitted" in msend.call_args[1]["text"]
    assert "unknown webpage" in msend.call_args[1]["text"]
def test_automatically_created_forms(
    client, host="somewhere.com", email="*****@*****.**"
):

    form = create_and_activate_form(
        client, host="somewhere.com", email="*****@*****.**"
    )

    # add four filler submissions
    DB.session.add(Submission(form.id))
    DB.session.add(Submission(form.id))
    DB.session.add(Submission(form.id))
    DB.session.commit()

    # submit again
    client.post(
        "/[email protected]",
        headers={"referer": "http://somewhere.com"},
        data={
            "_replyto": "*****@*****.**",
            "_next": "http://google.com",
            "name": "johannes",
            "message": "yahoo!",
        },
    )

    form = Form.query.first()
    assert form.submissions.count() == 4

    # check archived values
    submissions = form.submissions.all()

    assert 4 == len(submissions)
    assert "message" in submissions[0].data
    assert "_next" not in submissions[0].data

    # check if submissions over the limit are correctly deleted
    assert settings.ARCHIVED_SUBMISSIONS_LIMIT == 4

    client.post(
        "/[email protected]",
        headers={"referer": "http://somewhere.com"},
        data={"which-submission-is-this": "the fifth!"},
    )

    form = Form.query.first()
    assert 4 == form.submissions.count()
    newest = form.submissions.first()  # first should be the newest
    assert newest.data["which-submission-is-this"] == "the fifth!"

    client.post(
        "/[email protected]",
        headers={"referer": "http://somewhere.com"},
        data={"which-submission-is-this": "the sixth!"},
    )
    client.post(
        "/[email protected]",
        headers={"referer": "http://somewhere.com"},
        data={"which-submission-is-this": "the seventh!"},
    )

    form = Form.query.first()
    assert 4 == form.submissions.count()
    submissions = form.submissions.all()
    assert submissions[0].data["which-submission-is-this"] == "the seventh!"
    assert submissions[3].data["message"] == "yahoo!"

    #
    # try another form (to ensure that a form is not deleting wrong submissions)
    client.post(
        "/[email protected]",
        headers={"referer": "http://here.com"},
        data={"name": "send me the confirmation!"},
    )
    secondform = Form.get_with(host="here.com", email="*****@*****.**")
    assert secondform is not None

    # this form wasn't confirmed, so it still has no submissions
    assert secondform.submissions.count() == 0

    # confirm
    secondform.confirmed = True
    DB.session.add(form)
    DB.session.commit()

    # submit more times and test
    client.post(
        "/[email protected]",
        headers={"referer": "http://here.com"},
        data={"name": "leibniz"},
    )

    secondform = Form.query.filter_by(
        host="here.com", email="*****@*****.**"
    ).first()
    assert 1 == secondform.submissions.count()
    assert secondform.submissions.first().data["name"] == "leibniz"

    client.post(
        "/[email protected]",
        headers={"referer": "http://here.com"},
        data={"name": "schelling"},
    )

    secondform = Form.query.filter_by(
        host="here.com", email="*****@*****.**"
    ).first()
    assert 2 == secondform.submissions.count()
    newest, last = secondform.submissions.all()
    assert newest.data["name"] == "schelling"
    assert last.data["name"] == "leibniz"

    client.post(
        "/[email protected]",
        headers={"referer": "http://here.com"},
        data={"name": "husserl"},
    )
    client.post(
        "/[email protected]",
        headers={"referer": "http://here.com"},
        data={"name": "barban"},
    )
    client.post(
        "/[email protected]",
        headers={"referer": "http://here.com"},
        data={"name": "gliffet"},
    )

    secondform = Form.query.filter_by(
        host="here.com", email="*****@*****.**"
    ).first()
    assert 4 == secondform.submissions.count()
    last = secondform.submissions.order_by(Submission.id.desc()).first()
    assert last.data["name"] == "gliffet"

    # now check the previous form again
    form = Form.query.first()
    submissions = form.submissions.all()
    assert submissions[0].data["which-submission-is-this"] == "the seventh!"
    assert submissions[3].data["message"] == "yahoo!"
def test_grandfather_limit_and_decrease(client, msend):
    settings.GRANDFATHER_MONTHLY_LIMIT = 2
    settings.MONTHLY_SUBMISSIONS_LIMIT = 1
    settings.FORM_LIMIT_DECREASE_ACTIVATION_SEQUENCE = 1
    # the form limit should be 2 for the first form and 1 for the second

    # submit the forms
    client.post(
        "/[email protected]",
        headers={"referer": "http://somewhere.com"},
        data={"name": "john"},
    )
    form_grandfathered = Form.get_with(
        host="somewhere.com", email="*****@*****.**"
    )

    client.post(
        "/[email protected]",
        headers={"referer": "http://somewhere.com"},
        data={"name": "john"},
    )
    form_new = Form.get_with(host="somewhere.com", email="*****@*****.**")

    # confirm formS
    form_grandfathered.confirmed = True
    DB.session.add(form_grandfathered)
    form_new.confirmed = True
    DB.session.add(form_new)
    DB.session.commit()

    # submit each form 3 times
    msend.reset_mock()
    for i in range(3):
        client.post(
            "/[email protected]",
            headers={"referer": "http://somewhere.com"},
            data={"_replyto": "*****@*****.**", "name": "johann", "value": "v%s" % i},
        )

    assert len(msend.call_args_list) == 4
    assert "*****@*****.**" == msend.call_args_list[-4][1]["to"]
    assert "90%" in msend.call_args_list[-4][1]["text"]
    assert "*****@*****.**" == msend.call_args_list[-3][1]["to"]
    assert "v0" in msend.call_args_list[-3][1]["text"]
    assert "*****@*****.**" == msend.call_args_list[-2][1]["to"]
    assert "v1" in msend.call_args_list[-2][1]["text"]
    assert "*****@*****.**" == msend.call_args_list[-1][1]["to"]
    assert "limit" in msend.call_args_list[-1][1]["text"]

    msend.reset_mock()
    for i in range(3):
        client.post(
            "/[email protected]",
            headers={"referer": "http://somewhere.com"},
            data={"_replyto": "*****@*****.**", "name": "johann", "value": "v%s" % i},
        )

    assert len(msend.call_args_list) == 3
    assert "*****@*****.**" == msend.call_args_list[-3][1]["to"]
    assert "v0" in msend.call_args_list[-3][1]["text"]
    assert "*****@*****.**" == msend.call_args_list[-2][1]["to"]
    assert "limit" in msend.call_args_list[-2][1]["text"]
    assert "*****@*****.**" == msend.call_args_list[-1][1]["to"]
    assert "limit" in msend.call_args_list[-1][1]["text"]
def test_user_gets_previous_forms_assigned_to_him(client, msend):
    # verify a form for márkö@example.com
    client.post(
        u"/márkö@example.com",
        headers={"Referer": "tomatoes.com"},
        data={"name": "alice"},
    )
    f = Form.get_with(host="tomatoes.com", email="márkö@example.com")
    f.confirm_sent = True
    f.confirmed = True
    DB.session.add(f)
    DB.session.commit()

    # register márkö@example.com
    r = client.post(
        "/register", data={"email": "márkö@example.com", "password": "******"}
    )

    # confirm that the user account doesn't have access to the form
    r = client.get(
        "/api-int/forms",
        headers={"Accept": "application/json", "Referer": settings.SERVICE_URL},
    )
    forms = json.loads(r.data.decode("utf-8"))["forms"]
    assert 0 == len(forms)

    # verify user email
    link, qs = parse_confirmation_link_sent(msend.call_args[1]["text"])
    client.get(link, query_string=qs)

    # confirm that the user has no access to the form since he is not gold
    r = client.get(
        "/api-int/forms",
        headers={"Accept": "application/json", "Referer": settings.SERVICE_URL},
    )
    forms = json.loads(r.data.decode("utf-8"))["forms"]
    assert 0 == len(forms)

    # upgrade user
    user = User.query.filter_by(email="márkö@example.com").first()
    user.plan = Plan.gold
    DB.session.add(user)
    DB.session.commit()

    # confirm that the user account has access to the form
    r = client.get(
        "/api-int/forms",
        headers={"Accept": "application/json", "Referer": settings.SERVICE_URL},
    )
    forms = json.loads(r.data.decode("utf-8"))["forms"]
    assert 1 == len(forms)
    assert forms[0]["email"] == "márkö@example.com"
    assert forms[0]["host"] == "tomatoes.com"

    # verify a form for another address
    r = client.post(
        "/[email protected]", headers={"Referer": "mark.com"}, data={"name": "luke"}
    )
    f = Form.get_with(host="mark.com", email="*****@*****.**")
    f.confirm_sent = True
    f.confirmed = True
    DB.session.add(f)
    DB.session.commit()

    # confirm that the user account doesn't have access to the form
    r = client.get(
        "/api-int/forms",
        headers={"Accept": "application/json", "Referer": settings.SERVICE_URL},
    )
    forms = json.loads(r.data.decode("utf-8"))["forms"]
    assert 1 == len(forms)

    # add this other email address to user account
    client.post(
        "/api-int/account/emails",
        headers={"Content-Type": "application/json", "Referer": settings.SERVICE_URL},
        data=json.dumps({"address": "*****@*****.**"}),
    )

    link, qs = parse_confirmation_link_sent(msend.call_args[1]["text"])
    client.get(link, query_string=qs)

    # confirm that the user account now has access to the form
    r = client.get(
        "/api-int/forms",
        headers={"Accept": "application/json", "Referer": settings.SERVICE_URL},
    )
    forms = json.loads(r.data.decode("utf-8"))["forms"]
    assert 2 == len(forms)
    assert (
        forms[0]["email"] == "*****@*****.**"
    )  # forms are sorted by -id, so the newer comes first
    assert forms[0]["host"] == "mark.com"

    # create a new form spontaneously with an email already verified
    r = client.post(
        u"/márkö@example.com",
        headers={"Referer": "elsewhere.com"},
        data={"name": "luke"},
    )
    f = Form.get_with(host="elsewhere.com", email="márkö@example.com")
    f.confirm_sent = True
    f.confirmed = True
    DB.session.add(f)
    DB.session.commit()

    # confirm that the user has already accessto that form
    r = client.get(
        "/api-int/forms",
        headers={"Accept": "application/json", "Referer": settings.SERVICE_URL},
    )
    forms = json.loads(r.data.decode("utf-8"))["forms"]
    assert 3 == len(forms)
    assert forms[0]["email"] == "márkö@example.com"
    assert forms[0]["host"] == "elsewhere.com"
Esempio n. 26
0
def test_form_creation(client, msend):
    # register user
    r = client.post(
        "/register", data={"email": "*****@*****.**", "password": "******"}
    )
    assert r.status_code == 302
    assert 1 == User.query.count()

    # fail to create form
    r = client.post(
        "/api-int/forms",
        headers={"Content-type": "application/json", "Referer": settings.SERVICE_URL},
        data=json.dumps({"email": "*****@*****.**"}),
    )
    assert r.status_code == 402
    assert "error" in json.loads(r.data.decode("utf-8"))
    assert 0 == Form.query.count()

    # upgrade user manually
    user = User.query.filter_by(email="*****@*****.**").first()
    user.plan = Plan.gold
    DB.session.add(user)
    DB.session.commit()

    # verify email
    email = Email.query.filter_by(
        address="*****@*****.**", owner_id=user.id
    ).first()
    email.verified = True
    DB.session.add(email)
    DB.session.commit()

    # successfully create form
    msend.reset_mock()
    r = client.post(
        "/api-int/forms",
        headers={
            "Accept": "application/json",
            "Content-type": "application/json",
            "Referer": settings.SERVICE_URL,
        },
        data=json.dumps({"email": "*****@*****.**"}),
    )

    # no email should have been sent
    assert not msend.called

    # should return success payload
    resp = json.loads(r.data.decode("utf-8"))
    assert r.status_code == 201
    assert "submission_url" in resp
    assert "hashid" in resp
    form_endpoint = resp["hashid"]
    assert resp["hashid"] in resp["submission_url"]

    # a form should now exist in the db
    assert 1 == Form.query.count()
    assert Form.query.first().id == Form.get_with(hashid=resp["hashid"]).id
    assert Form.query.first().confirmed

    # post to the form
    r = client.post(
        "/" + form_endpoint,
        headers={"Referer": "http://testsite.com"},
        data={"name": "bruce"},
        follow_redirects=True,
    )

    # Should get thank-you page
    assert "Thanks!" in r.data.decode("utf-8")
    assert "You're only one step away" not in msend.call_args[1]["text"]

    # send 5 forms (monthly limits should not apply to the gold user)
    assert settings.MONTHLY_SUBMISSIONS_LIMIT == 2
    for i in range(5):
        r = client.post(
            "/" + form_endpoint,
            headers={"Referer": "http://testsite.com"},
            data={"name": "ana", "submission": "__%s__" % i},
        )

    # form should now have 6 submissions
    form = Form.query.first()
    assert form.counter == 6

    # check last submission email
    assert "ana" in msend.call_args[1]["text"]
    assert "__4__" in msend.call_args[1]["text"]
    assert "past the limit" not in msend.call_args[1]["text"]

    # submit form from a different host -- this is OK now
    r = client.post(
        "/" + form_endpoint,
        headers={"Referer": "http://different.com"},
        data={"name": "permitted"},
        follow_redirects=True,
    )
    assert r.status_code == 200
    assert "permitted" in msend.call_args[1]["text"]

    # submit form without a Referer -- this is OK now
    r = client.post(
        "/" + form_endpoint, data={"name": "permitted"}, follow_redirects=True
    )
    assert r.status_code == 200
    assert "permitted" in msend.call_args[1]["text"]
    assert "unknown webpage" in msend.call_args[1]["text"]
Esempio n. 27
0
def test_grandfather_limit_and_decrease(client, msend):
    settings.GRANDFATHER_MONTHLY_LIMIT = 2
    settings.MONTHLY_SUBMISSIONS_LIMIT = 1
    settings.FORM_LIMIT_DECREASE_ACTIVATION_SEQUENCE = 1
    # the form limit should be 2 for the first form and 1 for the second

    # submit the forms
    client.post(
        "/[email protected]",
        headers={"referer": "http://somewhere.com"},
        data={"name": "john"},
    )
    form_grandfathered = Form.get_with(host="somewhere.com",
                                       email="*****@*****.**")

    client.post(
        "/[email protected]",
        headers={"referer": "http://somewhere.com"},
        data={"name": "john"},
    )
    form_new = Form.get_with(host="somewhere.com", email="*****@*****.**")

    # confirm formS
    form_grandfathered.confirmed = True
    DB.session.add(form_grandfathered)
    form_new.confirmed = True
    DB.session.add(form_new)
    DB.session.commit()

    # submit each form 3 times
    msend.reset_mock()
    for i in range(3):
        client.post(
            "/[email protected]",
            headers={"referer": "http://somewhere.com"},
            data={
                "_replyto": "*****@*****.**",
                "name": "johann",
                "value": "v%s" % i
            },
        )

    assert len(msend.call_args_list) == 4
    assert "*****@*****.**" == msend.call_args_list[-4][1]["to"]
    assert "90%" in msend.call_args_list[-4][1]["text"]
    assert "*****@*****.**" == msend.call_args_list[-3][1]["to"]
    assert "v0" in msend.call_args_list[-3][1]["text"]
    assert "*****@*****.**" == msend.call_args_list[-2][1]["to"]
    assert "v1" in msend.call_args_list[-2][1]["text"]
    assert "*****@*****.**" == msend.call_args_list[-1][1]["to"]
    assert "limit" in msend.call_args_list[-1][1]["text"]

    msend.reset_mock()
    for i in range(3):
        client.post(
            "/[email protected]",
            headers={"referer": "http://somewhere.com"},
            data={
                "_replyto": "*****@*****.**",
                "name": "johann",
                "value": "v%s" % i
            },
        )

    assert len(msend.call_args_list) == 3
    assert "*****@*****.**" == msend.call_args_list[-3][1]["to"]
    assert "v0" in msend.call_args_list[-3][1]["text"]
    assert "*****@*****.**" == msend.call_args_list[-2][1]["to"]
    assert "limit" in msend.call_args_list[-2][1]["text"]
    assert "*****@*****.**" == msend.call_args_list[-1][1]["to"]
    assert "limit" in msend.call_args_list[-1][1]["text"]