RFC 1341 -> The Multipart Content-Type 学习笔记。
在含有多个“部分消息体”的消息中有一个或多个不同的数据集放在同一个消息体中,并且这个消息头部有一个值为 “multipart” 的 Content-Type 字段。这个消息的消息体由一个或多个“部分消息体”组成,并且这些“部分消息体”会被一个分割线来分离包装,并且最后一个“部分消息体”后面会有一个结束分割线来表示消息体的结束。每个“部分消息体”从一个分割线开始,然后是包含了头部区域,一个空白行,“部分消息体”的体部部分。因此这里我们所说的“部分消息体”和 RFC 822 中提到的消息在语法上是相同的,但是在含义上确实是不同的。
“部分消息体”现在不会再在 RFC 822 消息的定义中解释了。实际上,“部分消息体”起始部分不需要头部区域。因此,“部分消息体”允许从一个空白行开始,并且拥有默认值。当消息头中没有 Content-Type 字段时,说明消息体中的内容就是普通的 US-ASCII 文本(应该就是普通的文本文件吧,只是字符编码是 US-ASCII)。消息头中只有以 “Content-” 的字段是用来定义消息体中内容格式的。其他所有的字段在消息体中一般都会被忽略。尽管那些字段(即不是以 “Content-” 开头的字段)理应被邮件处理程序保留,但实际上它们更可能被网关,路由丢弃。因此,那些不是以 “Content-” 开头的字段虽然允许出现在消息体中,但是我们并不能指望着它们可以起到应有的作用。有时候,我们在实验性项目或者私有协议中会使用 “X-” 开头的字段,但是请记住:这些扩展字段是有可能被网关或者路由丢弃的。
“部分消息体”和 RFC 822 中定义的消息的区别是很小的,但是确实极其重要的。例如在 Internet mail 和 X.400 mail(至于什么是 X.400 mail,可以参考:https://en.wikipedia.org/wiki/X.400。大意就是说:早期邮件规范是用的 X.400 mail,后来被基于 SMTP 协议的 Internet mail 替代了)中,必须得区分一个拥有一张图片的“部分消息体”和一个封装了一张图片的“部分消息体”。为了表示后者,封装了一张图片的“部分消息体”一定要有一个“Content-Type:message”,并且它的体部(即空白行后面的内容)一定是一个包装了的消息,即拥有自己的头部字段“Content-Type:image”。使用相似的语法有利于消息和“部分消息体”之间的转变,但是,这两者之间一定要有一定的差别。(想象下:有时候所有的“部分消息体”都是一个消息,并且它们都定义了“digest”子类型。)
正如前面所说的,每个“部分消息体”前面都会有一个分割线,并且这个分割线的内容决不能出现在“部分消息体”里面。因此邮件代理(即我们常用的邮件客户端啦)必须指定一个独有的分割线来分割多个“部分消息体”。
所有的“multipart”的子类型必须得使用相同的语法。子类型可以有不同的语义,也可以有其额外的限制,但是其本身必须得遵循“multipart”所要求的语法。这也就确保了常规的邮件代理在不能识别子类型的情况下也可以识别消息体里的多个“部分消息体”。
正如我们在 Content-Transfer-Encoding 中定义的一样,“multipart”定义的实体内容只能使用“7 bit”,“8 bit”或者“binary”这三类编码。“部分消息体”分隔符和头部字段都是使用 7-bit ASCII 编码的,并且“部分消息体”的体部部分使用自身指定的 Content-Transfer-Encoding 字段的值来进行逐项编码。
邮件网关,中转服务器和处理邮件的邮件代理,都是可以对 RFC 822 消息中定义的头部字段进行任意的修改操作,例如:增加一个首部字段,删除一个首部字段,或者调整首部字段之间的前后顺序。但是,“部分消息体”中的头部字段是禁止修改的。
Multipart: The common syntax
“multipart”的所有子类型都使用本章定义的同一种语法。并且本章会给出一个简单的例子。附录 C 中将会给出更为复杂的多部分消息的例子。
对于多部分实体消息的Content-Type 需要有一个名为“boundary”的参数,用来指定包装“部分消息体”的分割线。包装“部分消息体”的分割线的内容是两个破折号后面接着Content-Type中“bounda”参数定义的值。
请注意:这种使用破折号前缀的语法是为了兼容 RFC 943 中定义的消息分割方式,以及其他的一些实现。然而,请记住多部分消息的包装语法并不完全兼容 RFC 934 中定义的包装语法;特别是,多部分消息的包装语法并不遵循 RFC 943 中以破折号开始的引用嵌入行语法。RFC 943 之所以使用这种语法是因为随着每级引用的增加,行数也会大量增加。SMTP 基于 RFC 943 这种机制实现在数据结构深层嵌套时造成包含了很长的空行。
因此,一个普通的 Content-Type 字段的内容如下:
这是这个字段表示消息实体会包含多个“部分消息体”,并且每个“部分消息体”的结构和 RFC 822 中定义的消息的格式相似,即头部区域为空,并且每个“部分消息体”前面都有一行用于包装的分割线:
请注意:这个分割线必须位于一行起始的位置,并且它的前面必须是一个回车换行,这个回车换行也是分割线的一部分。分割线后面又紧接着表示一个新的“部分消息体”起始部分的另一个回车换行,如果下面这个新的“部分消息体”的头部区域为空的话,分割线后面将连接接着两个回车换行(这种情况下,我们假定省略了的头部区域内容为 Content-Type text/plain)。
词典
encapsulation,封装,包装
interpreted,解释
distinction,区别,差别
subtle,微妙的,精细的
facilitate,促进,帮助
crucial,重要的
semantic,语义学
restrictions,限制,限制条件
conversion,转换
identical,完全相同的
conform,符合,遵循
appropriate,适当的
relay,中继器
alteration,改变,变更
explicitly,明确的
appendix,附录
convention,约定,习俗