From bddb5e500a08adbc34cd24fe0f3821e23f1ab33a Mon Sep 17 00:00:00 2001 From: Son Date: Thu, 21 Apr 2022 08:59:46 +0200 Subject: [PATCH] able to handle several noreply addresses This prepares the change of noreply@simplelogin.co to noreply@simplelogin.io --- app/config.py | 3 +++ email_handler.py | 5 +++-- tests/test_email_handler.py | 28 +++++++++++++++++++++++++++- tests/test_email_utils.py | 2 +- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/app/config.py b/app/config.py index fb77039f..475a661e 100644 --- a/app/config.py +++ b/app/config.py @@ -382,6 +382,9 @@ PGP_SIGNER = os.environ.get("PGP_SIGNER") # emails that have empty From address is sent from this special reverse-alias NOREPLY = os.environ.get("NOREPLY", f"noreply@{EMAIL_DOMAIN}") +# list of no reply addresses +NOREPLIES = sl_getenv("NOREPLIES", list) or [NOREPLY] + COINBASE_WEBHOOK_SECRET = os.environ.get("COINBASE_WEBHOOK_SECRET") COINBASE_CHECKOUT_ID = os.environ.get("COINBASE_CHECKOUT_ID") COINBASE_API_KEY = os.environ.get("COINBASE_API_KEY") diff --git a/email_handler.py b/email_handler.py index 98dbeb53..b3b54550 100644 --- a/email_handler.py +++ b/email_handler.py @@ -53,7 +53,7 @@ from flanker.addresslib.address import EmailAddress from sqlalchemy.exc import IntegrityError from sqlalchemy.orm.exc import ObjectDeletedError -from app import pgp_utils, s3 +from app import pgp_utils, s3, config from app.alias_utils import try_auto_create from app.config import ( EMAIL_DOMAIN, @@ -86,6 +86,7 @@ from app.config import ( OLD_UNSUBSCRIBER, ALERT_FROM_ADDRESS_IS_REVERSE_ALIAS, ALERT_TO_NOREPLY, + NOREPLIES, ) from app.db import Session from app.handler.dmarc import ( @@ -2386,7 +2387,7 @@ def handle(envelope: Envelope, msg: Message) -> str: nb_rcpt_tos = len(rcpt_tos) for rcpt_index, rcpt_to in enumerate(rcpt_tos): - if rcpt_to == NOREPLY: + if rcpt_to in config.NOREPLIES: LOG.i("email sent to {} address from {}".format(NOREPLY, mail_from)) send_no_reply_response(mail_from, msg) return status.E200 diff --git a/tests/test_email_handler.py b/tests/test_email_handler.py index 37553967..8b7a21cc 100644 --- a/tests/test_email_handler.py +++ b/tests/test_email_handler.py @@ -6,7 +6,8 @@ import pytest from aiosmtpd.smtp import Envelope import email_handler -from app.config import EMAIL_DOMAIN, ALERT_DMARC_FAILED_REPLY_PHASE +from app import config +from app.config import EMAIL_DOMAIN, ALERT_DMARC_FAILED_REPLY_PHASE, NOREPLY from app.db import Session from app.email import headers, status from app.email_utils import generate_verp_email @@ -233,3 +234,28 @@ def test_avoid_add_to_header_already_present_in_cc(): email_handler.add_alias_to_header_if_needed(msg, alias) assert msg[headers.TO] is None assert msg[headers.CC] == alias.email + + +def test_email_sent_to_noreply(flask_client): + msg = EmailMessage() + envelope = Envelope() + envelope.mail_from = "from@domain.test" + envelope.rcpt_tos = [config.NOREPLY] + result = email_handler.handle(envelope, msg) + assert result == status.E200 + + +def test_email_sent_to_noreplies(flask_client): + msg = EmailMessage() + envelope = Envelope() + envelope.mail_from = "from@domain.test" + config.NOREPLIES = ["other-no-reply@sl.test"] + + envelope.rcpt_tos = ["other-no-reply@sl.test"] + result = email_handler.handle(envelope, msg) + assert result == status.E200 + + # NOREPLY isn't used anymore + envelope.rcpt_tos = [config.NOREPLY] + result = email_handler.handle(envelope, msg) + assert result == status.E515 diff --git a/tests/test_email_utils.py b/tests/test_email_utils.py index 40f1f66d..972b5f96 100644 --- a/tests/test_email_utils.py +++ b/tests/test_email_utils.py @@ -775,7 +775,7 @@ def test_is_invalid_mailbox_domain(flask_client): assert not is_invalid_mailbox_domain("xy.zt") -@pytest.mark.parametrize("object_id", [10**i for i in range(0, 5)]) +@pytest.mark.parametrize("object_id", [10 ** i for i in range(0, 5)]) def test_generate_verp_email(object_id): generated_email = generate_verp_email( VerpType.bounce_forward, object_id, "somewhere.net"