do not send bounce to IgnoreBounceSender

This commit is contained in:
Son Nguyen Kim 2021-08-02 11:33:58 +02:00
parent 6dac717c75
commit fb29503b81
4 changed files with 47 additions and 8 deletions

View File

@ -8,6 +8,9 @@ E205 = "250 SL E205 bounce handled"
# out of office status
E206 = "250 SL E206 Out of office"
# if mail_from is a IgnoreBounceSender, no need to send back a bounce report
E207 = "250 SL E207 No bounce report"
# 4** errors
# E401 = "421 SL E401 Retry later"
E402 = "421 SL E402 Encryption failed - Retry later"

View File

@ -58,6 +58,7 @@ from app.models import (
Alias,
EmailLog,
TransactionalEmail,
IgnoreBounceSender,
)
from app.utils import (
random_string,
@ -1213,3 +1214,11 @@ def get_queue_id(msg: Message) -> Optional[str]:
with_esmtps = received_header[search_result.start() : search_result.end()]
return with_esmtps[len("with ESMTPS id ") :]
def should_ignore_bounce(mail_from: str) -> bool:
if IgnoreBounceSender.get_by(mail_from=mail_from):
LOG.w("do not send back bounce report to %s", mail_from)
return True
return False

View File

@ -111,6 +111,7 @@ from app.email_utils import (
sl_sendmail,
sanitize_header,
get_queue_id,
should_ignore_bounce,
)
from app.extensions import db
from app.log import LOG, set_message_id
@ -540,13 +541,19 @@ def handle_forward(envelope, msg: Message, rcpt_to: str) -> List[Tuple[bool, str
alias = try_auto_create(address)
if not alias:
LOG.d("alias %s cannot be created on-the-fly, return 550", address)
return [(False, status.E515)]
if should_ignore_bounce(envelope.mail_from):
return [(True, status.E207)]
else:
return [(False, status.E515)]
user = alias.user
if user.disabled:
LOG.w("User %s disabled, disable forwarding emails for %s", user, alias)
return [(False, status.E504)]
if should_ignore_bounce(envelope.mail_from):
return [(True, status.E207)]
else:
return [(False, status.E504)]
# mail_from = envelope.mail_from
# for mb in alias.mailboxes:
@ -588,7 +595,10 @@ def handle_forward(envelope, msg: Message, rcpt_to: str) -> List[Tuple[bool, str
# no valid mailbox
if not mailboxes:
return [(False, status.E516)]
if should_ignore_bounce(envelope.mail_from):
return [(True, status.E207)]
else:
return [(False, status.E516)]
# no need to create a copy of message
for mailbox in mailboxes:
@ -618,8 +628,11 @@ def forward_email_to_mailbox(
LOG.d("Forward %s -> %s -> %s", contact, alias, mailbox)
if mailbox.disabled:
LOG.debug("%s disabled, do not forward")
return False, status.E518
LOG.d("%s disabled, do not forward")
if should_ignore_bounce(envelope.mail_from):
return True, status.E207
else:
return False, status.E518
# sanity check: make sure mailbox is not actually an alias
if get_email_domain_part(alias.email) == get_email_domain_part(mailbox.email):
@ -819,7 +832,10 @@ def forward_email_to_mailbox(
alias,
mailbox,
)
return False, status.E521
if should_ignore_bounce(envelope.mail_from):
return True, status.E207
else:
return False, status.E521
else:
db.session.commit()
return True, status.E200
@ -1707,7 +1723,10 @@ def handle(envelope: Envelope) -> str:
if rate_limited(mail_from, rcpt_tos):
LOG.w("Rate Limiting applied for mail_from:%s rcpt_tos:%s", mail_from, rcpt_tos)
return status.E522
if should_ignore_bounce(envelope.mail_from):
return status.E207
else:
return status.E522
# Handle "out of office" auto notice. An automatic response is sent for every forwarded email
# todo: remove logging

View File

@ -28,9 +28,10 @@ from app.email_utils import (
decode_text,
parse_id_from_bounce,
get_queue_id,
should_ignore_bounce,
)
from app.extensions import db
from app.models import User, CustomDomain, Alias, Contact, EmailLog
from app.models import User, CustomDomain, Alias, Contact, EmailLog, IgnoreBounceSender
# flake8: noqa: E101, W191
from tests.utils import login
@ -740,3 +741,10 @@ def test_get_queue_id():
)
assert get_queue_id(msg) == "4FxQmw1DXdz2vK2"
def test_should_ignore_bounce(flask_client):
assert not should_ignore_bounce("not-exist")
IgnoreBounceSender.create(mail_from="to-ignore@example.com")
assert should_ignore_bounce("to-ignore@example.com")