smtp连接失败需核对服务器、端口及tls模式,国内企业邮箱多要求smtp_ssl+465端口;附件须用mimeapplication+rb模式+base64编码中文名;邮件发送必须调用send_message()或msg.as_string().encode();定时任务应使用系统级调度而非while循环。

SMTP连接失败:检查smtp_server、端口和TLS设置
大多数公司邮箱(如企业微信邮箱、阿里云邮箱、腾讯企业邮箱)不支持直接用SMTP_SSL连465端口,也不接受明文25端口;实际得看服务商文档。常见错误是硬套Gmail配置:smtp.gmail.com:587 + starttls(),但国内企业邮箱往往要求smtp.exmail.qq.com:465 + SMTP_SSL(),或者smtp.qiye.aliyun.com:465强制SSL。
实操建议:
- 先查清你邮箱域名对应的官方SMTP地址和端口(不是网页登录地址),比如腾讯企业邮箱是
smtp.exmail.qq.com,不是mail.qq.com - 用
telnet smtp.exmail.qq.com 465测试端口是否通(Windows需启用Telnet客户端);不通就别折腾代码了 - 如果用
SMTP_SSL(),不要调starttls();反之,用SMTP()连587就必须调starttls(),否则认证会报(530, b'Must issue a STARTTLS command first') - 密码不是邮箱登录密码,而是“SMTP专用密码”或“客户端授权码”——必须在邮箱后台开启并生成,且可能7天过期
附件乱码或无法打开:用MIMEMultipart正确封装二进制内容
直接把文件路径字符串塞进邮件体,或用attach(MIMEText(open(...).read()))读文本再转MIME,附件会变文字、中文名变=?utf-8?b?...编码失效、PDF/Excel打开提示损坏——根本原因是没按RFC 2045做base64编码和content-disposition头声明。
实操建议:
- 附件必须用
MIMEApplication(非文本)或MIMEBase,不能用MIMEText,哪怕文件是.txt - 读文件时务必加
rb模式:with open('report.xlsx', 'rb') as f: data = f.read() - 设文件名要用
add_header('Content-Disposition', 'attachment', filename=filename),其中filename必须是ASCII字符串;中文名要encode成utf-8再base64,例如:filename*=utf-8''%E6%97%A5%E6%8A%A5.xlsx - 整个邮件对象必须是
MIMEMultipart('mixed'),正文用MIMEText(..., 'plain', 'utf-8')子部件,附件作为另一个子部件attach()进去
发送后收件人看不到正文:别漏掉as_string()和send_message()的调用时机
很多人写完msg['From'] = ...就直接server.sendmail(..., msg),结果邮件空空如也——因为msg是MIME树结构,不是字符串;sendmail()底层需要原始RFC 5322格式字节流,而send_message()会自动调as_string()并处理换行符。
实操建议:
- 优先用
server.send_message(msg),不是sendmail(from_addr, to_addrs, msg.as_string()) - 如果非用
sendmail(),必须显式调msg.as_string().encode('utf-8'),否则中文正文会乱码(Python 3.7+默认as_string()返回str,但SMTP协议要求bytes) -
msg['To']和msg['Cc']填的是字符串,不是列表;多个收件人用', '拼接,例如'zhangsan@company.com, lisi@company.com' - 发前用
print(msg.as_string()[:500])快速扫一眼头部有没有Content-Type: multipart/mixed和boundary=字段,没有就是封装失败
定时发日报卡在凌晨:避免time.sleep()阻塞,改用系统级调度
写个while True:循环+time.sleep(3600)看似简单,但进程挂掉就停发,服务器重启也不自启,还占内存;更糟的是用schedule库在主线程里跑,遇到网络超时或附件IO卡住,整个调度就僵死。
实操建议:
- 开发阶段用
crontab -e(Linux/macOS)或任务计划程序(Windows)调Python脚本,命令形如:0 9 * * 1-5 /usr/bin/python3 /path/to/daily_report.py - 脚本开头加
#!/usr/bin/env python3和可执行权限:chmod +x daily_report.py,避免路径/环境变量问题 - 所有IO操作(读Excel、连SMTP)必须包
try/except,记录日志到文件(别只print),否则失败无声无息 - 附件生成逻辑(如用
pandas导出日报)和邮件发送逻辑要拆开:先确保report_20240520.xlsx存在且非空,再发;否则发个空表不如不发
附件名带日期、正文写明统计周期、SMTP密码存环境变量而非硬编码——这些细节比语法更重要。一旦用上企业邮箱,第一步永远不是写代码,是找IT部门要SMTP权限和授权码。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











