报告自己定时发,用 Python的smtplib 发一封带附件的邮件的简单方法
每天把一份数据报表、一份日志摘要发到邮箱,手动发迟早会忘,月底对账才发现少了好几天的。Python 标准库自带 smtplib 和 email 模块,不装任何第三方包,几行就能把文本甚至附件发出去;再挂上系统的定时任务(Linux 的 crontab、Windows 的任务计划),就彻底自动化,到点自己发。本文把"发纯文本"和"发带附件"两种都跑通。
一、发一封纯文本邮件
一封邮件本质是一段带头的文本:Subject/From/To 是头,正文是体。email 模块负责把内容组装成合规的邮件对象,smtplib 负责把它通过 SMTP 服务器发出去:
import os, smtplib
from email.mime.text import MIMEText
msg = MIMEText("今日数据已生成", "plain", "utf-8")
msg["Subject"] = "每日报表"
msg["From"] = os.environ["MAIL_USER"]
msg["To"] = "boss@example.com"
with smtplib.SMTP(os.environ["MAIL_HOST"], 587) as s:
s.starttls()
s.login(os.environ["MAIL_USER"], os.environ["MAIL_PASS"])
s.send_message(msg)
MIMEText 第一个参数是正文,“plain” 表示纯文本,“utf-8” 是编码。with 语句管连接,退出自动关。端口和加密方式要对应:25 是传统明文端口(基本不用了);587 是提交端口,连上后 starttls() 升级成加密;465 是 SSL 端口,得用 smtplib.SMTP_SSL 而不是 SMTP。多数现代邮箱用 587+starttls。
二、加附件
附件用 MIMEMultipart 当容器,正文和附件各是一"块"分别 attach 进去:
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
msg = MIMEMultipart()
msg["Subject"] = "每日报表"
msg.attach(MIMEText("见附件", "plain", "utf-8"))
with open("report.xlsx", "rb") as f:
part = MIMEApplication(f.read())
part.add_header("Content-Disposition", "attachment", filename="report.xlsx")
msg.attach(part)
MIMEMultipart 没有正文不行,所以先 attach 一段 MIMEText 当正文;附件读二进制,MIMEApplication 按"应用类型"包起来,add_header 的 Content-Disposition 告诉邮件客户端显示的文件名。要发多个附件就 open 多次、attach 多次。中文文件名在部分客户端会乱码,需要再对 filename 做 RFC 2231 编码(email 模块有 header 相关的处理),或者干脆用英文文件名最稳。
三、想发 HTML 正文
把 MIMEText 的 “plain” 换成 “html”,正文就能写带样式的 HTML,适合做得好看一点的报告:
msg = MIMEText("<h3>今日数据</h3><p>已完成</p>", "html", "utf-8")
配合 MIMEMultipart 时,正文块用 html 版、附件照加,就是一封带排版的带附件邮件。
四、几个要注意的点
第一,密码走环境变量(os.environ)别写死代码里,不然代码一进 git 凭据就泄露了。
第二,很多邮箱(Gmail、QQ、163)SMTP 不让用登录密码,要去邮箱设置里开"SMTP/IMAP"再拿一个专用"授权码"当密码用。
第三,频繁发会被服务商限流甚至判垃圾邮件,控制发送频率、用固定发件域名能降风险。
第四,生产环境别用个人邮箱发批量通知,用事务邮件服务(如 SendGrid、阿里云邮件推送)更稳、还能看送达率。
第五,send_message 抛异常要 try/catch,连不上、认证失败都得有处理,别让定时任务静默失败。
五、小结
发邮件用标准库 smtplib 就够:MIMEText 发纯文本(或 html 排版),要附件换 MIMEMultipart 把文件和正文都 attach,MIMEApplication 包二进制。端口按加密方式选 465(SSL) 或 587(starttls),密码走环境变量、邮箱服务商要授权码。挂上定时任务就能每日自动发,异常记得接住别静默失败。
- 点赞
- 收藏
- 关注作者
评论(0)