RFC 2046:MIME 第2部分——媒体类型
存在的原因
RFC 2045 引入了 Content-Type 和传输编码,但它没有定义存在哪些内容类型或它们如何表现。RFC 2046 通过定义以下内容填补了这一空白:
- 顶级媒体类型(text、image、audio、video、application、multipart、message)。
- 多部分机制,允许单个电子邮件包含具有边界分隔符的多个正文部分。
- 控制邮件客户端如何显示部分的特定多部分子类型(mixed、alternative、digest、parallel)。
这是使现代电子邮件成为可能的 RFC。没有它,每封电子邮件都将是一个单一的文本块。
工作原理
顶级媒体类型
| 类型 | 描述 | 常见子类型 |
|---|---|---|
text |
人类可读的文本 |
text/plain、text/html、text/calendar
|
image |
图像数据 |
image/png、image/jpeg、image/gif、image/svg+xml
|
audio |
音频数据 |
audio/mpeg、audio/ogg
|
video |
视频数据 |
video/mp4、video/webm
|
application |
二进制数据或结构化格式 |
application/pdf、application/json、application/octet-stream
|
multipart |
一条消息中的多个正文部分 |
multipart/mixed、multipart/alternative、multipart/related
|
message |
封装的电子邮件消息 |
message/rfc822、message/delivery-status
|
多部分机制
多部分类型是 RFC 2046 的核心。多部分消息包含一个 boundary 参数,用于分隔每个部分:
Content-Type: multipart/mixed; boundary="----=_boundary_001" ------ 前言(MIME 客户端忽略)------ ------=_boundary_001 Content-Type: text/plain; charset=utf-8 这是第一部分。 ------=_boundary_001 Content-Type: text/plain; charset=utf-8 这是第二部分。 ------=_boundary_001-- ^^^ 注意尾部 -- 标记结束
边界的关键规则:
- 每个部分前面都有
--+ 边界字符串,各自占一行。 - 最后的边界也在其后附加
--(例如--boundary--)。 - 边界字符串不得出现在任何正文部分中。使用长的随机字符串。
- 第一个边界之前的内容(前言)和最后一个边界之后的内容(后语)被 MIME 感知的客户端忽略。
多部分子类型
子类型告诉邮件客户端如何显示这些部分。这是微妙之处所在。
multipart/mixed — 顺序部分
最常见的多部分类型。部分按顺序显示。用于"消息正文 + 附件":
Content-Type: multipart/mixed; boundary="----=_mixed" ------=_mixed Content-Type: text/plain; charset=utf-8 以下是您请求的报告。 ------=_mixed Content-Type: application/pdf; name="report.pdf" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="report.pdf" JVBERi0xLjQKJeLjz9MK... ------=_mixed--
multipart/alternative — 相同内容,不同格式
包含相同内容的多个版本。邮件客户端选择它能显示的最佳版本。部分从最简单到最丰富的顺序排列 — 最后一部分是首选:
Content-Type: multipart/alternative; boundary="----=_alt" ------=_alt Content-Type: text/plain; charset=utf-8 欢迎使用我们的服务! ------=_alt Content-Type: text/html; charset=utf-8 <h1>欢迎使用我们的服务!</h1> <p>我们很高兴有您。</p> ------=_alt--
这是每个格式良好的 HTML 电子邮件的工作方式:text/plain 备选方案首先出现,text/html 版本最后出现。支持 HTML 的客户端显示 HTML;纯文本客户端显示文本。
multipart/related — 链接部分
用于部分相互引用的情况。最常见的用例是带有内联图像的 HTML 电子邮件。HTML 通过 Content-ID(cid: URL)引用图像:
Content-Type: multipart/related; boundary="----=_rel" ------=_rel Content-Type: text/html; charset=utf-8 <p>看看我们的徽标:</p> <img src="cid:logo@example.com" alt="徽标" /> ------=_rel Content-Type: image/png Content-Transfer-Encoding: base64 Content-ID: <logo@example.com> iVBORw0KGgoAAAANSUhEU... ------=_rel--
multipart/digest — 消息集合
mixed 的一个变体,其中每个部分的默认内容类型是 message/rfc822 而不是 text/plain。由邮件列表摘要使用。在现代电子邮件中很少见。
关键技术细节
嵌套多部分类型
MIME 的真正功能来自嵌套。一个带有内联图像和附件的典型营销电子邮件看起来像这样:
; HTML 电子邮件标准结构(带内联图像 + 附件) Content-Type: multipart/mixed ← 外层:正文 + 附件 | |-- multipart/alternative ← 正文:文本或 HTML | |-- text/plain ← 纯文本备选 | |-- multipart/related ← HTML + 内联图像 | |-- text/html ← HTML 正文 | |-- image/png (cid:logo) ← 内联图像 | |-- application/pdf (attachment) ← 文件附件
这个三级嵌套是几乎所有电子邮件库和电子邮件服务提供商使用的标准模式。
message/rfc822 类型
将整个电子邮件消息封装为正文部分。用于转发消息作为附件和在退回通知中(RFC 3462 multipart/report)。封装的消息有自己的标头(From、To、Subject 等)和正文。
application/octet-stream 备选方案
当文件的内容类型未知时,使用 application/octet-stream。这告诉客户端将其视为通用二进制数据,通常会触发下载提示。这是 MIME 版本的"我不知道这是什么;保存它并自己弄清楚。"
边界要求
边界字符串有特定的规则:
- 最多 70 个字符。
- 由 ASCII 字母数字加有限的特殊字符组成:
'()+_,-./:=?和空格。 - 不得出现在任何附加的正文部分中。
- 实际上,使用长的随机字符串,如
----=_Part_12345_67890.1234567890。
常见错误
-
使用
multipart/mixed代替multipart/alternative来处理文本 + HTML。如果你把 text/plain 和 text/html 放在一个 mixed 容器中,客户端将显示两者(或显示文本并提供 HTML 作为下载)。使用 alternative,客户端就能选择最佳格式。 -
multipart/alternative中的部分顺序错误。最简单的格式优先,最丰富的最后。如果你把 HTML 放在纯文本之前,某些客户端即使 HTML 可用也会显示纯文本版本。 -
不带
multipart/related的内联图像。如果你在 HTML 中引用cid:URL,但图像在同级multipart/mixed部分而不是multipart/related容器中,许多客户端不会解析引用。 -
缺少 Content-ID 尖括号。Content-ID 标头值必须用尖括号包装:
<image001@example.com>。HTML 中的cid:引用省略它们:src="cid:image001@example.com"。 -
边界碰撞。使用短的或可预测的边界字符串(如
boundary或---)有风险出现在正文内容中,这将破坏消息结构。始终使用随机边界。 -
遗漏最后的
--。结束边界必须以--结尾(例如--boundary--)。缺少这个会导致解析器等待更多部分,可能导致消息损坏或不完整。
可传递性影响
- 正确的 multipart/alternative 至关重要。垃圾邮件过滤器期望格式良好的 HTML 电子邮件包含 text/plain 备选方案。缺少它是垃圾邮件信号。文本和 HTML 部分应该有大致相同的内容 — 一行文本部分加上 50 KB HTML 部分看起来很可疑。
-
内联图像增加垃圾邮件得分。大量使用
multipart/related和许多内联图像(尤其是当电子邮件主要是图像、很少文本时)会触发图像垃圾邮件启发式。对于营销电子邮件,优先使用带有https://URL 的托管图像,而不是cid:引用。 -
附件类型很重要。可执行附件(
.exe、.js、.bat)被几乎所有邮件提供商阻止或隔离。即使包含可执行文件的.zip文件也会被标记。坚持安全的类型:PDF、常见图像格式、Office 文档。 - 超大消息被退回。许多提供商拒绝超过 25 MB 的消息(某些超过 10 MB)。请记住 base64 编码增加 33% 的开销。20 MB 附件变成约 27 MB 电子邮件。
- 正确结构化的 MIME 标志合法性。格式良好的 MIME,具有正确的嵌套、有效的边界和适当的 Content-Type 声明,告诉垃圾邮件过滤器此消息由合法电子邮件软件生成,而不是手工制作的垃圾邮件工具。