位置:首页 > Python > Python中用smtplib发送带附件的HTML邮件方法

Python中用smtplib发送带附件的HTML邮件方法

时间:2026-08-13  |  作者:冻月看渠  |  阅读:0

说白了,smtplib做的只是传输原始字节流,本身并不会替你处理MIME结构。要是靠手动去拼接邮件内容,boundary一旦处理失误,附件就很容易“消失”,HTML内容也可能被直接当成纯文本来解析。

更稳妥的做法,是通过email模块里的MIMEMultipart等类来构造符合RFC 2822规范的邮件体,把层级关系、编码方式、Content-Disposition头以及SMTP配置这些关键细节都设置到位。

如何在Python中使用smtplib模块发送带有附件的HTML格式邮件?

为什么直接用 smtplib.sendmail() 会丢失附件或HTML渲染?

因为 smtplib 本身不处理邮件结构,它只负责把原始字节流发出去。

如果你手动拼接 HTML 内容和附件二进制数据,很容易破坏 MIME 边界(boundary),导致收件端无法识别附件或把 HTML 当纯文本显示。

真正该用的是 email 标准库里的 MIMEMultipartMIMETextMIMEBase 等类来构造符合 RFC 2822 的多部分邮件体。

  • 必须用 MIMEMultipart("mixed") 作为根容器,再嵌套 MIMEMultipart("alternative") 放 HTML/plain 文本
  • 附件要用 MIMEApplicationMIMEBase 包装,并调用 set_payload() + encoders.encode_base64()
  • Content-Disposition: attachment 头不能漏,否则 Outlook 等客户端可能内联显示而非下载

怎么正确添加 HTML 正文和多个附件?

关键在于层级:外层 mixed → 中层 alternative(放 text/html + text/plain)→ 外层同级追加附件节点。

顺序错了,附件就变成正文的一部分。

示例片段(注意变量名和路径):

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
import smtplib

msg = MIMEMultipart("mixed")
msg["Subject"] = "测试带附件的HTML邮件"
msg["From"] = "sender@example.com"
msg["To"] = "receiver@example.com"

构造HTML正文部分

html_part = MIMEMultipart("alternative") html_body = MIMEText("

你好

这是 HTML 邮件

", "html", "utf-8") plain_body = MIMEText("这是纯文本备用内容", "plain", "utf-8") html_part.attach(plain_body) html_part.attach(html_body) msg.attach(html_part)

添加附件(假设文件在当前目录)

for file_path in ["report.pdf", "data.xlsx"]: with open(file_path, "rb") as f: part = MIMEApplication(f.read(), _subtype="pdf" if file_path.endswith(".pdf") else "vnd.openxmlformats-officedocument.spreadsheetml.sheet") part.add_header("Content-Disposition", "attachment", filename=file_path) msg.attach(part)

发送

先建立 SMTP 连接:server = smtplib.SMTP("smtp.example.com", 587),接着调用 server.starttls() 启用 TLS 加密;随后用 server.login("sender@example.com", "app_password") 完成账号登录,之后通过 server.send_message(msg) 把邮件发出去,最后再执行 server.quit() 关闭连接。

常见报错和对应修复点

smtplib.SMTPDataError: (554, b'Transaction failed') —— 多半是附件没设 Content-Disposition 或文件路径不存在;

UnicodeEncodeError: 'ascii' codec can't encode characters —— HTML 字符串没指定 charset="utf-8",或 MIMEText 初始化时漏了第三个参数;

  • 所有 MIMEText 必须显式传入 "utf-8" 编码,不能依赖默认
  • 附件文件名含中文?用 Header 类编码:from email.header import Header; part.add_header("Content-Disposition", "attachment", filename=Header("中文.pdf", "utf-8").encode())
  • Gmail 拒绝登录?改用应用专用密码(App Password),且确保账户开启两步验证

附件太大或 HTML 含图片资源怎么办?

smtplib 对单次发送的数据量没硬限制,但邮箱服务商有(Gmail 是 25MB)。

超限会直接断连,不会抛出明确异常,只会卡在 send_message() 或返回模糊错误码。

  • 超过 10MB 的附件建议转用云存储链接 + 文本说明,而非硬塞进邮件
  • HTML 里引用本地图片?不行 —— 收件方看不到。要转成内联 base64(用 MIMEImage),或托管到公网 URL
  • 避免在 HTML 中写 ,这种路径仅发件人本地有效

边界、编码、头字段、服务商限制——这四点漏掉任何一环,附件就大概率消失或 HTML 变乱码。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多