Exemplo n.º 1
0
def test_get_alias_infos_with_pagination_v3_no_duplicate_when_empty_contact(
    flask_client,
):
    """
    Make sure an alias is returned once when it has 2 contacts that have no email log activity
    """
    user = create_user(flask_client)
    alias = Alias.first()

    Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
    )

    Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
    )

    alias_infos = get_alias_infos_with_pagination_v3(user)
    assert len(alias_infos) == 1
def get_contact_by_id(contact_id):
    connection = get_connection()
    cursor = connection.cursor()
    cursor.execute("SELECT * FROM contact WHERE contact_id = ?", [contact_id.value])
    row = cursor.fetchone()
    contact = Contact.create(row[1], row[2], row[3], ContactId(row[0]), row[4])
    return contact
Exemplo n.º 3
0
def test_rate_limited_forward_phase_for_alias(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # no rate limiting for a new alias
    alias = Alias.create_new_random(user)
    db.session.commit()
    assert not rate_limited_for_alias(alias)

    # rate limit when there's a previous activity on alias
    contact = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
    )
    db.session.commit()
    for _ in range(MAX_ACTIVITY_DURING_MINUTE_PER_ALIAS + 1):
        EmailLog.create(user_id=user.id, contact_id=contact.id)
        db.session.commit()

    assert rate_limited_for_alias(alias)
Exemplo n.º 4
0
def test_alias_activities(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    Session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    Session.commit()

    alias = Alias.create_new_random(user)
    Session.commit()

    # create some alias log
    contact = Contact.create(
        website_email="*****@*****.**",
        reply_email="[email protected]",
        alias_id=alias.id,
        user_id=alias.user_id,
    )
    Session.commit()

    for _ in range(int(PAGE_LIMIT / 2)):
        EmailLog.create(
            contact_id=contact.id,
            is_reply=True,
            user_id=contact.user_id,
            alias_id=contact.alias_id,
        )

    for _ in range(int(PAGE_LIMIT / 2) + 2):
        EmailLog.create(
            contact_id=contact.id,
            blocked=True,
            user_id=contact.user_id,
            alias_id=contact.alias_id,
        )

    r = flask_client.get(
        url_for("api.get_alias_activities", alias_id=alias.id, page_id=0),
        headers={"Authentication": api_key.code},
    )

    assert r.status_code == 200
    assert len(r.json["activities"]) == PAGE_LIMIT
    for ac in r.json["activities"]:
        assert ac["from"]
        assert ac["to"]
        assert ac["timestamp"]
        assert ac["action"]
        assert ac["reverse_alias"]
        assert ac["reverse_alias_address"]

    # second page, should return 1 or 2 results only
    r = flask_client.get(
        url_for("api.get_alias_activities", alias_id=alias.id, page_id=1),
        headers={"Authentication": api_key.code},
    )
    assert len(r.json["activities"]) < 3
Exemplo n.º 5
0
def test_rate_limited_reply_phase(flask_client):
    # no rate limiting when reply_email does not exist
    assert not rate_limited_reply_phase("*****@*****.**")

    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    alias = Alias.create_new_random(user)
    db.session.commit()

    contact = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
    )
    db.session.commit()
    for _ in range(MAX_ACTIVITY_DURING_MINUTE_PER_ALIAS + 1):
        EmailLog.create(user_id=user.id, contact_id=contact.id)
        db.session.commit()

    assert rate_limited_reply_phase("*****@*****.**")
Exemplo n.º 6
0
def test_should_disable(flask_client):
    user = User.create(
        email="[email protected]",
        password="******",
        name="Test User",
        activated=True,
        include_sender_in_reverse_alias=True,
    )
    alias = Alias.create_new_random(user)
    db.session.commit()

    assert not should_disable(alias)

    # create a lot of bounce on this alias
    contact = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
        commit=True,
    )
    for _ in range(20):
        EmailLog.create(user_id=user.id,
                        contact_id=contact.id,
                        commit=True,
                        bounced=True)

    assert should_disable(alias)

    # should not affect another alias
    alias2 = Alias.create_new_random(user)
    db.session.commit()
    assert not should_disable(alias2)
Exemplo n.º 7
0
def test_website_send_to(flask_client):
    user = User.create(
        email="[email protected]",
        password="******",
        name="Test User",
        activated=True,
        commit=True,
    )

    alias = Alias.create_new_random(user)
    Session.commit()

    # non-empty name
    c1 = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="rep@SL",
        name="First Last",
    )
    assert c1.website_send_to(
    ) == '"First Last | abcd at example.com" <rep@SL>'

    # empty name, ascii website_from, easy case
    c1.name = None
    c1.website_from = "First Last <*****@*****.**>"
    assert c1.website_send_to(
    ) == '"First Last | abcd at example.com" <rep@SL>'

    # empty name, RFC 2047 website_from
    c1.name = None
    c1.website_from = "=?UTF-8?B?TmjGoW4gTmd1eeG7hW4=?= <*****@*****.**>"
    assert c1.website_send_to(
    ) == '"Nhơn Nguyễn | abcd at example.com" <rep@SL>'
