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
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)
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
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("*****@*****.**")
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)
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>'
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
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
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}
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)
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)
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)
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)
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
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)
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", )
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
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
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
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)
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>'
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}")
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>'
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}
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
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", )
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()
def contact(): return Contact.create(first_name='Ronald', last_name='Redacted', number='919-555-5555')
def test_contact_with_no_email_raises_expected_error(self): with self.assertRaises(ValueError): Contact.create("John F Kidd", "075535533", None, None)
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)
def test_contact_with_no_mobile_raises_expected_error(self): with self.assertRaises(ValueError): Contact.create("John F Kidd", None, "*****@*****.**", None)
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)
def test_contact_with_empty_name_raises_expected_error(self): with self.assertRaises(ValueError): Contact.create("", "076363633", "*****@*****.**", None)
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
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)