From 2978bfb281450bfcbb8bb21a0d2f75c43b6e5823 Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Fri, 15 May 2020 23:18:30 +0200 Subject: [PATCH 1/2] Fix user cannot change personal email back and better naming. Happens when user - changes their personal email - wants to change back: they can't as this email is already used as mailbox --- app/api/views/auth.py | 10 +++++----- app/auth/views/register.py | 6 +++--- app/dashboard/views/mailbox.py | 4 ++-- app/dashboard/views/mailbox_detail.py | 4 ++-- app/dashboard/views/setting.py | 6 +++--- app/email_utils.py | 14 +++++--------- tests/test_email_utils.py | 22 +++++++++++----------- 7 files changed, 31 insertions(+), 35 deletions(-) diff --git a/app/api/views/auth.py b/app/api/views/auth.py index e85dd017..75aa54f5 100644 --- a/app/api/views/auth.py +++ b/app/api/views/auth.py @@ -12,8 +12,8 @@ from app.api.base import api_bp from app.config import FLASK_SECRET, DISABLE_REGISTRATION from app.dashboard.views.setting import send_reset_password_email from app.email_utils import ( - can_be_used_as_personal_email, - email_already_used, + email_domain_can_be_used_as_mailbox, + personal_email_already_used, send_email, render, ) @@ -84,7 +84,7 @@ def auth_register(): if DISABLE_REGISTRATION: return jsonify(error="registration is closed"), 400 - if not can_be_used_as_personal_email(email) or email_already_used(email): + if not email_domain_can_be_used_as_mailbox(email) or personal_email_already_used(email): return jsonify(error=f"cannot use {email} as personal inbox"), 400 if not password or len(password) < 8: @@ -236,7 +236,7 @@ def auth_facebook(): if not user: if DISABLE_REGISTRATION: return jsonify(error="registration is closed"), 400 - if not can_be_used_as_personal_email(email) or email_already_used(email): + if not email_domain_can_be_used_as_mailbox(email) or personal_email_already_used(email): return jsonify(error=f"cannot use {email} as personal inbox"), 400 LOG.d("create facebook user with %s", user_info) @@ -288,7 +288,7 @@ def auth_google(): if not user: if DISABLE_REGISTRATION: return jsonify(error="registration is closed"), 400 - if not can_be_used_as_personal_email(email) or email_already_used(email): + if not email_domain_can_be_used_as_mailbox(email) or personal_email_already_used(email): return jsonify(error=f"cannot use {email} as personal inbox"), 400 LOG.d("create Google user with %s", user_info) diff --git a/app/auth/views/register.py b/app/auth/views/register.py index e4caa022..ee72ef96 100644 --- a/app/auth/views/register.py +++ b/app/auth/views/register.py @@ -7,7 +7,7 @@ from app import email_utils, config from app.auth.base import auth_bp from app.auth.views.login_utils import get_referral from app.config import URL -from app.email_utils import can_be_used_as_personal_email, email_already_used +from app.email_utils import email_domain_can_be_used_as_mailbox, personal_email_already_used from app.extensions import db from app.log import LOG from app.models import User, ActivationCode @@ -37,10 +37,10 @@ def register(): if form.validate_on_submit(): email = form.email.data.strip().lower() - if not can_be_used_as_personal_email(email): + if not email_domain_can_be_used_as_mailbox(email): flash("You cannot use this email address as your personal inbox.", "error") else: - if email_already_used(email): + if personal_email_already_used(email): flash(f"Email {email} already used", "error") else: LOG.debug("create user %s", form.email.data) diff --git a/app/dashboard/views/mailbox.py b/app/dashboard/views/mailbox.py index 1174d5fe..9e02e0b1 100644 --- a/app/dashboard/views/mailbox.py +++ b/app/dashboard/views/mailbox.py @@ -8,7 +8,7 @@ from wtforms.fields.html5 import EmailField from app.config import EMAIL_DOMAIN, ALIAS_DOMAINS, MAILBOX_SECRET, URL from app.dashboard.base import dashboard_bp from app.email_utils import ( - can_be_used_as_personal_email, + email_domain_can_be_used_as_mailbox, mailbox_already_used, render, send_email, @@ -86,7 +86,7 @@ def mailbox_route(): if mailbox_already_used(mailbox_email, current_user): flash(f"{mailbox_email} already used", "error") - elif not can_be_used_as_personal_email(mailbox_email): + elif not email_domain_can_be_used_as_mailbox(mailbox_email): flash(f"You cannot use {mailbox_email}.", "error") else: new_mailbox = Mailbox.create( diff --git a/app/dashboard/views/mailbox_detail.py b/app/dashboard/views/mailbox_detail.py index b28057f2..01bb8aa8 100644 --- a/app/dashboard/views/mailbox_detail.py +++ b/app/dashboard/views/mailbox_detail.py @@ -10,7 +10,7 @@ from wtforms.fields.html5 import EmailField from app.config import ENFORCE_SPF, MAILBOX_SECRET from app.config import URL from app.dashboard.base import dashboard_bp -from app.email_utils import can_be_used_as_personal_email +from app.email_utils import email_domain_can_be_used_as_mailbox from app.email_utils import mailbox_already_used, render, send_email from app.extensions import db from app.log import LOG @@ -54,7 +54,7 @@ def mailbox_detail_route(mailbox_id): or DeletedAlias.get_by(email=new_email) ): flash(f"Email {new_email} already used", "error") - elif not can_be_used_as_personal_email(new_email): + elif not email_domain_can_be_used_as_mailbox(new_email): flash("You cannot use this email address as your mailbox", "error") else: mailbox.new_email = new_email diff --git a/app/dashboard/views/setting.py b/app/dashboard/views/setting.py index aa647112..9879cf15 100644 --- a/app/dashboard/views/setting.py +++ b/app/dashboard/views/setting.py @@ -12,7 +12,7 @@ from wtforms.fields.html5 import EmailField from app import s3, email_utils from app.config import URL from app.dashboard.base import dashboard_bp -from app.email_utils import can_be_used_as_personal_email, email_already_used +from app.email_utils import email_domain_can_be_used_as_mailbox, personal_email_already_used from app.extensions import db from app.log import LOG from app.models import ( @@ -70,12 +70,12 @@ def setting(): # check if this email is not already used if ( - email_already_used(new_email) + personal_email_already_used(new_email) or Alias.get_by(email=new_email) or DeletedAlias.get_by(email=new_email) ): flash(f"Email {new_email} already used", "error") - elif not can_be_used_as_personal_email(new_email): + elif not email_domain_can_be_used_as_mailbox(new_email): flash( "You cannot use this email address as your personal inbox.", "error", diff --git a/app/email_utils.py b/app/email_utils.py index 7dc60a03..4ddf865c 100644 --- a/app/email_utils.py +++ b/app/email_utils.py @@ -346,10 +346,11 @@ def email_belongs_to_alias_domains(address: str) -> bool: return False -def can_be_used_as_personal_email(email: str) -> bool: - """return True if an email can be used as a personal email. Currently the only condition is email domain is not +def email_domain_can_be_used_as_mailbox(email: str) -> bool: + """return True if an email can be used as a personal email. An email domain can be used if it is not - one of ALIAS_DOMAINS - one of custom domains + - disposable domain """ domain = get_email_domain_part(email) if not domain: @@ -402,17 +403,12 @@ def get_mx_domain_list(domain) -> [str]: return [d[:-1] for _, d in priority_domains] -def email_already_used(email: str) -> bool: - """test if an email can be used when: - - user signs up - - add a new mailbox +def personal_email_already_used(email: str) -> bool: + """test if an email can be used as user email """ if User.get_by(email=email): return True - if Mailbox.get_by(email=email): - return True - return False diff --git a/tests/test_email_utils.py b/tests/test_email_utils.py index c043d58f..ef2cc522 100644 --- a/tests/test_email_utils.py +++ b/tests/test_email_utils.py @@ -4,7 +4,7 @@ from app.config import MAX_ALERT_24H from app.email_utils import ( get_email_domain_part, email_belongs_to_alias_domains, - can_be_used_as_personal_email, + email_domain_can_be_used_as_mailbox, delete_header, add_or_replace_header, parseaddr_unicode, @@ -29,10 +29,10 @@ def test_email_belongs_to_alias_domains(): def test_can_be_used_as_personal_email(flask_client): # default alias domain - assert not can_be_used_as_personal_email("ab@sl.local") - assert not can_be_used_as_personal_email("hey@d1.test") + assert not email_domain_can_be_used_as_mailbox("ab@sl.local") + assert not email_domain_can_be_used_as_mailbox("hey@d1.test") - assert can_be_used_as_personal_email("hey@ab.cd") + assert email_domain_can_be_used_as_mailbox("hey@ab.cd") # custom domain user = User.create( email="a@b.c", password="password", name="Test User", activated=True @@ -40,17 +40,17 @@ def test_can_be_used_as_personal_email(flask_client): db.session.commit() CustomDomain.create(user_id=user.id, domain="ab.cd", verified=True) db.session.commit() - assert not can_be_used_as_personal_email("hey@ab.cd") + assert not email_domain_can_be_used_as_mailbox("hey@ab.cd") # disposable domain - assert not can_be_used_as_personal_email("abcd@10minutesmail.fr") - assert not can_be_used_as_personal_email("abcd@temp-mail.com") + assert not email_domain_can_be_used_as_mailbox("abcd@10minutesmail.fr") + assert not email_domain_can_be_used_as_mailbox("abcd@temp-mail.com") # subdomain will not work - assert not can_be_used_as_personal_email("abcd@sub.temp-mail.com") + assert not email_domain_can_be_used_as_mailbox("abcd@sub.temp-mail.com") # valid domains should not be affected - assert can_be_used_as_personal_email("abcd@protonmail.com") - assert can_be_used_as_personal_email("abcd@gmail.com") - assert can_be_used_as_personal_email("abcd@example.com") + assert email_domain_can_be_used_as_mailbox("abcd@protonmail.com") + assert email_domain_can_be_used_as_mailbox("abcd@gmail.com") + assert email_domain_can_be_used_as_mailbox("abcd@example.com") def test_delete_header(): From 7ed77a66b21ab8a86155a451a92f5c9005035928 Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Fri, 15 May 2020 23:18:42 +0200 Subject: [PATCH 2/2] format --- app/api/views/auth.py | 12 +++++++++--- app/auth/views/register.py | 5 ++++- app/dashboard/views/setting.py | 5 ++++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/app/api/views/auth.py b/app/api/views/auth.py index 75aa54f5..bbf150ab 100644 --- a/app/api/views/auth.py +++ b/app/api/views/auth.py @@ -84,7 +84,9 @@ def auth_register(): if DISABLE_REGISTRATION: return jsonify(error="registration is closed"), 400 - if not email_domain_can_be_used_as_mailbox(email) or personal_email_already_used(email): + if not email_domain_can_be_used_as_mailbox(email) or personal_email_already_used( + email + ): return jsonify(error=f"cannot use {email} as personal inbox"), 400 if not password or len(password) < 8: @@ -236,7 +238,9 @@ def auth_facebook(): if not user: if DISABLE_REGISTRATION: return jsonify(error="registration is closed"), 400 - if not email_domain_can_be_used_as_mailbox(email) or personal_email_already_used(email): + if not email_domain_can_be_used_as_mailbox( + email + ) or personal_email_already_used(email): return jsonify(error=f"cannot use {email} as personal inbox"), 400 LOG.d("create facebook user with %s", user_info) @@ -288,7 +292,9 @@ def auth_google(): if not user: if DISABLE_REGISTRATION: return jsonify(error="registration is closed"), 400 - if not email_domain_can_be_used_as_mailbox(email) or personal_email_already_used(email): + if not email_domain_can_be_used_as_mailbox( + email + ) or personal_email_already_used(email): return jsonify(error=f"cannot use {email} as personal inbox"), 400 LOG.d("create Google user with %s", user_info) diff --git a/app/auth/views/register.py b/app/auth/views/register.py index ee72ef96..a616771c 100644 --- a/app/auth/views/register.py +++ b/app/auth/views/register.py @@ -7,7 +7,10 @@ from app import email_utils, config from app.auth.base import auth_bp from app.auth.views.login_utils import get_referral from app.config import URL -from app.email_utils import email_domain_can_be_used_as_mailbox, personal_email_already_used +from app.email_utils import ( + email_domain_can_be_used_as_mailbox, + personal_email_already_used, +) from app.extensions import db from app.log import LOG from app.models import User, ActivationCode diff --git a/app/dashboard/views/setting.py b/app/dashboard/views/setting.py index 9879cf15..0a935667 100644 --- a/app/dashboard/views/setting.py +++ b/app/dashboard/views/setting.py @@ -12,7 +12,10 @@ from wtforms.fields.html5 import EmailField from app import s3, email_utils from app.config import URL from app.dashboard.base import dashboard_bp -from app.email_utils import email_domain_can_be_used_as_mailbox, personal_email_already_used +from app.email_utils import ( + email_domain_can_be_used_as_mailbox, + personal_email_already_used, +) from app.extensions import db from app.log import LOG from app.models import (