邮件主题为什么会乱码:聊聊 RFC 2047 的 Subject 编码
【摘要】 邮件正文正常、主题却乱码,多半是 Subject 没按 RFC 2047 编码。本文介绍编码字格式、B/Q 两种编码的区别,以及用 Python 标准库正确生成与解析邮件主题的方法和常见坑。
最近在做一个自动发信的小工具时遇到一个问题:邮件正文显示正常,唯独主题里的中文在部分客户端里变成了一串以 =?UTF-8?B? 开头的乱码。其实这不是显示端的故障,而是邮件头编码方式没有处理对。
邮件头为什么不能直接写中文
邮件协议(RFC 5322)规定,邮件头字段只能使用 ASCII 字符。主题(Subject)里要放中文,就必须先编码。RFC 2047 定义了“编码字”(Encoded-Word)格式:
=?字符集?编码方式?编码后文本?=
编码方式有两种:
- B 编码:Base64,适合较长的非 ASCII 文本;
- Q 编码:类似 Quoted-Printable,适合以 ASCII 为主、夹杂少量非 ASCII 字符的文本。
例如“测试邮件”用 UTF-8 加 B 编码表示为:
=?UTF-8?B?5rWL6K+V6YKu5Lu2?=
接收端按相反顺序解码,就能还原出原文。
用 Python 正确生成主题
不要手工拼接编码字,直接用标准库:
from email.header import Header
from email.mime.text import MIMEText
msg = MIMEText("正文内容", "plain", "utf-8")
msg["Subject"] = Header("测试邮件", "utf-8")
msg["From"] = "sender@example.com"
msg["To"] = "rcpt@example.com"
Header 类会根据内容自动选择 B 编码,并按长度上限折行,避免长主题被截断或被服务器拒收。
解析收到的主题时用 decode_header:
from email.header import decode_header
parts = decode_header(msg["Subject"])
subject = "".join(
p.decode(charset or "ascii") if isinstance(p, bytes) else p
for p, charset in parts
)
几个常见坑
- 编码字之间、编码字与普通文本之间的空格在解码时会被忽略,拼接多段主题时要留意。
- 编码后的单行长度不能超过 75 个字符,长主题要折行,续行以空格开头。
- 主题里不要直接放换行符,否则有邮件头注入风险,发送前应过滤回车和换行。
小结
主题乱码大多是“该编码时没编码”或“解码时没按字符集还原”造成的。用标准库处理编码字,并注意长度与换行,就能避开绝大多数兼容问题。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)