Use InvalidMailboxDomain instead of DISPOSABLE_EMAIL_DOMAINS

This commit is contained in:
Son 2022-01-03 10:33:21 +01:00
parent 4332fd3244
commit 325207d6ba
4 changed files with 59 additions and 20 deletions

View File

@ -293,12 +293,6 @@ DISPOSABLE_FILE_PATH = get_abs_path(
os.environ.get("DISPOSABLE_FILE_PATH", "local_data/local_disposable_domains.txt") os.environ.get("DISPOSABLE_FILE_PATH", "local_data/local_disposable_domains.txt")
) )
with open(get_abs_path(DISPOSABLE_FILE_PATH), "r") as f:
DISPOSABLE_EMAIL_DOMAINS = f.readlines()
DISPOSABLE_EMAIL_DOMAINS = [d.strip().lower() for d in DISPOSABLE_EMAIL_DOMAINS]
DISPOSABLE_EMAIL_DOMAINS = [
d for d in DISPOSABLE_EMAIL_DOMAINS if not d.startswith("#")
]
# Used when querying info on Apple API # Used when querying info on Apple API
# for iOS App # for iOS App

View File

@ -42,7 +42,6 @@ from app.config import (
SUPPORT_NAME, SUPPORT_NAME,
POSTFIX_SUBMISSION_TLS, POSTFIX_SUBMISSION_TLS,
MAX_NB_EMAIL_FREE_PLAN, MAX_NB_EMAIL_FREE_PLAN,
DISPOSABLE_EMAIL_DOMAINS,
MAX_ALERT_24H, MAX_ALERT_24H,
POSTFIX_PORT, POSTFIX_PORT,
URL, URL,
@ -70,6 +69,7 @@ from app.models import (
EmailLog, EmailLog,
TransactionalEmail, TransactionalEmail,
IgnoreBounceSender, IgnoreBounceSender,
InvalidMailboxDomain,
) )
from app.utils import ( from app.utils import (
random_string, random_string,
@ -548,8 +548,8 @@ def email_can_be_used_as_mailbox(email_address: str) -> bool:
LOG.d("domain %s is a SimpleLogin custom domain", domain) LOG.d("domain %s is a SimpleLogin custom domain", domain)
return False return False
if is_disposable_domain(domain): if is_invalid_mailbox_domain(domain):
LOG.d("Domain %s is disposable", domain) LOG.d("Domain %s is invalid mailbox domain", domain)
return False return False
# check if email MX domain is disposable # check if email MX domain is disposable
@ -561,19 +561,23 @@ def email_can_be_used_as_mailbox(email_address: str) -> bool:
return False return False
for mx_domain in mx_domains: for mx_domain in mx_domains:
if is_disposable_domain(mx_domain): if is_invalid_mailbox_domain(mx_domain):
LOG.d("MX Domain %s %s is disposable", mx_domain, domain) LOG.d("MX Domain %s %s is invalid mailbox domain", mx_domain, domain)
return False return False
return True return True
def is_disposable_domain(domain): def is_invalid_mailbox_domain(domain):
for d in DISPOSABLE_EMAIL_DOMAINS: """
if domain == d: Whether a domain is invalid mailbox domain
return True Also return True if `domain` is a subdomain of an invalid mailbox domain
# subdomain """
if domain.endswith("." + d): parts = domain.split(".")
for i in range(0, len(parts) - 1):
parent_domain = ".".join(parts[i:])
if InvalidMailboxDomain.get_by(domain=parent_domain):
return True return True
return False return False

View File

@ -1,7 +1,12 @@
from app.config import ALIAS_DOMAINS, PREMIUM_ALIAS_DOMAINS from app.config import (
ALIAS_DOMAINS,
PREMIUM_ALIAS_DOMAINS,
get_abs_path,
DISPOSABLE_FILE_PATH,
)
from app.db import Session from app.db import Session
from app.log import LOG from app.log import LOG
from app.models import Mailbox, Contact, SLDomain from app.models import Mailbox, Contact, SLDomain, InvalidMailboxDomain
from app.pgp_utils import load_public_key from app.pgp_utils import load_public_key
from server import create_light_app from server import create_light_app
@ -50,8 +55,25 @@ def add_sl_domains():
Session.commit() Session.commit()
def add_invalid_mailbox_domains():
with open(get_abs_path(DISPOSABLE_FILE_PATH), "r") as f:
disposable_email_domains = f.readlines()
disposable_email_domains = [d.strip().lower() for d in disposable_email_domains]
disposable_email_domains = [
d for d in disposable_email_domains if not d.startswith("#")
]
for domain in disposable_email_domains:
if InvalidMailboxDomain.get_by(domain=domain) is None:
LOG.i("Add disposable domain %s as invalid mailbox domain", domain)
InvalidMailboxDomain.create(domain=domain)
Session.commit()
if __name__ == "__main__": if __name__ == "__main__":
# wrap in an app context to benefit from app setup like database cleanup, sentry integration, etc # wrap in an app context to benefit from app setup like database cleanup, sentry integration, etc
with create_light_app().app_context(): with create_light_app().app_context():
load_pgp_public_keys() load_pgp_public_keys()
add_sl_domains() add_sl_domains()
add_invalid_mailbox_domains()

View File

@ -35,8 +35,17 @@ from app.email_utils import (
parse_full_address, parse_full_address,
get_orig_message_from_bounce, get_orig_message_from_bounce,
get_mailbox_bounce_info, get_mailbox_bounce_info,
is_invalid_mailbox_domain,
)
from app.models import (
User,
CustomDomain,
Alias,
Contact,
EmailLog,
IgnoreBounceSender,
InvalidMailboxDomain,
) )
from app.models import User, CustomDomain, Alias, Contact, EmailLog, IgnoreBounceSender
# flake8: noqa: E101, W191 # flake8: noqa: E101, W191
from tests.utils import login from tests.utils import login
@ -766,3 +775,13 @@ def test_get_mailbox_bounce_info():
orig_msg = get_mailbox_bounce_info(bounce_report) orig_msg = get_mailbox_bounce_info(bounce_report)
assert orig_msg["Final-Recipient"] == "rfc822; not-existing@gmail.com" assert orig_msg["Final-Recipient"] == "rfc822; not-existing@gmail.com"
assert orig_msg["Original-Recipient"] == "rfc822;not-existing@gmail.com" assert orig_msg["Original-Recipient"] == "rfc822;not-existing@gmail.com"
def test_is_invalid_mailbox_domain(flask_client):
InvalidMailboxDomain.create(domain="ab.cd", commit=True)
assert is_invalid_mailbox_domain("ab.cd")
assert is_invalid_mailbox_domain("sub.ab.cd")
assert is_invalid_mailbox_domain("sub1.sub2.ab.cd")
assert not is_invalid_mailbox_domain("xy.zt")