SMTP发信失败主因是网关配置错误:OAuth2强制要求时smtplib不原生支持;端口与协议须匹配(587+starttls/465+SSL);HTML图片需内嵌CID引用;附件名用Header编码;连接需定期noop检测或发完即断。

SMTP连接失败:认证被拒或超时的常见原因
绝大多数发邮件失败不是代码写错了,而是网关配置没对。比如用公司邮箱发信,smtp.office365.com 要开现代身份验证(Modern Auth),但 smtplib 默认只支持基础认证(Basic Auth)——这直接导致 535 错误或连接卡死。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 优先查清你用的邮件服务商是否强制要求 OAuth2(如 Outlook/Office 365、Gmail 新账号)。如果是,
smtplib原生不支持,得换msal+graph API或退回到应用专用密码(Gmail)或启用“基本身份验证”(仅旧版 Exchange) - 端口别硬记:
587对应starttls(),465对应 SSL 封装;用错端口+协议组合会静默失败(比如连465却调starttls()) - 防火墙和代理常被忽略:内网机器发信失败,先 telnet 测试
telnet smtp.gmail.com 587是否通;不通就不是 Python 的问题
HTML 邮件正文里图片不显示?别直接写本地路径
HTML 邮件里的 <img src="file:///xxx"> 在收件端 100% 不加载——客户端根本不读本地文件。必须把图片作为内嵌资源(inline attachment)注入,并用 cid: 引用。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
MIMEMultipart('related')替代'mixed',否则 CID 无法绑定 - 图片附件要设
add_header('Content-ID', '<myimage>'),HTML 中对应写<img src="cid:myimage">(注意前后尖括号) - 避免用相对路径读图:
open('chart.png', 'rb')可能因工作目录不同而报FileNotFoundError,建议用pathlib.Path(__file__).parent / 'chart.png'
带多个附件时,中文文件名乱码或变成下划线
SMTP 协议本身不传文件名编码,靠 MIME 头里的 filename*= 字段声明编码。默认用 encode_header 或手动拼 filename="=?utf-8?b?..." 容易出错,且部分老客户端(如某些 Outlook 版本)只认 filename* 格式。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 别自己 base64 编码文件名,用
email.utils.encode_rfc2231()+Header类组合: -
from email.header import Header,然后part.add_header('Content-Disposition', 'attachment', filename=Header('报告_2024.pdf', 'utf-8').encode()) - 如果附件是生成的内存文件(如
io.BytesIO),记得在 attach 前设part.set_payload(...)并encoders.encode_base64(part),漏掉会导致内容为空
定时发信脚本跑着跑着就卡住?别让 SMTP 连接长期空闲
smtplib.SMTP 实例不会自动重连,连接空闲超过服务商心跳阈值(通常 5–30 分钟)会被服务器主动断开。下次 send_message() 时抛 SMTPServerDisconnected,但脚本若没捕获,就直接停了。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 每次发信前加简单检测:
try: server.noop() except (smtplib.SMTPServerDisconnected, ConnectionResetError): server.connect(host, port); server.starttls(); server.login(user, pwd) - 别复用一个
SMTP实例跑一整天——更稳妥的是“发一封,连一次,断一次”,虽然略慢,但稳定。高频发送场景再考虑连接池封装 - 用
atexit.register(server.quit)不可靠,进程异常退出时不一定触发;关键任务必须用try/finally包裹send_message和quit
附件名编码、CID 绑定、连接保活——这三个点只要漏一个,邮件就可能发出去但内容残缺或根本收不到。真要上生产,先拿 Outlook 和 Apple Mail 各测一遍渲染效果,别只看 Gmail。