Exemplo n.º 8
0
def get_or_create_contact(contact_from_header: str, mail_from: str,
                          alias: Alias) -> Contact:
    """
    contact_from_header is the RFC 2047 format FROM header
    """
    # contact_from_header can be None, use mail_from in this case instead
    contact_from_header = contact_from_header or mail_from

    # force convert header to string, sometimes contact_from_header is Header object
    contact_from_header = str(contact_from_header)

    contact_name, contact_email = parseaddr_unicode(contact_from_header)
    if not contact_email:
        # From header is wrongly formatted, try with mail_from
        LOG.warning("From header is empty, parse mail_from %s %s", mail_from,
                    alias)
        contact_name, contact_email = parseaddr_unicode(mail_from)
        if not contact_email:
            LOG.exception(
                "Cannot parse contact from from_header:%s, mail_from:%s",
                contact_from_header,
                mail_from,
            )

    contact = Contact.get_by(alias_id=alias.id, website_email=contact_email)
    if contact:
        if contact.name != contact_name:
            LOG.d(
                "Update contact %s name %s to %s",
                contact,
                contact.name,
                contact_name,
            )
            contact.name = contact_name
            db.session.commit()
    else:
        LOG.debug(
            "create contact for alias %s and contact %s",
            alias,
            contact_from_header,
        )

        reply_email = generate_reply_email()

        try:
            contact = Contact.create(
                user_id=alias.user_id,
                alias_id=alias.id,
                website_email=contact_email,
                name=contact_name,
                reply_email=reply_email,
            )
            db.session.commit()
        except IntegrityError:
            LOG.warning("Contact %s %s already exist", alias, contact_email)
            db.session.rollback()
            contact = Contact.get_by(alias_id=alias.id,
                                     website_email=contact_email)

    return contact
Exemplo n.º 9
0
def contact():
    if request.method == 'POST':
        form = ContactForm()
        form.contact_type.choices = current_app.config['CONTACT_TYPE_CHOICES']
        if form.validate_on_submit():
            vals = form.get_dict()
            vals['subject'] = current_app.config['CONTACT_SUBJECT']
            vals['ip'] = request.remote_addr
            vals['ua'] = request.headers.get('User-Agent')
            contact = Contact.create(vals)
            body = contact.to_dict()

            types = form.contact_type.choices
            body['contact_type_label'] = [ label for val, label in types\
                                    if int(val) == body['contact_type'] ][0]

            if not current_app.config['DEFAULT_TIMEZONE']:
                body['created_at_formatted'] = body['created_at'].\
                                                    strftime('%Y/%m/%d %H:%M')
            else:
                body['created_at_formatted'] = conv_dt_from_utc(
                    body['created_at'],
                    current_app.config['DEFAULT_TIMEZONE'],
                    '%Y/%m/%d %H:%M'
                )

            send_contact_email(body['email'], body['subject'], body)

        else:
            body = {'errors':form.errors}
            return jsonify(body), 400
    else:
        body = {'hoge':'fuga'}

    return jsonify(body), 200
Exemplo n.º 10
0
def test_delete_contact(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    alias = Alias.create_new_random(user)
    db.session.commit()

    contact = Contact.create(
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
        user_id=alias.user_id,
    )
    db.session.commit()

    r = flask_client.delete(
        url_for("api.delete_contact", contact_id=contact.id),
        headers={"Authentication": api_key.code},
    )

    assert r.status_code == 200
    assert r.json == {"deleted": True}
Exemplo n.º 11
0
def test_should_disable_bounces_every_day(flask_client):
    """if an alias has bounces every day at least 9 days in the last 10 days, disable alias"""
    user = login(flask_client)
    alias = Alias.create_new_random(user)
    Session.commit()

    assert not should_disable(alias)

    # create a lot of bounce on this alias
    contact = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
        commit=True,
    )
    for i in range(9):
        EmailLog.create(
            user_id=user.id,
            contact_id=contact.id,
            alias_id=contact.alias_id,
            commit=True,
            bounced=True,
            created_at=arrow.now().shift(days=-i),
        )

    assert should_disable(alias)
Exemplo n.º 12
0
def test_should_disable_bounces_account(flask_client):
    """if an account has more than 10 bounces every day for at least 5 days in the last 10 days, disable alias"""
    user = login(flask_client)
    alias = Alias.create_new_random(user)

    Session.commit()

    # create a lot of bounces on alias
    contact = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
        commit=True,
    )

    for day in range(6):
        for _ in range(10):
            EmailLog.create(
                user_id=user.id,
                contact_id=contact.id,
                alias_id=contact.alias_id,
                commit=True,
                bounced=True,
                created_at=arrow.now().shift(days=-day),
            )

    alias2 = Alias.create_new_random(user)
    assert should_disable(alias2)
