handle out-of-office email in addition to bounce
This commit is contained in:
parent
6c42872440
commit
385dd1e755
|
@ -1,4 +1,4 @@
|
|||
# 2** status
|
||||
# region 2** status
|
||||
E200 = "250 Message accepted for delivery"
|
||||
E201 = "250 SL E201"
|
||||
E202 = "250 Unsubscribe request accepted"
|
||||
|
@ -19,7 +19,9 @@ E210 = "250 SL E210 Yahoo complaint handled"
|
|||
E211 = "250 SL E211 Bounce Forward phase handled"
|
||||
E212 = "250 SL E212 Bounce Reply phase handled"
|
||||
|
||||
# 4** errors
|
||||
# endregion
|
||||
|
||||
# region 4** errors
|
||||
# E401 = "421 SL E401 Retry later"
|
||||
E402 = "421 SL E402 Encryption failed - Retry later"
|
||||
# E403 = "421 SL E403 Retry later"
|
||||
|
@ -27,8 +29,12 @@ E404 = "421 SL E404 Unexpected error - Retry later"
|
|||
E405 = "421 SL E405 Mailbox domain problem - Retry later"
|
||||
E406 = "421 SL E406 Retry later"
|
||||
E407 = "421 SL E407 Retry later"
|
||||
E408 = "421 SL E408 Retry later"
|
||||
E409 = "421 SL E409 Retry later"
|
||||
E410 = "421 SL E410 Retry later"
|
||||
# endregion
|
||||
|
||||
# 5** errors
|
||||
# region 5** errors
|
||||
E501 = "550 SL E501"
|
||||
E502 = "550 SL E502 Email not exist"
|
||||
E503 = "550 SL E503"
|
||||
|
@ -53,3 +59,4 @@ E522 = (
|
|||
"at a rate that prevents additional messages from being delivered."
|
||||
)
|
||||
E523 = "550 SL E523 Unknown error"
|
||||
# endregion
|
||||
|
|
115
email_handler.py
115
email_handler.py
|
@ -2051,15 +2051,26 @@ def handle(envelope: Envelope) -> str:
|
|||
LOG.d("Handle unsubscribe request from %s", mail_from)
|
||||
return handle_unsubscribe(envelope, msg)
|
||||
|
||||
# emails sent to sender. Probably bounce emails
|
||||
# emails sent to transactional VERP. Either bounce emails or out-of-office
|
||||
if (
|
||||
len(rcpt_tos) == 1
|
||||
and rcpt_tos[0].startswith(TRANSACTIONAL_BOUNCE_PREFIX)
|
||||
and rcpt_tos[0].endswith(TRANSACTIONAL_BOUNCE_SUFFIX)
|
||||
):
|
||||
LOG.d("Handle email sent to sender from %s", mail_from)
|
||||
handle_transactional_bounce(envelope, msg, rcpt_tos[0])
|
||||
return status.E205
|
||||
if is_bounce(envelope, msg):
|
||||
handle_transactional_bounce(envelope, msg, rcpt_tos[0])
|
||||
return status.E205
|
||||
elif is_automatic_out_of_office(msg):
|
||||
LOG.d(
|
||||
"Ignore out-of-office for transactional emails. Headers: %s", msg.items
|
||||
)
|
||||
return status.E206
|
||||
else:
|
||||
LOG.e(
|
||||
"cannot handle email sent to transactional VERP, saved at %s",
|
||||
save_email_for_debugging(msg), # todo: remove
|
||||
)
|
||||
return status.E408
|
||||
|
||||
if (
|
||||
len(rcpt_tos) == 1
|
||||
|
@ -2083,7 +2094,7 @@ def handle(envelope: Envelope) -> str:
|
|||
if handle_yahoo_complaint(msg):
|
||||
return status.E210
|
||||
|
||||
# Handle bounce
|
||||
# Mails sent to forward VERP, can be either bounce or out-of-office
|
||||
if (
|
||||
len(rcpt_tos) == 1
|
||||
and rcpt_tos[0].startswith(BOUNCE_PREFIX)
|
||||
|
@ -2092,20 +2103,41 @@ def handle(envelope: Envelope) -> str:
|
|||
email_log_id = parse_id_from_bounce(rcpt_tos[0])
|
||||
email_log = EmailLog.get(email_log_id)
|
||||
|
||||
# out of office is sent to the mail_from and not the From: header
|
||||
# more info on https://support.google.com/mail/thread/21246740/my-auto-reply-filter-isn-t-replying-to-original-sender-address?hl=en&msgid=21261237
|
||||
# convert the email into a normal email sent to the reverse alias
|
||||
if (
|
||||
is_automatic_out_of_office(msg)
|
||||
and msg[headers.TO] == rcpt_tos[0]
|
||||
and email_log
|
||||
):
|
||||
LOG.d("send the out-of-office email to the contact")
|
||||
rcpt_tos[0] = email_log.contact.reply_email
|
||||
msg[headers.TO] = email_log.contact.reply_email
|
||||
envelope.rcpt_tos = [email_log.contact.reply_email]
|
||||
else:
|
||||
if not email_log:
|
||||
LOG.w("No such email log")
|
||||
return status.E512
|
||||
|
||||
if is_bounce(envelope, msg):
|
||||
return handle_bounce(envelope, email_log, msg)
|
||||
elif is_automatic_out_of_office(msg):
|
||||
# convert the email into a normal email sent to the reverse alias, so it can be forwarded to contact
|
||||
LOG.d(
|
||||
"send the out-of-office email to the contact %s %s %s",
|
||||
email_log.contact,
|
||||
msg[headers.TO],
|
||||
rcpt_tos,
|
||||
)
|
||||
reverse_alias = email_log.contact.reply_email
|
||||
|
||||
rcpt_tos[0] = reverse_alias
|
||||
envelope.rcpt_tos = [reverse_alias]
|
||||
|
||||
add_or_replace_header(msg, headers.TO, reverse_alias)
|
||||
# delete reply-to header that can affect email delivery
|
||||
delete_header(msg, headers.REPLY_TO)
|
||||
|
||||
LOG.d(
|
||||
"after out-of-office transformation %s %s %s",
|
||||
msg.get_all(headers.TO),
|
||||
msg.get_all(headers.REPLY_TO),
|
||||
rcpt_tos,
|
||||
)
|
||||
else:
|
||||
LOG.e(
|
||||
"cannot handle email sent to forward VERP, saved at %s",
|
||||
save_email_for_debugging(msg),
|
||||
)
|
||||
return status.E409
|
||||
|
||||
if len(rcpt_tos) == 1 and rcpt_tos[0].startswith(
|
||||
f"{BOUNCE_PREFIX_FOR_REPLY_PHASE}+"
|
||||
|
@ -2113,19 +2145,42 @@ def handle(envelope: Envelope) -> str:
|
|||
email_log_id = parse_id_from_bounce(rcpt_tos[0])
|
||||
email_log = EmailLog.get(email_log_id)
|
||||
|
||||
# out-of-office email sent by the contact
|
||||
# convert the email into a normal email sent to the alias
|
||||
if (
|
||||
is_automatic_out_of_office(msg)
|
||||
and msg[headers.TO] == rcpt_tos[0]
|
||||
and email_log
|
||||
):
|
||||
LOG.d("send the out-of-office email to the contact")
|
||||
rcpt_tos[0] = email_log.contact.alias.email
|
||||
msg[headers.TO] = email_log.contact.alias.email
|
||||
envelope.rcpt_tos = [email_log.contact.alias.email]
|
||||
if not email_log:
|
||||
LOG.w("No such email log")
|
||||
return status.E512
|
||||
|
||||
return handle_bounce(envelope, email_log, msg)
|
||||
if is_bounce(envelope, msg):
|
||||
return handle_bounce(envelope, email_log, msg)
|
||||
elif is_automatic_out_of_office(msg):
|
||||
# convert the email into a normal email sent to the alias, so it can be forwarded to mailbox
|
||||
LOG.d(
|
||||
"send the out-of-office email to the alias %s %s %s",
|
||||
email_log.alias,
|
||||
msg[headers.TO],
|
||||
rcpt_tos,
|
||||
)
|
||||
alias_address = email_log.alias.email
|
||||
|
||||
rcpt_tos[0] = alias_address
|
||||
envelope.rcpt_tos = [alias_address]
|
||||
|
||||
replace(msg, headers.TO, alias_address)
|
||||
# delete reply-to header that can affect email delivery
|
||||
delete_header(msg, headers.REPLY_TO)
|
||||
|
||||
LOG.d(
|
||||
"after out-of-office transformation %s %s %s",
|
||||
msg.get_all(headers.TO),
|
||||
msg.get_all(headers.REPLY_TO),
|
||||
rcpt_tos,
|
||||
)
|
||||
|
||||
else:
|
||||
LOG.e(
|
||||
"cannot handle email sent to reply VERP, saved at %s",
|
||||
save_email_for_debugging(msg),
|
||||
)
|
||||
return status.E410
|
||||
|
||||
# iCloud returns the bounce with mail_from=bounce+{email_log_id}+@simplelogin.co, rcpt_to=alias
|
||||
if (
|
||||
|
|
Loading…
Reference in New Issue