使用Python的email、smtplib库发送的EmailMessage在收件端显示异常
问题原因
- 你使用的163 SMTP服务器对
smtplib内置的send_message方法兼容性不佳,该方法生成的邮件头换行符不符合163服务器的预期,导致邮件头和MIME边界的换行被合并,邮件客户端无法正确识别MIME结构,就会把所有MIME内容直接当成明文展示。 - 部分场景下是因为
EmailMessage默认未在头部显式标注MIME-Version,虽然标准要求该字段自动携带,但部分国内邮件服务商要求必须显式声明。
解决方案
分两步修改代码即可修复:
- 在
add_mail方法中给msg显式添加MIME-Version头 - 将
server.send_message(msg)替换为用sendmail方法发送转成标准字符串格式的邮件内容
修改后的代码片段
add_mail方法修改
def add_mail( self, from_email="", from_name="", to_email="", to_name="", subject="", message_txt="", files=None, ): msg = EmailMessage() msg["Subject"] = subject msg["From"] = self._add_name_header(from_name, from_email) msg["To"] = self._add_name_header(to_name, to_email) # 新增:显式声明MIME版本 msg["MIME-Version"] = "1.0" msg.set_content(message_txt) # 下方原有附件处理逻辑保持不变 if not files is None: for file_obj in files: if file_obj.exists(): file = str(file_obj) ctype, encoding = mimetypes.guess_type(file) if ctype is None or encoding is not None: ctype = "application/octet-stream" maintype, subtype = ctype.split("/", 1) with file_obj.open("rb") as fp: msg.add_attachment( fp.read(), maintype=maintype, subtype=subtype, filename=file_obj.name, ) self.mails.append(msg)
send方法修改
def send(self, time_interval=1): with smtplib.SMTP_SSL( host=self.host, port=self.PORT, context=self.CONTEXT ) as server: try: server.login(user=self.username, password=self.password) except Exception as e: raise e for msg in self.mails: # 替换原有send_message为兼容更好的sendmail server.sendmail( from_addr=msg["From"], to_addrs=msg["To"], msg=msg.as_string().encode('utf-8') ) time.sleep(time_interval)
修改完成后重新发送,邮件客户端即可正常识别MIME结构,分开展示正文和附件。
内容的提问来源于stack exchange,提问作者C.K.
相关产品推荐
相关产品推荐

