摘要

  • 开放式媒体类型不可能要求每个客户端理解全部 subtype;RFC 2049 因而规定了“不理解时怎样做”的共同底线。
  • 陌生传输编码、陌生字符集和陌生非文本类型都朝 application/octet-stream 退让,非文本原始字节不得直接显示给用户。
  • 文档所谓 “safe” 只涉及正确标记的数据穿过已知合规 RFC 821/822 系统,并避免二进制内容冒充屏幕文本;它不证明文件、身份、完整性、显示或结果安全。

真正困难的是怎样承认不懂

一个可扩展的命名体系每天都可能出现接收端从未见过的格式。若合规等于支持所有格式,任何客户端都会随着新名称出现而失格;若陌生内容没有统一出口,标签相同的字节又可能被打印、猜测、执行或丢弃。

RFC 2049 选择了最低行为,而不是全知。它要求合规用户代理认识 MIME 的控制面,并知道解释应在哪里停止。MIME 前几部分定义字段、传输表示、媒体家族与头部文字;第五部分把“我不认识”也变成可互操作的状态。

发送自建消息时要有 MIME-Version: 1.0。接收端要认识 Content-Transfer-Encoding,能解 quoted-printable 与 base64,也要认识 7bit、8bit、binary。底层通道不能承担 8bit 或 binary 时,发送者必须先适当编码再正确标记。标签只是逆变换的说明,不会自动修复一路上已经变掉的字节。

编码不认识,类型再熟也不能猜

最严格的退让发生在媒体解释之前。遇到陌生 Content-Transfer-Encoding,整个 MIME entity 要按 application/octet-stream 处理,不论 Content-Type 是否看起来熟悉。因为解码规则未知时,接收端尚未取得可供图片、文本或应用解释的那串 octet。

当前勘误记录补上了这个句子的隐含主语。EID 5470 指出原文在语法上仿佛让 encoding 自己带着 Content-Type,建议改为“带有陌生传输编码的 MIME entity”。它仍是 Held for Document Update,文章只能说明建议与技术含义,不能写成原 RFC 已被替换。

这条顺序把两个问题拆开:是否重建出预期字节?字节重建后是否懂得媒体声明?不能因为第二层名称熟悉,就跳过第一层的不确定。

顶层家族只买到一点知识

对 text,最低要求是显示 US-ASCII,并至少能告知用户另一种 charset 的名称。只有 charset 已知时,陌生 text subtype 才能在 canonical-to-local 转换后提供 raw view;charset 也陌生时仍退为 octet-stream。“文本”不是把未解码字节泼上屏幕的许可。

陌生 image、audio、video subtype 至少按 octet-stream 处理。application 若用了 quoted-printable 或 base64,接收端要能去掉编码并把结果放入用户文件。这是保管能力,不是执行指令。RFC 2046 还提醒,把陌生图片交给通用查看器,会继承该查看器最危险格式的安全问题。

复合类型另有最小动作:识别 multipart/mixed、alternative、digest;陌生 multipart subtype 当 mixed。递归识别 message/rfc822;陌生 message subtype 当 octet-stream。完全陌生的 Content-Type 也降格为无参数 octet-stream。保存文件或让用户指定程序只是本地选项,并非自动运行授权。

“安全”只到屏幕边缘

列完十项要求后,RFC 2049 才解释 MIME-conformant 的意义。正确标记的数据被称为可安全发送,是因为系统至少会把它当作不透明二进制,不会直接泼到毫无准备的用户屏幕上。另一层 “safe” 是:任何已知且符合 RFC 821 与 RFC 822 的系统,既不会被这种数据破坏,也不会破坏这种数据。

这两句话都很窄。不透明字节仍可能恶意;被选择的程序仍可能有漏洞;正确解码可以得到用户无权或无意打开的内容;消息可以伪造、截断或在到达前被不合规中继改写。合规标签陈述最低能力,并不记录某个产品真的执行了每一步。

成功显示也不是承诺。陌生 charset 只告知名称就可能合规;陌生 subtype 能保存即可。这个体系保留了有用的拒绝。

坏现实不是规范许可

RFC 2049 同时承认当时的邮件网并不整齐:许多广泛部署但不合规的 MTA 会按本机存储结构改写消息,或者干脆损坏消息。NUL、TAB、尾随空格、长行、非 invariant 字符、单独一行的句点与行首 From 都可能变化。base64 符合最窄的可移植字符与行规则;quoted-printable 只能穿过大多数而非全部文档所说的 gateway。

文档紧接着强调:这些不是对 MTA 的建议。RFC 821 禁止改写空白或折行;它们是 BAD、invalid、却真实存在的实践。发送端可以为坏现实做防御,却不能把坏现实洗成协议允许。

因此,规范义务、对合规系统的假设、对不合规系统的防御建议与实际部署证据必须分开。一份 RFC 不能证明某个客户端怎样处理过一封邮件。

状态与勘误也是边界

RFC Editor 当前信息页把 RFC 2049 标作 Draft Standard;原文写 Standards Track,日期为 1996 年 11 月。这个出版记录证明规范身份,不证明部署规模。

Verified 的 EID 3933 修正第十项的交叉引用:它应指向 RFC 822 的 word grammar 与 RFC 2047 的 encoded-word 识别规则,而不是 RFC 2049 第四节。修正只让语法链更准确,不会把显示用 encoded-word 变成发送者身份或路由地址。

RFC 2049 真正留下的是有纪律的无知。接收端解码它懂的,隔离它不懂的,并拒绝把二进制保管误写成文本理解。开放式 MIME 才因此不必等待所有软件同时升级。

来源