Sfoglia il codice sorgente

handle SMTPRecipientsRefused in forward phase

Son NK 4 anni fa
parent
commit
c03bb70755
1 ha cambiato i file con 24 aggiunte e 12 eliminazioni
  1. 24 12
      email_handler.py

+ 24 - 12
email_handler.py

@@ -41,7 +41,7 @@ from email.mime.application import MIMEApplication
 from email.mime.multipart import MIMEMultipart
 from email.mime.multipart import MIMEMultipart
 from email.utils import parseaddr, formataddr, make_msgid
 from email.utils import parseaddr, formataddr, make_msgid
 from io import BytesIO
 from io import BytesIO
-from smtplib import SMTP
+from smtplib import SMTP, SMTPRecipientsRefused
 from typing import List, Tuple
 from typing import List, Tuple
 
 
 import aiosmtpd
 import aiosmtpd
@@ -633,16 +633,27 @@ async def forward_email_to_mailbox(
 
 
     # smtp.send_message has UnicodeEncodeErroremail issue
     # smtp.send_message has UnicodeEncodeErroremail issue
     # encode message raw directly instead
     # encode message raw directly instead
-    smtp.sendmail(
-        contact.reply_email,
-        mailbox.email,
-        msg.as_bytes(),
-        envelope.mail_options,
-        envelope.rcpt_options,
-    )
-
-    db.session.commit()
-    return True, "250 Message accepted for delivery"
+    try:
+        smtp.sendmail(
+            contact.reply_email,
+            mailbox.email,
+            msg.as_bytes(),
+            envelope.mail_options,
+            envelope.rcpt_options,
+        )
+    except SMTPRecipientsRefused:
+        # that means the mailbox is maybe invalid
+        LOG.exception(
+            "SMTPRecipientsRefused forward phase %s -> %s -> %s",
+            contact,
+            alias,
+            mailbox,
+        )
+        # return 421 so Postfix can retry later
+        return False, "421 SL E17 Retry later"
+    else:
+        db.session.commit()
+        return True, "250 Message accepted for delivery"
 
 
 
 
 async def handle_reply(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> (bool, str):
 async def handle_reply(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> (bool, str):
@@ -846,7 +857,7 @@ async def handle_reply(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> (boo
         # to not save the email_log
         # to not save the email_log
         db.session.rollback()
         db.session.rollback()
 
 
-        LOG.exception("Cannot send email from %s to %s", alias, contact)
+        LOG.warning("Cannot send email from %s to %s", alias, contact)
         send_email(
         send_email(
             mailbox.email,
             mailbox.email,
             f"Email cannot be sent to {contact.email} from {alias.email}",
             f"Email cannot be sent to {contact.email} from {alias.email}",
@@ -866,6 +877,7 @@ async def handle_reply(envelope, smtp: SMTP, msg: Message, rcpt_to: str) -> (boo
             ),
             ),
         )
         )
 
 
+    # return 250 even if error as user is already informed of the incident and can retry sending the email
     db.session.commit()
     db.session.commit()
     return True, "250 Message accepted for delivery"
     return True, "250 Message accepted for delivery"