Exemplo n.º 13
0
def test_should_disable_bounce_consecutive_days(flask_client):
    user = login(flask_client)
    alias = Alias.create_new_random(user)
    Session.commit()

    contact = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
        commit=True,
    )

    # create 6 bounce on this alias in the last 24h: alias is not disabled
    for _ in range(6):
        EmailLog.create(
            user_id=user.id,
            contact_id=contact.id,
            alias_id=contact.alias_id,
            commit=True,
            bounced=True,
        )
    assert not should_disable(alias)

    # create 2 bounces in the last 7 days: alias should be disabled
    for _ in range(2):
        EmailLog.create(
            user_id=user.id,
            contact_id=contact.id,
            alias_id=contact.alias_id,
            commit=True,
            bounced=True,
            created_at=arrow.now().shift(days=-3),
        )
    assert should_disable(alias)
Exemplo n.º 14
0
def test_greylisting_needed_forward_phase_for_mailbox(flask_client):
    user = User.create(
        email="[email protected]", password="******", name="Test User", activated=True
    )
    db.session.commit()

    alias = Alias.create_new_random(user)
    db.session.commit()

    contact = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
    )
    db.session.commit()
    for _ in range(MAX_ACTIVITY_DURING_MINUTE_PER_MAILBOX + 1):
        EmailLog.create(user_id=user.id, contact_id=contact.id)
        db.session.commit()

    EmailLog.create(user_id=user.id, contact_id=contact.id)

    # Create another alias with the same mailbox
    # will be greylisted as there's a previous activity on mailbox
    alias2 = Alias.create_new_random(user)
    db.session.commit()
    assert greylisting_needed_for_mailbox(alias2)
Exemplo n.º 15
0
def test_create_contact(client):
    new_contact = Contact.create(first_name='Ronald',
                                 last_name='Redacted',
                                 number='9195555555')

    assert new_contact.first_name == 'Ronald'
    assert new_contact.last_name == 'Redacted'
    assert new_contact.number == 9195555555
Exemplo n.º 16
0
def create_contact_route(alias_id):
    """
    Create contact for an alias
    Input:
        alias_id: in url
        contact: in body
    Output:
        201 if success
        409 if contact already added


    """
    data = request.get_json()
    if not data:
        return jsonify(error="request body cannot be empty"), 400

    user = g.user
    alias: Alias = Alias.get(alias_id)

    if alias.user_id != user.id:
        return jsonify(error="Forbidden"), 403

    contact_addr = data.get("contact")

    if not contact_addr:
        return jsonify(error="Contact cannot be empty"), 400

    full_address: EmailAddress = address.parse(contact_addr)
    if not full_address:
        return jsonify(error=f"invalid contact email {contact_addr}"), 400

    contact_name, contact_email = full_address.display_name, full_address.address

    contact_email = sanitize_email(contact_email, not_lower=True)

    # already been added
    contact = Contact.get_by(alias_id=alias.id, website_email=contact_email)
    if contact:
        return jsonify(**serialize_contact(contact, existed=True)), 200

    try:
        contact = Contact.create(
            user_id=alias.user_id,
            alias_id=alias.id,
            website_email=contact_email,
            name=contact_name,
            reply_email=generate_reply_email(contact_email, user),
        )
    except CannotCreateContactForReverseAlias:
        return jsonify(
            error="You can't create contact for a reverse alias"), 400

    LOG.d("create reverse-alias for %s %s", contact_addr, alias)
    Session.commit()

    return jsonify(**serialize_contact(contact)), 201
def main():
    init_db()
    rebase()
    contact = Contact.create(
        "John F Kidd",
        "0765242421",
        "*****@*****.**",
        comments="A test comment @ {}".format(time.strftime("%H:%M:%S")))

    execute = handle_error(log_error, log_info)
    execute(lambda: create_and_read(contact), get_description)
Exemplo n.º 18
0
def test_new_addr(flask_client):
    user = User.create(
        email="[email protected]",
        password="******",
        name="Test User",
        activated=True,
        commit=True,
        sender_format=1,
    )

    alias = Alias.create_new_random(user)
    db.session.commit()

    # default sender_format is 'via'
    c1 = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="rep@SL",
        name="First Last",
        commit=True,
    )
    assert c1.new_addr() == '"[email protected] via SimpleLogin" <rep@SL>'

    # set sender format = FULL
    user.sender_format = SenderFormatEnum.FULL.value
    db.session.commit()
    assert c1.new_addr() == '"First Last - [email protected]" <rep@SL>'

    # Make sure email isn't duplicated if sender name equals email
    c1.name = "*****@*****.**"
    db.session.commit()
    assert c1.new_addr() == '"*****@*****.**" <rep@SL>'

    # set sender_format = AT
    user.sender_format = SenderFormatEnum.AT.value
    c1.name = "First Last"
    db.session.commit()
    assert c1.new_addr() == '"First Last - abcd at example.com" <rep@SL>'

    # unicode name
    c1.name = "Nhơn Nguyễn"
    db.session.commit()
    assert (
        c1.new_addr()
        == "=?utf-8?q?Nh=C6=A1n_Nguy=E1=BB=85n_-_abcd_at_example=2Ecom?= <rep@SL>"
    )

    # sanity check for parseaddr_unicode
    assert parseaddr_unicode(c1.new_addr()) == (
        "Nhơn Nguyễn - abcd at example.com",
        "rep@sl",
    )
