摘要

  • RFC 2047 的编码词在指定邮件头位置承载非 ASCII 文字;解码成功只能说明显示转换完成,不能认证发件人。
  • 可复核证据应分别保留原始字段、结构解析、字符集解码、邮箱语法、签名覆盖范围与客户端最终呈现。

假设两封测试邮件都在界面中显示同一个带重音符号的姓名。一封用 UTF-8 字节和 Q 编码,另一封用较早的单字节字符集;也可能两封信的尖括号邮箱根本不同。联系人卡片把它们折叠成同一串字,并不表示底层字节相同、邮箱相同,更不表示背后是同一个人。

这并非协议失灵,而是 RFC 2047 所完成工作的边界。该文档由 Keith Moore 署名,发布于 1996 年,是 MIME 文档组的一部分。早期互联网邮件头以 ASCII 语法为基础,又要经过会重新折行、调整字段顺序或误解少见合法语法的软件。与此同时,读者需要在主题、注释和姓名中使用自己的文字。编码词用一层容易识别的可打印 ASCII 外壳,把这些文字带到能够解码的阅读器。

它的格式是 =?charset?encoding?encoded-text?=。字符集决定字节如何变成字符;编码最初有 Q 和 B 两类。这里的 B 使用 MIME 的 Base64 形式,Q 接近 quoted-printable,并把下划线解释为空格字节。一个完整编码词最长 75 个字符,含编码词的邮件头行最长 76 个字符;更长的内容可以拆成若干相邻编码词。

这张小小的外壳是一份表示法说明。它没有“此人已经核验”的字段。

位置限制保存了语法边界

RFC 2047 只允许编码词进入特定位置:Subject 等文本型字段、注释,以及短语中的词,例如地址前的显示名。它明确禁止编码词出现在 addr-spec、引号字符串、Received 字段和 Content-Type、Content-Disposition 的参数中,也不能任意塞入其他结构化位置。

因此,处理顺序不是细枝末节。软件先按照邮件头语法把结构化字段切成标记,再识别合法位置里的编码词,最后解码供显示。解码后出现的 @、逗号或尖括号,在视觉上可以与周围标点完全一样,却不会倒过来成为地址语法。阅读器不能把显示结果重新送入地址解析器,仿佛刚收到一份新字段。

RFC 5322 把显示名与 addr-spec 分开描述。显示名帮助人阅读,addr-spec 才是邮箱语法。该文档还区分 From 与 Sender:前者表达格式中的作者角色,后者在实际发送代理并非作者时表达发送代理。它们是消息中声明的角色,不是对人、账户控制权或组织授权的密码学证明。

如果客户端只显示姓名头像,隐藏邮箱,那是产品的呈现决策,不是两个字段已经在协议里合并。

被界面吞掉的空白

相邻编码词之间的线性空白在显示时会被忽略。这样,长名称可以为传输折行,而不会在屏幕上凭空多出一个空格。但这也说明屏幕文字不是原始邮件头的逐字抄本:折行仍存在于历史输入中,只是在呈现阶段不再可见。

每个编码词必须自包含。转义序列、字节或多字节字符不能从一个词开头、到下一个词结束。即使如此,多种合法原始形式仍可能汇入同一显示结果:不同字符集都能表示同一字符,Q 与 B 可以表达相同文字,折行位置和十六进制书写也可能不同。

同一原始形式也未必处处显示相同。客户端可能不支持某个字符集,选择展示原语法、给出替代提示或尽力渲染;对格式错误的编码词,不同实现也可能采取不同恢复策略。RFC 2047 不要求一个坏词阻止整封邮件继续处理。缺少解析器版本、字符集库和错误策略时,仅有服务端邮件头无法精确复原某位读者当时所见。

解码的目的就是消耗表示差异、交付可读文字。审计的职责则是记住哪些差异被消耗了。

直接 UTF-8 走的是另一条路

RFC 6532 后来允许在支持国际化邮件的环境中,许多邮件头字段直接携带 UTF-8。它建议使用 NFC 规范化,也提醒等价或混淆的 Unicode 表示可能带来安全影响。直接 UTF-8 省去了同一用途上的 RFC 2047 外壳,却没有让字节、码点、字形、邮箱与身份变成一件事。

现实系统常同时接收两条路径。新消息使用直接 UTF-8,旧档案和网关仍可能包含编码词。如果监控只保存最终姓名,就无法说明经历了哪条路径、哪里发生替换或规范化,也无法判断显示差异来自传输、解析还是字体。

签名所证明的不是屏幕上的面孔

RFC 6376 提供另一类证据。DKIM 对正文和签名者选择的邮件头字段进行规范化并签名,主要责任标识是签名域。验证通过能够说明受覆盖的输入在该域密钥和所选规则下保持一致。它不保证所有可见字段都被签入,也不会把解码后的个人姓名变成已核验的人类身份。

界面常把验证标记放在姓名旁边。空间距离很近,不等于语义范围扩大。要解释这个连接,记录必须指出被签的是哪一个 From 实例、哪些字段进入签名、使用何种规范化、签名域是什么、RFC 5322 解析出了哪个邮箱、RFC 2047 又把哪些位置显示成什么文字。

“签名有效”和“姓名显示正确”可以同时成立,却回答两道不同的问题。

从显示回到证据链

可复核记录从观测点和受保护的原始字段哈希开始。它列出字段顺序、折行和换行形式,解析器与解码器版本,结构标记边界,所有被识别为编码词的位置,声明字符集、Q 或 B、解码成败和替换策略。随后记录码点、规范化、文字方向或脚本告警,并把显示名与解析出的 addr-spec 放在不同字段。

认证结果在旁边自成一列:DKIM 覆盖字段、规范化、验证结果和签名域。最后一列才是用户实际看到的字符串、界面语言、字体回退和警告状态。若原始字节、软件版本或呈现环境已经丢失,结论应保留“不确定”,而不是由熟悉姓名补空白。

邮件头含有个人信息。这套记录不是无限保留的理由;采集最小化、访问控制和与决策相称的期限不可省略。

Keith Moore 的 IETF Datatracker 记录 列出了他的多项 RFC 工作。一篇由 University of Tennessee ICL 保存的 2008 年历史文章 写明,他在 1991 至 2007 年间任该校计算机科学研究人员,并从 1990 年起参与 IETF 标准化小组。这些都是带日期的背景,不能改写成现任职务。RFC 2047 的具体贡献更值得精确表述:它让国际化姓名可以被读出,同时没有假装“读得出”就是“认得准”。

来源