发送xml附件必须作为二进制处理,用mimeapplication设content-type=application/xml并声明charset=utf-8;mutt需-e指定content_type;powershell须手动设contenttype.mediatype;xml文件需确保编码声明一致、无多余字符、权限正确。

Python 用 smtplib 和 MIMEApplication 发 XML 附件
直接发 XML 文件,核心是别把它当纯文本塞进邮件正文——必须作为二进制附件处理,否则换行、编码、特殊字符全乱。用 MIMEApplication(不是 MIMEText)包装,Content-Type 设为 application/xml,并显式指定 charset=utf-8(即使文件本身是 UTF-8,不声明的话 Outlook 等客户端常默认 GBK 解析)。
常见错误现象:UnicodeEncodeError(读文件时没指定 encoding)、XML 内容出现在正文中而非附件里(误用 MIMEText)、收件方双击打不开(缺 charset 或后缀没设对)。
- 读文件务必加
encoding='utf-8':用open('data.xml', 'rb')读二进制更稳妥,避免隐式解码 -
add_header('Content-Disposition', 'attachment', filename='report.xml')中的filename必须带.xml后缀,否则某些邮箱会丢扩展名 - 如果 XML 里有中文且未声明 ,发出去后可能显示为乱码——发前检查文件头,或用
lxml.etree.tostring(..., encoding='utf-8', xml_declaration=True)重写输出
Shell 脚本调用 mutt 发送 XML 附件
mutt 是 Linux 下最轻量可靠的命令行邮件工具,比 mail 对附件支持更稳。关键点在于:不能只靠 -a 参数,必须配合 -e 设置 MIME 类型,否则 XML 被识别成 text/plain,Gmail 会拒收或转成正文。
使用场景:定时任务(cron)跑完数据导出 XML 后自动通知运维。
- 命令必须包含:
mutt -e "set content_type='application/xml'" -a report.xml -- recipient@example.com -
report.xml路径必须是绝对路径,cron 环境下cd不生效,相对路径大概率失败 - 若 XML 文件含非 ASCII 字符,
mutt默认用系统 locale 编码,建议在 cron 中显式设置:LANG=en_US.UTF-8 mutt ...
Windows 上用 PowerShell 的 Send-MailMessage 发 XML 附件
PowerShell 自带的 Send-MailMessage 对附件类型判断很弱,默认把 XML 当文本,容易触发反垃圾策略被拦截。必须用 -Encoding 强制指定,并手动构造 MIME 头——但该命令不支持自定义 Content-Type,所以得绕道:先用 [System.Net.Mail.Attachment] 创建附件对象,再设 ContentType.MediaType。
性能影响:每次调用都会启动 .NET 邮件栈,小文件无感,但若单次发几十个 XML,建议改用 System.Net.SmtpClient 手动复用连接。
- 别用
-Attachments 'data.xml'简写,必须用完整对象:$att = New-Object Net.Mail.Attachment('data.xml'); $att.ContentType.MediaType = 'application/xml' - PowerShell 5.1 及以下版本不支持 UTF-8 BOM 自动识别,XML 文件若带 BOM,需用
[IO.File]::ReadAllBytes()读取后传入,否则附件内容开头多出乱码 - Gmail 对来自 PowerShell 的邮件较敏感,建议在
-From中用公司域名邮箱,别用user@outlook.com直接发
附件 XML 文件本身要注意的三个细节
很多脚本能发出去,但对方打不开,问题常出在 XML 源文件上,不是发送逻辑的问题。
- 文件末尾不能有多余空行或不可见控制字符(比如 Windows 记事本保存时加的
\r\n\r\n),用xxd data.xml | head或 VS Code 的“显示空白字符”确认 - 如果 XML 是程序生成的,确保根节点前没有
print()或日志输出混入——常见于 Python 脚本调试时忘了删print('done'),导致 XML 开头多一行文本 - 文件权限要放开:
chmod 644 data.xml,否则mutt或 Python 的open()会因权限拒绝读取,报错信息却只显示“file not found”
最容易被忽略的是 XML 声明行和实际编码不一致——比如文件存为 UTF-8,但第一行写着 <?xml version="1.0" encoding="ISO-8859-1"?>,这种错不会阻断发送,但会让接收方解析失败,且查起来极隐蔽。