Exemplo n.º 19
0
def test_alias_contacts(flask_client):
    user = User.create(
        email="[email protected]", password="******", name="Test User", activated=True
    )
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    alias = Alias.create_new_random(user)
    db.session.commit()

    # create some alias log
    for i in range(PAGE_LIMIT + 1):
        contact = Contact.create(
            website_email=f"marketing-{i}@example.com",
            reply_email=f"reply-{i}@a.b",
            alias_id=alias.id,
            user_id=alias.user_id,
        )
        db.session.commit()

        EmailLog.create(
            contact_id=contact.id,
            is_reply=True,
            user_id=contact.user_id,
            alias_id=contact.alias_id,
        )
        db.session.commit()

    r = flask_client.get(
        url_for("api.get_alias_contacts_route", alias_id=alias.id, page_id=0),
        headers={"Authentication": api_key.code},
    )

    assert r.status_code == 200
    assert len(r.json["contacts"]) == PAGE_LIMIT
    for ac in r.json["contacts"]:
        assert ac["creation_date"]
        assert ac["creation_timestamp"]
        assert ac["last_email_sent_date"]
        assert ac["last_email_sent_timestamp"]
        assert ac["contact"]
        assert ac["reverse_alias"]
        assert ac["reverse_alias_address"]

    # second page, should return 1 result only
    r = flask_client.get(
        url_for("api.get_alias_contacts_route", alias_id=alias.id, page_id=1),
        headers={"Authentication": api_key.code},
    )
    assert len(r.json["contacts"]) == 1
Exemplo n.º 20
0
def create_contact_route(alias_id):
    """
    Create contact for an alias
    Input:
        alias_id: in url
        contact: in body
    Output:
        201 if success
        409 if contact already added


    """
    data = request.get_json()
    if not data:
        return jsonify(error="request body cannot be empty"), 400

    user = g.user
    alias: Alias = Alias.get(alias_id)

    if alias.user_id != user.id:
        return jsonify(error="Forbidden"), 403

    contact_addr = data.get("contact")

    if not contact_addr:
        return jsonify(error="Contact cannot be empty"), 400

    contact_name, contact_email = parseaddr_unicode(contact_addr)

    if not is_valid_email(contact_email):
        return jsonify(error=f"invalid contact email {contact_email}"), 400

    contact_email = sanitize_email(contact_email)

    # already been added
    contact = Contact.get_by(alias_id=alias.id, website_email=contact_email)
    if contact:
        return jsonify(**serialize_contact(contact, existed=True)), 200

    contact = Contact.create(
        user_id=alias.user_id,
        alias_id=alias.id,
        website_email=contact_email,
        name=contact_name,
        reply_email=generate_reply_email(contact_email, user),
    )

    LOG.d("create reverse-alias for %s %s", contact_addr, alias)
    db.session.commit()

    return jsonify(**serialize_contact(contact)), 201
Exemplo n.º 21
0
def create_contact_route(alias_id):
    """
    Create contact for an alias
    Input:
        alias_id: in url
        contact: in body
    Output:
        201 if success
        409 if contact already added


    """
    data = request.get_json()
    if not data:
        return jsonify(error="request body cannot be empty"), 400

    user = g.user
    alias: Alias = Alias.get(alias_id)

    if alias.user_id != user.id:
        return jsonify(error="Forbidden"), 403

    contact_addr = data.get("contact")

    # generate a reply_email, make sure it is unique
    # not use while to avoid infinite loop
    reply_email = f"ra+{random_string(25)}@{EMAIL_DOMAIN}"
    for _ in range(1000):
        reply_email = f"ra+{random_string(25)}@{EMAIL_DOMAIN}"
        if not Contact.get_by(reply_email=reply_email):
            break

    contact_name, contact_email = parseaddr_unicode(contact_addr)

    # already been added
    if Contact.get_by(alias_id=alias.id, website_email=contact_email):
        return jsonify(error="Contact already added"), 409

    contact = Contact.create(
        user_id=alias.user_id,
        alias_id=alias.id,
        website_email=contact_email,
        name=contact_name,
        reply_email=reply_email,
    )

    LOG.d("create reverse-alias for %s %s", contact_addr, alias)
    db.session.commit()

    return jsonify(**serialize_contact(contact)), 201
