摘要

  • RFC 1428 只处理一条窄路径:未经 MIME 标记的旧式八位邮件,由有权修改内容的网关送入 MIME/ESMTP 环境。文件列出了新旧系统间的多种组合,却没有声称一项转换能解决全部互通问题。
  • 网关有可靠字符集资料时,可以加入具体标签;没有时,unknown-8bit 只声明证据不足。它不代表混合字符集,不提供解码规则,也不能把局部约定变成普遍事实。
  • MIME 结构、正文传输编码、头部编码、转换轨迹、单跳能力、字节保全、最终投递和人类读懂是不同层次。格式被“升级”,不等于意义已经被确认。

“不知道”不是字段空缺

RFC 821 所描述的 SMTP 以七位传输为边界,高位会被清零。但用户写非 ASCII 邮件的需要并没有等待统一方案。全国版本的 ISO 646、ISO 8859 八位字节、个人电脑的专有编码,以及用 ISO 2022 转义序列切换字符集的日文邮件,都先在运行系统里出现了。

一些实现选择让第八位透明通过。这种办法在特定圈子里确实能用:两端私下知道采用哪套字符集,中途又没有设备改写字节。RFC 1428 直白地把条件写了出来——解释消息的上下文并不在消息里,而在一项带外的松散约定中。

所以,旧系统的成功包含两件不同的东西。一件是字节到达;另一件是收发双方仍共享如何阅读这些字节的知识。路径稳定时,两件事看似合一。只要邮件离开原圈子、进入档案、遇到转换节点,或后来的人不再知道那项约定,字节即使原封不动,文字也可能消失。

MIME 把一部分上下文搬进邮件对象:版本字段说明采用哪种结构,内容类型说明正文是什么并可附带字符集,传输编码说明正文怎样穿过受限通道。RFC 1428 面对的不是一封从头按 MIME 写成的邮件,而是已经存在、已经流通、却没有携带这些资料的旧邮件。新结构要求回答问题,旧对象未必保存答案。

六个互通情形,只修其中一个

文件把发送端分为七位、八位透明和 MIME/ESMTP,把接收端也按相应能力排列。七位发送端大体沿用原路径。八位透明发送端遇到严格七位接收端,可能被剥掉高位而改变字符。两个八位透明系统只有在共享带外约定时才能解释彼此。两个 MIME/ESMTP 系统还要求接收端支持发送端选择的字符集。

跨代方向并不对称。新系统给正文套上 Base64 或 quoted-printable,可能在传输上很安全,却让旧读者看到一团不可读的表示。旧八位系统发给新系统,则缺少 MIME 接收端期望的自描述字段。

RFC 1428 只展开后一种,也就是它表格中的第(4)种情形:八位透明发送端经转换网关进入 MIME/ESMTP 接收端。成功至少要同时满足三项条件:存在合理升级路径、网关插入的字符集标签正确、接收端支持该字符集。

表格的作用不是宣布兼容,而是约束论证。某一个格子的办法不能自动覆盖其余格子。字节损坏、格式不识别、字符集不支持和旧读者看不懂编码,是不同的失败面。

转发保管与内容改写不是同一种权力

RFC 1428 给“网关”下了一个严格定义:它是一种传输代理,同时拥有用户代理级别的权限,可以修改或转换邮件内容。

普通中继也会暂时持有邮件,但它的任务是继续运输。添加 MIME-Version、选择 Content-Type、写入 charset、重新表示正文、改变非 ASCII 头部,则是在改造对象。处在中间位置本身并不产生这种资格,文件把额外权限明确放进了网关角色。

然而,权限不产生知识。网关可以完全有权修改一封邮件,却仍不知道其中八位字节最初依据哪套编码生成。谁能行动与行动者能证明什么,必须分别回答。RFC 1428 没有让改写权顺手变成事实制造权。

新加的三个字段各自只管一件事

如果一个站点确实只使用一种已知字符集,网关可以批量把离站邮件纳入 MIME:添加 MIME 版本,将正文声明为带有该 charset 的 text/plain,再加入合适的内容传输编码。

三个字段不能相互替代:

  • MIME-Version 指明新对象遵循的结构语法;
  • Content-Type 描述正文类型,并提出字符解释;
  • Content-Transfer-Encoding 描述正文如何表示以适应传输。

8bit 不能说明语言或字符表。一个 charset 标签不能证明下一跳会接收高位字节。Base64 可以无损保存一串被错误分类的字节。邮件在语法上符合 MIME,也不能反过来证明网关选择的 charset 正确。

文件允许网关使用“现有最佳资料”,同时给这种判断划线。站点级单一标签只有在站点确实使用一种字符集时才成立。如果环境里本来就混杂多种编码,用最常见值覆盖全部邮件,只是把概率包装成了逐封邮件的事实。

unknown-8bit 保存的是证据边界

当没有可靠资料时,网关应当使用 unknown-8bit。这个值只表示网关无法可靠得知邮件所用的一种或多种字符集。

