RFC 2231:MIME 参数值扩展
ELI5: 电子邮件附件有文件名,文件名可能包含非英文字符或非常长。原始MIME只能在标头中处理纯ASCII值。RFC 2231添加了三个功能:支持非ASCII字符(如日文或阿拉伯文文件名)、语言标记和将长值分割到多行。
为什么存在这个标准
MIME 参数出现在 Content-Type 和 Content-Disposition 等标头中。最常见的用例是附件的 filename 参数:
Content-Disposition: attachment; filename="report.pdf"
这对 ASCII 文件名效果很好。但对于名为 報告書.pdf(日语"报告")或包含 200 个字符的文件名呢?原始 MIME 规范(RFC 2045)没有这样的机制。RFC 2231 解决了三个问题:
- 字符集:在参数值中编码非 ASCII 字符
- 语言标签:为参数值添加语言标识符注释
- 延续:将长参数值拆分为多行
工作原理
字符集和语言编码
要包含非 ASCII 字符,请在参数名后附加星号并使用格式 charset'language'encoded-value:
Content-Disposition: attachment; filename*=UTF-8''%E5%A0%B1%E5%91%8A%E6%9B%B8.pdf ^^^^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^^^ 字符集 语言 百分比编码的值 (空 = 无语言标签)
值 %E5%A0%B1%E5%91%8A%E6%9B%B8 是"報告書"的 UTF-8 字节百分比编码。单引号之间的语言标签是可选的(通常留空)。
长值的延续
当参数值过长而不适合单个标头行时,使用编号延续进行拆分:
Content-Type: application/pdf; filename*0="very-long-document-name-that-exceeds-the"; filename*1="-reasonable-line-length-limit-for-headers.pdf"
各部分按数字顺序重新组合:*0、*1、*2 等。
组合:具有字符集的延续
对于长的非 ASCII 值,请组合两个功能。只有第一个段包括字符集和语言;后续段只是编码值:
Content-Disposition: attachment; filename*0*=UTF-8''%E3%81%93%E3%82%8C%E3%81%AF%E9%95%B7; filename*1*=%E3%81%84%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB; filename*2*=%E5%90%8D.pdf ^^^^ 数字 + 星号 = 编码延续
关键技术细节
参数名称语法
| 形式 | 含义 | 示例 |
|---|---|---|
filename |
纯 ASCII 值 | filename="report.pdf" |
filename* |
编码值 (charset'lang'value) | filename*=UTF-8''%E5%A0%B1.pdf |
filename*0 |
延续部分 0,纯 ASCII | filename*0="very-long-" |
filename*0* |
延续部分 0,编码 | filename*0*=UTF-8''%E5%A0%B1 |
编码规则
- 对非 ASCII 字节使用百分比编码(如 URL 编码)
- MIME 令牌中安全的 ASCII 字符(字母、数字、连字符、句号)不需要编码
- 字符集在现代实践中几乎总是
UTF-8 - 语言标签遵循 BCP 47(例如
en、ja、zh-CN),但通常会省略
与 RFC 2047 的交互
RFC 2047 为标头中的非 ASCII 文本提供编码字(=?UTF-8?B?...?=)。但是,RFC 2047 明确指出编码字不得出现在带引号的字符串或参数值内。RFC 2231 是 MIME 参数的正确机制。尽管有此规则,许多邮件客户端在 filename 参数中使用 RFC 2047,所以健壮的解析器必须处理两者。
常见错误
-
在参数值中使用 RFC 2047 编码。编写
filename="=?UTF-8?B?...?="在技术上是无效的,但很普遍。为了获得最大兼容性,发送两者:带 ASCII 回退的纯filename和带 RFC 2231 编码值的filename*。 -
忘记编码延续的双星号。
filename*1是纯文本延续。filename*1*是编码延续。缺少末尾星号意味着该值将被视为字面文本,而不是解码。 - 延续顺序错误。部分必须从 0 开始顺序编号。编号间隙(0、1、3)或从 1 而不是 0 开始会导致严格实现中的解析失败。
- 使用 UTF-8 以外的字符集。虽然 RFC 2231 允许任何 IANA 字符集,但现代实践仅使用 UTF-8。使用 ISO-8859-1 或 Windows-1252 会降低与国际收件人的互操作性。
-
未提供 ASCII 回退。某些较旧的电子邮件客户端不支持 RFC 2231。始终在
filename*参数旁边包含带有 ASCII 近似值的纯filename参数。
可交付性影响
- 附件文件名显示。不正确的编码会导致附件文件名在收件人的邮件客户端中显示为乱码或问号。这令人困惑且不专业,尽管它不会直接影响是否传递消息。
- 垃圾邮件过滤器触发。格式错误的 MIME 参数可能会触发垃圾邮件过滤器。某些过滤器会将编码异常的消息标记为可疑,因为恶意软件活动有时会使用格式错误的标头来利用解析器漏洞。
-
跨客户端互操作性。RFC 2231 支持的真实情况差异很大。Gmail、Apple Mail 和 Thunderbird 处理得很好。某些较旧的企业客户端则不能。最安全的方法是始终包含
filename(ASCII)和filename*(RFC 2231)参数。 -
Content-Type 参数也是。虽然
filename是最明显的用例,但 RFC 2231 也适用于Content-Type参数,如name和charset,以及任何其他 MIME 标头参数。