Exemplo n.º 22
0
 def test_contact_to_string(self):
     name_stub = "John F Kidd"
     mobile_stub = "0776666621"
     email_address_stub = "*****@*****.**"
     target = Contact.create(name_stub, mobile_stub, email_address_stub)
     expected = "\tContact\n\t{}\n\t\tName: {}\n\t\tMobile: {}\n\t\tEmail: {}\n\t\tComments: {}\n\t\tValid: {}"\
         .format(
             target.contact_id,
             target.name,
             target.mobile,
             target.email,
             target.comments,
             target.is_valid())
     actual = target.__str__()
     self.assertEqual(expected, actual)
Exemplo n.º 23
0
def test_new_addr_at_only_sender_format(flask_client):
    user = login(flask_client)
    user.sender_format = SenderFormatEnum.AT_ONLY.value
    Session.commit()
    alias = Alias.first()

    contact = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="rep@SL",
        name="First Last",
        commit=True,
    )

    assert contact.new_addr() == '"abcd at example.com" <rep@SL>'
Exemplo n.º 24
0
def test_block_contact(flask_client):
    user = login(flask_client)
    alias = Alias.first()
    contact = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="re1@SL",
        commit=True,
    )

    assert not contact.block_forward
    flask_client.post(f"/dashboard/block_contact/{contact.id}")
    assert contact.block_forward

    # make sure the page loads
    flask_client.get(f"/dashboard/block_contact/{contact.id}")
Exemplo n.º 25
0
def test_new_addr_default_sender_format(flask_client):
    user = login(flask_client)
    alias = Alias.first()

    contact = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="rep@SL",
        name="First Last",
        commit=True,
    )

    assert contact.new_addr() == '"First Last - abcd at example.com" <rep@SL>'

    # Make sure email isn't duplicated if sender name equals email
    contact.name = "*****@*****.**"
    assert contact.new_addr() == '"abcd at example.com" <rep@SL>'
Exemplo n.º 26
0
def test_toggle_contact(flask_client):
    user = login(flask_client)

    alias = Alias.create_new_random(user)
    Session.commit()

    contact = Contact.create(
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
        user_id=alias.user_id,
    )
    Session.commit()

    r = flask_client.post(f"/api/contacts/{contact.id}/toggle")

    assert r.status_code == 200
    assert r.json == {"block_forward": True}
Exemplo n.º 27
0
def test_alias_contacts(flask_client):
    user = login(flask_client)

    alias = Alias.create_new_random(user)
    Session.commit()

    # create some alias log
    for i in range(PAGE_LIMIT + 1):
        contact = Contact.create(
            website_email=f"marketing-{i}@example.com",
            reply_email=f"reply-{i}@a.b",
            alias_id=alias.id,
            user_id=alias.user_id,
        )
        Session.commit()

        EmailLog.create(
            contact_id=contact.id,
            is_reply=True,
            user_id=contact.user_id,
            alias_id=contact.alias_id,
        )
        Session.commit()

    r = flask_client.get(f"/api/aliases/{alias.id}/contacts?page_id=0")

    assert r.status_code == 200
    assert len(r.json["contacts"]) == PAGE_LIMIT
    for ac in r.json["contacts"]:
        assert ac["creation_date"]
        assert ac["creation_timestamp"]
        assert ac["last_email_sent_date"]
        assert ac["last_email_sent_timestamp"]
        assert ac["contact"]
        assert ac["reverse_alias"]
        assert ac["reverse_alias_address"]
        assert "block_forward" in ac

    # second page, should return 1 result only
    r = flask_client.get(f"/api/aliases/{alias.id}/contacts?page_id=1")
    assert len(r.json["contacts"]) == 1
Exemplo n.º 28
0
def test_new_addr_unicode(flask_client):
    user = login(flask_client)
    alias = Alias.first()

    contact = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="rep@SL",
        name="Nhơn Nguyễn",
        commit=True,
    )

    assert (
        contact.new_addr() ==
        "=?utf-8?q?Nh=C6=A1n_Nguy=E1=BB=85n_-_abcd_at_example=2Ecom?= <rep@SL>"
    )

    # sanity check
    assert parse_full_address(contact.new_addr()) == (
        "Nhơn Nguyễn - abcd at example.com",
        "rep@sl",
    )