它可以覆盖任何语言、任何编码,正因为它没有规定任何字节到字符的映射。RFC 1428 还禁止继续细化这个名字。若每个站点都为同一标记暗藏一套默认解释,公共字段会重新退化为私人约定,接收端又无法知道自己面对的是哪一种“unknown”。

使用者也被限定。写信程序被假定知道自己生成文字时采用的字符集,应当明确标注。unknown-8bit 是给迁移网关的:它继承了一件缺少来源资料的旧对象,即使查找带外信息也不能确定原意。它不为有知识却省略标签的创作端开脱。

剩余选择交给邮件阅读器。人可能从字形和语言线索中判断,或选择合适的预处理器。但这只是一种可能性,不是一份成功回执。字段没有证明软件选对、用户看懂,更没有证明呈现出来的文字就是发送者的原意。

因此,charset=unknown-8bit 真正有权说明的是网关的认知状态,而不是邮件的语义状态。

正文被包好,主题行仍可能损坏

旧邮件的非 ASCII 内容不只在正文里。RFC 822 头部中的主题、注释和短语也可能包含八位字节。RFC 1428 要求这部分遵循 RFC 1342 的 encoded-word 机制。

正文可以用 Content-Transfer-Encoding: 8bit 表示。头部没有一项同等的通用许可。符合 RFC 1342 位置规则的非 ASCII 文本需要转换为 B 或 Q 形式;地址本身又有更窄的限制。

于是,一次所谓“转成 MIME”实际至少包含两条处理链:一条为正文选择类型、字符集和传输表示;另一条识别头部中的可编码文本,并用头部专用语法转换。

两条链各自可能成功或失败。正文的字节可以保全,主题行却被误判。encoded-word 语法可以完全合法,里面声明的 charset 却不正确。Q 编码对某些 ISO 8859 文字可能保持部分肉眼可辨,这也只说明表面友好,不能证明意义完整。

convert 留下“这里动过”的痕迹

RFC 1428 还要求在邮件里增加转换轨迹。示例把 convert 子句放进 Received 信息,区分转向八位、Base64 或 quoted-printable 的操作。

这样,输出对象不会悄悄冒充未曾改变的原件。后续运维者能够定位表示发生变化的边界,把某个阅读异常与某次中间处理联系起来。

轨迹仍然不是正确性证明。它不是数字签名,也不是原始字节的哈希;它不能证明 charset 选对、所有字节无损、网关得到某位用户授权,或最后有人读懂。它记录的是一个节点对自己所做操作的声明。

来源记录能缩小调查范围,不能填回转换时就缺失的资料。RFC 1428 同时保留 unknown-8bit 和 convert,正好把“我不知道原字符集”与“我确实改写了表示”分成两条事实。

从字节产生到意义恢复,要走十四级台阶

一封邮件跨过迁移边界,至少涉及以下事实:

  1. 旧创作端生成了一串字节;
  2. 旧传输没有清除第八位;
  3. 某个局部群体可能共享隐含字符集;
  4. 网关收到了对象;
  5. 网关拥有内容改写权限;
  6. 它拥有或缺少可靠 charset 资料;
  7. 它添加了 MIME 结构;
  8. 它选择正文表示;
  9. 它单独处理适用的头部;
  10. 它留下转换轨迹;
  11. 某个 ESMTP 对端在当前会话声明并接受相应能力;
  12. 结果到达阅读器;
  13. 软件或人选择一种解释;
  14. 发送者想表达的意义被恢复。

每一级都需要自己的证据。八位透明不是字符集知识;有权改写不是知道如何改写;MIME 标签不是链路能力;转换轨迹不是校验和;投递不是阅读;看起来可读也不是原意证明。

RFC 1426 管字节保全,RFC 1428 管“不知道什么”

RFC 1426 的 8BITMIME 从一件已经属于 MIME 的八位正文开始。服务器接受后,必须在投递或转发中保留每个字节的全部位。下一跳不支持扩展时,发送端要么无损转换为有效七位 MIME,要么把它当作永久错误。

RFC 1428 往前多走了一步。旧内容已经使用第八位,却还不是 MIME;字符解释存在于当地习惯,而没有进入消息字段。网关不仅要决定怎样运输,更要决定自己有资格加入哪些声明。

前一份文件建立协商后的保管义务;后一份文件阻止缺失的来源知识被包装成具体标签。两者共享技术边界,却不是同一篇历史。

史料没有提供的答案

RFC 1428 于 1993 年 2 月以 Informational 文件发布。它没有列出采用者,没有统计错误率,也没有跟踪任何具体邮件。它明确没有讨论安全问题。不能据此声称某家产品、站点或今天的邮件系统采用了这些行为。

它留下的是一种设计秩序。新的公共结构只规定需要共同理解的最小字段;迁移网关依据所在边界掌握的资料作本地决定;接收端保留以后重新解释的空间;格式只有经过运行实现才成为事实。

标准化没有强迫未知消失,而是让未知能够被准确携带。相比一项漂亮但虚构的 charset,这种克制更接近真正的互通。

来源