直接用smtplib和email标准库即可发送带附件邮件,无需额外安装;关键在于用mimemultipart容器封装、mimetext设utf-8编码、mimebase/mimeapplication处理附件并base64编码、smtp_ssl加密连接(如qq/163/gmail均需465端口),且须正确设置content-disposition头避免中文名乱码。

直接用 smtplib 和 email 标准库就能发带附件的邮件,不需要额外装包;但新手常卡在编码错误、附件乱码、SMTP 认证失败这三处。
为什么用 smtplib + email.mime 而不是第三方库?
因为 Python 自带,不用 pip install,适合刚配好环境的新手快速验证流程。第三方库如 yagmail 虽简单,但隐藏了 MIME 构建逻辑,出错时反而更难定位。
关键点:
-
email.mime.multipart.MIMEMultipart()是容器,必须用它包裹正文和附件 - 纯文本正文要用
email.mime.text.MIMEText(..., _charset="utf-8")显式指定编码 - 附件必须用
email.mime.base.MIMEBase或MIMEApplication封装,并调用encode_base64() - 不能直接把文件路径传给邮件对象——得先
open(path, "rb")读成 bytes
smtplib.SMTP_SSL 还是 smtplib.SMTP + starttls()?
国内主流邮箱(QQ、163、Gmail)现在基本只支持 SSL/TLS 加密连接。用错协议会报 Connection refused 或卡在 sendmail() 不返回。
实操建议:
- QQ 邮箱:用
smtplib.SMTP_SSL("smtp.qq.com", 465),端口必须是 465(不是 587) - 163 邮箱:同样用
SMTP_SSL("smtp.163.com", 465),注意开启 SMTP 服务并用「授权码」而非登录密码 - Gmail:用
SMTP_SSL("smtp.gmail.com", 465),需提前在 Google 账户里开启两步验证并生成应用专用密码 - 别试
SMTP("smtp.qq.com", 25)——默认端口 25 已被多数邮箱服务商禁用
附件中文名乱码或收不到附件?检查这三点
这是新手最高频的问题,根本原因在于 MIME 头部没正确声明文件名编码。
正确做法:
- 用
email.utils.formataddr()包裹发件人昵称(可选),避免发件地址被拒 - 附件的
Content-Disposition头必须用encode('utf-8')+encode('base64')双重处理,例如:part.add_header('Content-Disposition', f'attachment; filename="{os.path.basename(file_path).encode("utf-8").decode("latin-1")}"')——但这行容易出错,更稳的方式是用email.header.Header: from email.header import Header<br>part.add_header('Content-Disposition', 'attachment', filename=Header(os.path.basename(file_path), 'utf-8').encode())
另外确认:附件文件路径是真实存在的,且 Python 进程有读取权限;msg.attach(part) 别漏掉,否则附件不生效。
真正麻烦的是不同邮箱对 MIME 结构的容忍度差异——比如 QQ 邮箱会静默丢弃没有 Content-Transfer-Encoding: base64 的附件,而 Outlook 可能因换行符格式(\r\n vs \n)拒绝解析。发之前务必用自己邮箱发给自己测试,别只看控制台没报错就以为成功了。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