Exemplo n.º 29
0
def fake_data():
    LOG.d("create fake data")
    # Remove db if exist
    if os.path.exists("db.sqlite"):
        LOG.d("remove existing db file")
        os.remove("db.sqlite")

    # Create all tables
    db.create_all()

    # Create a user
    user = User.create(
        email="*****@*****.**",
        name="John Wick",
        password="******",
        activated=True,
        is_admin=True,
        enable_otp=False,
        otp_secret="base32secret3232",
        intro_shown=True,
        fido_uuid=None,
    )
    user.include_sender_in_reverse_alias = None
    user.trial_end = None
    db.session.commit()

    # add a profile picture
    file_path = "profile_pic.svg"
    s3.upload_from_bytesio(
        file_path,
        open(os.path.join(ROOT_DIR, "static", "default-icon.svg"), "rb"),
        content_type="image/svg",
    )
    file = File.create(user_id=user.id, path=file_path, commit=True)
    user.profile_picture_id = file.id
    db.session.commit()

    # create a bounced email
    alias = Alias.create_new_random(user)
    db.session.commit()

    bounce_email_file_path = "bounce.eml"
    s3.upload_email_from_bytesio(
        bounce_email_file_path,
        open(os.path.join(ROOT_DIR, "local_data", "email_tests", "2.eml"),
             "rb"),
        "download.eml",
    )
    refused_email = RefusedEmail.create(
        path=bounce_email_file_path,
        full_report_path=bounce_email_file_path,
        user_id=user.id,
        commit=True,
    )

    contact = Contact.create(
        user_id=user.id,
        alias_id=alias.id,
        website_email="*****@*****.**",
        reply_email="*****@*****.**",
        commit=True,
    )
    EmailLog.create(
        user_id=user.id,
        contact_id=contact.id,
        refused_email_id=refused_email.id,
        bounced=True,
        commit=True,
    )

    LifetimeCoupon.create(code="coupon", nb_used=10, commit=True)

    # Create a subscription for user
    Subscription.create(
        user_id=user.id,
        cancel_url="https://checkout.paddle.com/subscription/cancel?user=1234",
        update_url="https://checkout.paddle.com/subscription/update?user=1234",
        subscription_id="123",
        event_time=arrow.now(),
        next_bill_date=arrow.now().shift(days=10).date(),
        plan=PlanEnum.monthly,
        commit=True,
    )

    CoinbaseSubscription.create(user_id=user.id,
                                end_at=arrow.now().shift(days=10),
                                commit=True)

    api_key = ApiKey.create(user_id=user.id, name="Chrome")
    api_key.code = "code"

    api_key = ApiKey.create(user_id=user.id, name="Firefox")
    api_key.code = "codeFF"

    pgp_public_key = open(get_abs_path("local_data/public-pgp.asc")).read()
    m1 = Mailbox.create(
        user_id=user.id,
        email="*****@*****.**",
        verified=True,
        pgp_public_key=pgp_public_key,
    )
    m1.pgp_finger_print = load_public_key(pgp_public_key)
    db.session.commit()

    for i in range(3):
        if i % 2 == 0:
            a = Alias.create(email=f"e{i}@{FIRST_ALIAS_DOMAIN}",
                             user_id=user.id,
                             mailbox_id=m1.id)
        else:
            a = Alias.create(
                email=f"e{i}@{FIRST_ALIAS_DOMAIN}",
                user_id=user.id,
                mailbox_id=user.default_mailbox_id,
            )
        db.session.commit()

        if i % 5 == 0:
            if i % 2 == 0:
                AliasMailbox.create(alias_id=a.id,
                                    mailbox_id=user.default_mailbox_id)
            else:
                AliasMailbox.create(alias_id=a.id, mailbox_id=m1.id)
        db.session.commit()

        # some aliases don't have any activity
        # if i % 3 != 0:
        #     contact = Contact.create(
        #         user_id=user.id,
        #         alias_id=a.id,
        #         website_email=f"contact{i}@example.com",
        #         reply_email=f"rep{i}@sl.local",
        #     )
        #     db.session.commit()
        #     for _ in range(3):
        #         EmailLog.create(user_id=user.id, contact_id=contact.id)
        #         db.session.commit()

        # have some disabled alias
        if i % 5 == 0:
            a.enabled = False
            db.session.commit()

    CustomDomain.create(user_id=user.id, domain="ab.cd", verified=True)
    CustomDomain.create(user_id=user.id,
                        domain="very-long-domain.com.net.org",
                        verified=True)
    db.session.commit()

    Directory.create(user_id=user.id, name="abcd")
    Directory.create(user_id=user.id, name="xyzt")
    db.session.commit()

    # Create a client
    client1 = Client.create_new(name="Demo", user_id=user.id)
    client1.oauth_client_id = "client-id"
    client1.oauth_client_secret = "client-secret"
    client1.published = True
    db.session.commit()

    RedirectUri.create(client_id=client1.id, uri="https://ab.com")

    client2 = Client.create_new(name="Demo 2", user_id=user.id)
    client2.oauth_client_id = "client-id2"
    client2.oauth_client_secret = "client-secret2"
    client2.published = True
    db.session.commit()

    ClientUser.create(user_id=user.id, client_id=client1.id, name="Fake Name")

    referral = Referral.create(user_id=user.id,
                               code="REFCODE",
                               name="First referral")
    db.session.commit()

    for i in range(6):
        Notification.create(user_id=user.id,
                            message=f"""Hey hey <b>{i}</b> """ * 10)
    db.session.commit()

    User.create(
        email="*****@*****.**",
        password="******",
        activated=True,
        referral_id=referral.id,
    )
    db.session.commit()
