def sendmail(self, from_addr: str, to_addrs: Sequence[str], msg: bytes, mail_options: List[str]=[],
rcpt_options: List[str]=[]) -> Union[str, None]:
"""
Wraps smtplib.sendmail and handles all the exceptions it can throw.
:return: a SMTP return string or None
"""
with smtplib.SMTP(self.external_ip, self.external_port) as smtp:
try:
smtp.sendmail(from_addr, to_addrs, msg, mail_options, rcpt_options)
except smtplib.SMTPSenderRefused as e:
if isinstance(e.smtp_error, bytes):
errorstr = e.smtp_error.decode("utf-8", errors="ignore")
else:
errorstr = str(e.smtp_error)
_log.info("Downstream server refused sender: %s (%s %s)", e.sender, e.smtp_code, errorstr)
return "%s %s" % (e.smtp_code, e.smtp_error)
except smtplib.SMTPResponseException as e:
# This exception baseclass is for all exceptions that have a SMTP response code.
# Return the downstream error code upstream
if isinstance(e.smtp_error, bytes):
errorstr = e.smtp_error.decode("utf-8", errors="ignore")
else:
errorstr = str(e.smtp_error)
_log.info("Unexpected response from server (passed upstream): %s %s", e.smtp_code, errorstr)
return "%s %s" % (e.smtp_code, errorstr)
except smtplib.SMTPRecipientsRefused as e:
_log.info("Some recipients where refused by the downstream server: %s", ", ".join(e.recipients.keys()))
if self.internal_ip and self.internal_port:
with smtplib.SMTP(self.internal_ip, self.internal_port) as smtp_r:
try:
smtp_r.sendmail(
"<>",
[from_addr],
self._format_denied_recipients(msg, list(e.recipients.keys()))
)
except smtplib.SMTPException as ex:
_log.exception("Error while sending denied recipients reply: %s", str(ex))
return None
except smtplib.SMTPServerDisconnected as e:
_log.info("Downstream server unexpectedly disconnected: %s", str(e))
return "421 Possible network problem. Please try again."
return None
# patch the SMTP channel implementation to pass us a reference to the channel
# and use sane logging
评论列表
文章目录