Exemplo n.º 30
0
def contact():
    return Contact.create(first_name='Ronald',
                          last_name='Redacted',
                          number='919-555-5555')
Exemplo n.º 31
0
 def test_contact_with_no_email_raises_expected_error(self):
     with self.assertRaises(ValueError):
         Contact.create("John F Kidd", "075535533", None, None)
Exemplo n.º 32
0
 def test_contact_with_invalid_email_address_returns_expected_value(self):
     contact_stub = Contact.create("John F Kidd", "0776666621", "j.test.com")
     actual = contact_stub.is_valid()
     self.assertFalse(actual)
Exemplo n.º 33
0
 def test_contact_with_no_mobile_raises_expected_error(self):
     with self.assertRaises(ValueError):
         Contact.create("John F Kidd", None, "*****@*****.**", None)
Exemplo n.º 34
0
def replace_header_when_forward(msg: Message, alias: Alias, header: str):
    """
    Replace CC or To header by Reply emails in forward phase
    """
    addrs = get_addrs_from_header(msg, header)

    # Nothing to do
    if not addrs:
        return

    new_addrs: [str] = []
    need_replace = False

    for addr in addrs:
        contact_name, contact_email = parseaddr_unicode(addr)

        # no transformation when alias is already in the header
        if contact_email == alias.email:
            new_addrs.append(addr)
            continue

        contact = Contact.get_by(alias_id=alias.id,
                                 website_email=contact_email)
        if contact:
            # update the contact name if needed
            if contact.name != contact_name:
                LOG.d(
                    "Update contact %s name %s to %s",
                    contact,
                    contact.name,
                    contact_name,
                )
                contact.name = contact_name
                db.session.commit()
        else:
            LOG.debug(
                "create contact for alias %s and email %s, header %s",
                alias,
                contact_email,
                header,
            )

            reply_email = generate_reply_email()

            contact = Contact.create(
                user_id=alias.user_id,
                alias_id=alias.id,
                website_email=contact_email,
                name=contact_name,
                reply_email=reply_email,
                is_cc=header.lower() == "cc",
            )
            db.session.commit()

        new_addrs.append(contact.new_addr())
        need_replace = True

    if need_replace:
        new_header = ",".join(new_addrs)
        LOG.d("Replace %s header, old: %s, new: %s", header, msg[header],
              new_header)
        add_or_replace_header(msg, header, new_header)
    else:
        LOG.d("No need to replace %s header", header)
Exemplo n.º 35
0
 def test_contact_with_empty_name_raises_expected_error(self):
     with self.assertRaises(ValueError):
         Contact.create("", "076363633", "*****@*****.**", None)
Exemplo n.º 36
0
def test_get_aliases_v2(flask_client):
    user = User.create(email="[email protected]",
                       password="******",
                       name="Test User",
                       activated=True)
    db.session.commit()

    # create api_key
    api_key = ApiKey.create(user.id, "for test")
    db.session.commit()

    a0 = Alias.create_new(user, "prefix0")
    a1 = Alias.create_new(user, "prefix1")
    db.session.commit()

    # add activity for a0
    c0 = Contact.create(
        user_id=user.id,
        alias_id=a0.id,
        website_email="*****@*****.**",
        reply_email="re0@SL",
    )
    db.session.commit()
    EmailLog.create(contact_id=c0.id, user_id=user.id)
    db.session.commit()

    # a1 has more recent activity
    c1 = Contact.create(
        user_id=user.id,
        alias_id=a1.id,
        website_email="*****@*****.**",
        reply_email="re1@SL",
    )
    db.session.commit()
    EmailLog.create(contact_id=c1.id, user_id=user.id)
    db.session.commit()

    # get aliases v2
    r = flask_client.get(
        url_for("api.get_aliases_v2", page_id=0),
        headers={"Authentication": api_key.code},
    )
    assert r.status_code == 200

    # make sure a1 is returned before a0
    r0 = r.json["aliases"][0]
    # r0 will have the following format
    # {
    #     "creation_date": "2020-04-25 21:10:01+00:00",
    #     "creation_timestamp": 1587849001,
    #     "email": "*****@*****.**",
    #     "enabled": true,
    #     "id": 3,
    #     "name": "Hey hey",
    #     "latest_activity": {
    #         "action": "forward",
    #         "contact": {
    #             "email": "*****@*****.**",
    #             "name": null,
    #             "reverse_alias": "\"c1 at example.com\" <re1@SL>"
    #         },
    #         "timestamp": 1587849001
    #     },
    #     "mailbox": {
    #         "email": "[email protected]",
    #         "id": 1
    #     },
    #     "nb_block": 0,
    #     "nb_forward": 1,
    #     "nb_reply": 0,
    #     "note": null
    # }
    assert "name" in r0
    assert r0["email"].startswith("prefix1")
    assert r0["latest_activity"]["action"] == "forward"
    assert "timestamp" in r0["latest_activity"]

    assert r0["latest_activity"]["contact"]["email"] == "*****@*****.**"
    assert "name" in r0["latest_activity"]["contact"]
    assert "reverse_alias" in r0["latest_activity"]["contact"]

    assert "id" in r0["mailbox"]
    assert "email" in r0["mailbox"]

    assert r0["mailboxes"]
    for mailbox in r0["mailboxes"]:
        assert "id" in mailbox
        assert "email" in mailbox
Exemplo n.º 37
0
def alias_contact_manager(alias_id):
    highlight_contact_id = None
    if request.args.get("highlight_contact_id"):
        highlight_contact_id = int(request.args.get("highlight_contact_id"))

    alias = Alias.get(alias_id)

    page = 0
    if request.args.get("page"):
        page = int(request.args.get("page"))

    query = request.args.get("query") or ""

    # sanity check
    if not alias:
        flash("You do not have access to this page", "warning")
        return redirect(url_for("dashboard.index"))

    if alias.user_id != current_user.id:
        flash("You do not have access to this page", "warning")
        return redirect(url_for("dashboard.index"))

    new_contact_form = NewContactForm()

    if request.method == "POST":
        if request.form.get("form-name") == "create":
            if new_contact_form.validate():
                contact_addr = new_contact_form.email.data.strip()

                try:
                    contact_name, contact_email = parseaddr_unicode(
                        contact_addr)
                    contact_email = sanitize_email(contact_email)
                except Exception:
                    flash(f"{contact_addr} is invalid", "error")
                    return redirect(
                        url_for(
                            "dashboard.alias_contact_manager",
                            alias_id=alias_id,
                        ))

                if not is_valid_email(contact_email):
                    flash(f"{contact_email} is invalid", "error")
                    return redirect(
                        url_for(
                            "dashboard.alias_contact_manager",
                            alias_id=alias_id,
                        ))

                contact = Contact.get_by(alias_id=alias.id,
                                         website_email=contact_email)
                # already been added
                if contact:
                    flash(f"{contact_email} is already added", "error")
                    return redirect(
                        url_for(
                            "dashboard.alias_contact_manager",
                            alias_id=alias_id,
                            highlight_contact_id=contact.id,
                        ))

                contact = Contact.create(
                    user_id=alias.user_id,
                    alias_id=alias.id,
                    website_email=contact_email,
                    name=contact_name,
                    reply_email=generate_reply_email(contact_email,
                                                     current_user),
                )

                LOG.d("create reverse-alias for %s", contact_addr)
                db.session.commit()
                flash(f"Reverse alias for {contact_addr} is created",
                      "success")

                return redirect(
                    url_for(
                        "dashboard.alias_contact_manager",
                        alias_id=alias_id,
                        highlight_contact_id=contact.id,
                    ))
        elif request.form.get("form-name") == "delete":
            contact_id = request.form.get("contact-id")
            contact = Contact.get(contact_id)

            if not contact:
                flash("Unknown error. Refresh the page", "warning")
                return redirect(
                    url_for("dashboard.alias_contact_manager",
                            alias_id=alias_id))
            elif contact.alias_id != alias.id:
                flash("You cannot delete reverse-alias", "warning")
                return redirect(
                    url_for("dashboard.alias_contact_manager",
                            alias_id=alias_id))

            delete_contact_email = contact.website_email
            Contact.delete(contact_id)
            db.session.commit()

            flash(f"Reverse-alias for {delete_contact_email} has been deleted",
                  "success")

            return redirect(
                url_for("dashboard.alias_contact_manager", alias_id=alias_id))

        elif request.form.get("form-name") == "search":
            query = request.form.get("query")
            return redirect(
                url_for(
                    "dashboard.alias_contact_manager",
                    alias_id=alias_id,
                    query=query,
                    highlight_contact_id=highlight_contact_id,
                ))

    contact_infos = get_contact_infos(alias, page, query=query)
    last_page = len(contact_infos) < PAGE_LIMIT

    # if highlighted contact isn't included, fetch it
    # make sure highlighted contact is at array start
    contact_ids = [contact_info.contact.id for contact_info in contact_infos]
    if highlight_contact_id and highlight_contact_id not in contact_ids:
        contact_infos = (get_contact_infos(
            alias, contact_id=highlight_contact_id, query=query) +
                         contact_infos)

    return render_template(
        "dashboard/alias_contact_manager.html",
        contact_infos=contact_infos,
        alias=alias,
        new_contact_form=new_contact_form,
        highlight_contact_id=highlight_contact_id,
        page=page,
        last_page=last_page,
        query=query,
    )
 def get_contact_by_id_stub(contact_id):
     return Contact.create("John F Kidd", "+4478866662", "*****@*****.**", contact_id)