最新消息:请随时分享你的乐趣!

RFC 2045 信体格式说明书

技术博客 磊子 285浏览 0评论

多用途Internet邮件扩展(多用途网际邮件扩充协议(MIME))由两部分组成,信头和信体。信体格式说明书即(RFC 2045)
  本备忘录的状态
  本文档讲述了一种Internet团体的Internet标准跟踪协议,它需要进一步的讨论和建议以得到改进。请参考最新版的Internet正式协议标准
(STD1)来获得本协议的标准化程度和状态。本备忘录的发布不受任何限制。

链接:http://www.ietf.org/rfc/rfc2045.txt

摘要

  STD11,RFC 822定义了一种信息表示协议,该协议规定了US-ASCII消息报头(message header)的详细细节,并规定消息内容(message content)和消息体(message body)为US-ASCII 文本格式。本系列文档共同被称为MIME(Multipurpose Internet Mail Extensions),重新定义了一系列允许下列内容的信息格式:

(1) 非US-ASCII的字符集的文本消息体(message body)   
(2) 不同格式的非文本消息体(message body)的扩展集
(3) 多部分消息体(message body)   
(4) 非US-ASCII字符集的文本报头息

  这套文档基于更早的文档RFC934、STD 11及RFC1049,但对它们进行了扩展和修正。由于RFC822对消息体(message body)涉及太少,所以这套文档与RFC822的相关性不大(不是修正RFC822 )。
  本文档说明了用于描述MIME消息(message)的多种报头;第二个文档RFC2046定义了MIME媒体类型系统的总体结构并且定义了媒体类型的初始集;第三个文档是RFC 2047,它扩展了RFC822,允许在Internet邮件报头中出现非US-ASCII文本;第四个文档RFC2048说明了MIME相关程序的不同IANA注册过程;第五个也是最后一个文档RFC2049描述了MIME一致性标准,同时提供了一些关于MIME消息格式的说明性示例,还有致谢参考书目
  这些文档都是RFC1521、RFC1522和RFC1590的修正版,而后面三个RFC又是RFC1341和1342的修订版。在RFC2049中的附录描述了与以前版本的不同及变化。

目录
1. 4
定义、约定和一般的BNF语法
2. 介绍
2.1 CRLF
2.2 字符集 (Character Set)
2.3 消息 (Message)
2.4 实体 (Entity)
2.5 部分主体 (Body Part)
2.6 主体 (Body)
2.7 7位的数据 (7bit Data)
2.8 8位的数据 (8bit Data)
2.9 二进制数据 (Binary Data)
2.10 行 (Lines)
3. MIME头字段(MIME Header Fields)
4. MIME-Version头字段
5. Content-Type 头字段
5.1 Content-Type头字段的语法
5.2 Content-Type的缺省值
6. Content-Transfer-Encoding头字段
6.1 Content-Transfer-Encoding 句法
6.2 Content-Transfer-Encoding 语义
6.3 新的Content-Transfer-Encoding
6.4 解释及使用
6.5编码转换
6.6 规范的编码模式(Canonical Encoding Model)
6.7 Quoted-Printable编码
6.8 Base64 Content-Transfer-Encoding
7. Content-ID 头字段
8. Content-Description 头字段
9. 另外的MIME头字段
10. 摘要
11. 安全考虑
12. 作者地址
附录A :收集的语法 

1. 介绍

  自从1982年发布以来,RFC822已经定义了一个在Internet上传输文本邮件的标准格式。RFC822格式是如此的成功,它已经完全或部分的为大家所接受,其程度甚至超越了Internet或在RFC821中定义的Internet SMTP。也正是由于这种格式被广泛的使用,所以许多限制因素日益约束着使用者群体。
  RFC822被制定为用来指定文本信息格式。这样,非文本信息――如包含音频或图像的多媒体信息――就完全没有被提及。甚至对一些文本的情况也是这样。RFC822不适用于那些需要多于US-ASCII字符集内容的使用者。因为RFC822没有定义一种机制,以允许邮件包含音频、视频、亚洲语言的文本甚至一些欧洲的语言文本,所以需要一个额外的规范来进行说明。
  RFC821/822中的一个基于邮件系统的明显限制,就是将电子邮件消息(message)内容限制在一些由7位的US-ASCII字符组成的短行中(每行1000字节或更少[RFC821])。这就迫使使用者在用本地用户代理(UA—User Agent,用来收发邮件的程序)发送他们的邮件之前,先要将将要发送的非文本数据转换为可打印的7位的US-ASCII字符。当前在Internet上使用的编码方式有:纯十六进制、uuencode、RFC1421中说明的base 64、ATK(the Andrew Toolkit Representation)及一些其它方式。
  当为在RFC822主机与X.400主机之间交换邮件信息而设计网关时,RFC822的局限性就更加明显了。X.400[X400]指定了一种在电子邮件消息中包含非文本内容的机制。当前,从X.400消息到RFC822消息的映射标准规定,X.400消息中的非文本部分必须要转换为IA5Text格式,否则,这些内容就会被丢弃,并在丢弃即将发生时,通报RFC822的使用者。当一个用户丢掉了他想接收的内容时,这显然是十分另人不快的。即使在用户代理不能处理非文本内容的时候,用户也可以对其采取一些额外的机制,来提取有用的信息。另外,这种处理也没有考虑到:消息最后可能会被网关转发到支持非文本信息的X.400消息处理系统中。
  这篇文档描述了几种机制,将它们联合起来,可以解决大部分的这类问题,而不会引入与RFC822不兼容的问题。详细的说,它描述了:

(1) MIME-Version头字段。它使用一个版本号来说明消息适用于MIME,而且允许邮件处理代理将这类消息与其它由旧版本或不适用的软件所产生的消息相区别。
(2) 在RFC1049中归纳的Content-Type头字段。用来指定消息数据的媒体类型(media type)及子类型,以及指定这些数据的本地表示方法(规范形式)。
(3) Content-Transfer-Encoding头字段。用来指定应用于主体(body)的编码转换方式及结果所处的范围。编码转换不同于恒等转换,它通常用于使数据通过那些有数据或字符集限制的邮件传输机制。
(4) 两个附加的头字段:Content-IDContent-Description。它们被用来更深层的描述主体(body)中的数据。

这篇文档中的所有的头字段定义都服从于RFC822中规定的句法规则。特别的,除了Content-Disposition以外,所有的这些头字段都可以包含RFC822注释。这些注释没有实际意义,应该在MIME处理过程中忽略。
  最后,为了说明及促进互用性,RFC2049为以上机制的子集提供了一个基本的适用性声明。它定义了与本文档相适应的最低限度。
  历史注释:在第一次阅读时,这组文档中所描述的几个机制看起来会有些奇怪或具有巴洛克风格。但要注意,对于开发这组文档的团体而言,与现有标准兼容以及遇到现有习惯时的稳健性,这两者具有相同的优先级。特别是兼容性永远优先于简洁
  请查阅当前版本的《因特网官方标准》(Internet Official Protocol Standards)以得到本协议的标准化状态及情况。RFC 822和STD3,RFC1123也提供了MIME的基本背景,符合MIME的实现都不会违背它们。另外,MIME的实现者也许会关心几个另外的RFC文档,特别是RFC1344、RFC1345和RFC1524。

2. 定义、约定和一般的BNF语法

  虽然这组文档所定义的机制都以文字的形式给出,但仍有一部分是由RFC 822定义的BNF符号所描述。为了了解这组文档,实现者需要熟悉这些符号,并参考RFC 822,以得到这些扩充的BNF符号的完整解释。
  本文档中的一些扩展BNF所构成的名字参考了RFC 822中的句法规则。或要获得完整的语法则要组合如下内容:本系列每个文档中收集了语法的附录、RFC822中定义的BNF以及在RFC1123中对RFC822所进行的修正。(其中给出了returndatamailbox的语法变化)
  在这组文档中,所有的数值字及字节的值都由十进制的形式给出。所有的媒体类型(media type)、子类型以及参数名称都是大小写无关的。然而,除非特别说明,否则参数内容是大小写相关的。
  格式注释:这部分的注释提供了一些不重要的信息,在阅读时可以跳过它们而不会错过任何本质的东西。添加这些注释的基本目的是为了说明关于这系列文档的基础原理,或是为了将其恰当地放置于历史或发展过程中。这些信息,可以被那些只关心建立实现的人所忽略,但对那些希望懂得为什么某种设计会被应用的人来说,这些信息还是会有一定用处的。

2.1 CRLF

  在这系列文档中,术语CRLF指一个US-ASCII字符序列。它由两个字符组成:CR(十进制值为13)和LF(十进制值为10),它们按顺序放在一起,构成RFC 822邮件的换行。

2.2 字符集 (Character Set)

  在MIME中,术语字符集(character set)被用来表示一种将字节序列转换成字符序列的方法。注意,反方向不需要绝对的、明确的转换,因为并不是所有的字符都可以被一个已知的字符集描述,而且一个字符集可能提供多于一个的字节序列,来表示某字符序列。
  本定义允许将各种类型的字符编码做为字符集使用,如从简单的单表映射(如US-ASCII)到多表转换方法(如使用ISO 2022技术)等。然而与MIME字符集名称相关的定义则必须完全说明所要执行的映射。特别的,不允许使用外部描述信息来决定精确的映射。
  注释:术语字符集(character set)最初是用来描述一些简单的方案如US-ASCII和ISO-8859-1的,它们都是从单一字节到单一字符的一对一映射。多字节编码字符集和转换方法使得情况更加复杂。例如,一些团体使用术语character encoding,而不是MIME中所使用的术语character set来表示字符集,而且使用coded character set来抽象的表示从整数(而不是字节)到字符的映射。

2.3 消息 (Message)

  术语消息(Message)在没有进一步限定的时候,表示的是在Internet上传输的(完整或顶层的)RFC822消息,或者表示压缩在message/rfc822message/partial中的内容。

2.4 实体 (Entity)

  术语实体(Entity)特指MIME定义的头字段(header field)及内容(content),它们存在于消息(message)及多部分实体的一部分之中。对这些实体的规范是MIME的基本内容。因为一个实体的内容经常被称为主体(body),所以关于实体主体说法是有意义的。任何字段都可以出现在实体头信息中,但是只有那些以content-开头的字段有真实的、与MIME相关的意义。注意,这并不意味着它们没有意义,一个没有MIME头字段的实体(或消息)的意义由RFC822所定义。

2.5 部分主体 (Body Part)

  body part指的是多部分实体(mulitpart entity)中的一个实体(entity)。

2.6 主体 (Body)

  在没做进一步说明的时候,术语主体(body)指的是一个实体(entity)的主体部分。也就是指消息(message)或部分主体(body part)的主体部分。
  注释:很明显,以上四个概念被循环定义。因为MIME消息的整个结构就是递归的,所以这种情况不可避免。

2.7 7位的数据 (7bit Data)

  7位的数据(7bit Data)所描述的是相对较短的数据行:每行有998个或更少的8位字节内容,行分隔符为CRLF序列[RFC-821]。其中,每一个8位字节的值都不可以大于十进制的127,也不能为NUL(十进制的0),而且CR(十进制值为13)和LF(十进制值为10)字节只可以出现在CRLF序列中。

2.8 8位的数据 (8bit Data)

  8位的数据(8bit Data)所描述的是相对较短的数据行:每行有998个或更少的8位字节内容,行分隔符为CRLF序列[RFC-821]。其但是字节的值可以大于十进制的127。与7bit data一样, CR(十进制值为13)和LF(十进制值为10)字节只可以出现在CRLF序列中,字节的值不能为NUL(十进制的0)。

2.9 二进制数据 (Binary Data)

  二进制数据(Binary Data)是指可以包含任何字节序列的数据。

2.10 行 (Lines)

  (Lines)被定义为由CRLF分隔的字节序列。这与RFC 821及RFC 822一致。(Lines)是指消息(Message)中的数据单位,它可以符合或不符合用户代理(user agent)所显示的真实情形。

3. MIME头字段(MIME Header Fields)

  MIME定义了许多新的RFC822头字段,用以描述MIME实体内容(entity content)。这些头字段至少会在以下两个地方出现:
  (1) 做为规则的RFC822消息(message)头信息的一部分。
  (2) 在多部分结构(multipart construct)里,存在于部分主体(body part)头信息中。

  这些头字段的形式定义如下: 
   entity-headers := [ content CRLF ] 
   [ encoding CRLF ] 
   [ id CRLF ] 
   [ description CRLF ] 
   *( MIME-extension-field CRLF ) 

   MIME-message-headers := entity-headers 
   fields 
   version CRLF 
   ; 当前BNF所暗含的实体头信息 
   ; 顺序可以被忽略。 

   MIME-part-headers := entity-headers 
   [ fields ] 
   ; 任何不以`content-`开始的字段 
   ; 都没有被定义,可以被忽略。 
   ; 当前BNF所暗含的实体头信息 
   ; 顺序也可以被忽略。 

  不同的MIME头字段的语法细节会在下面的章节中说明。
  

4. MIME-Version头字段

  自从1982年发布了RFC 822以来,实际上只存在这一种Internet消息格式标准,而且几乎没人意识到需要声明那些正在使用中的格式。这篇文档是一个补充RFC822的独立说明。虽然在这篇文档中所做的扩展已经被定义为与RFC 822兼容,但是,邮件处理代理仍然需要知道一个消息是否是按照新的标准构成。
  为此,本文档定义了一个新的头字段:MIME-Version。它被用来声明Internet消息主体(message body)所使用格式的版本号。
  按照本文档格式所构成的消息(message),必须按如下格式包含这个头字段:
  MIME-Version: 1.0
  这个字段就是一个声明,它表示消息的结构符合本文档所规定的格式。
  因为今后的文档中有可能再次扩展消息格式的标准,所以这里给出MIME-Version头字段的BNF:
  version := "MIME-Version" ":" 1*DIGIT "." 1*DIGIT
  这样,将来的格式说明符都被约束为以小数点分隔的两个整数,它们可能会替代或扩展字符:1.0。如果接收到一个消息,它的MIME-version值不是1.0,那么就可以假定它不符合本文档的规范。
  还有一件值得注意的事情是,不可以使用MIME-Version机制来实行对媒体类型的版本控制。特别的,一些格式(如application/postscript)拥有包含在媒体格式内部的约定版本号。当这种约定存在时,MIME不会将其取代。当这种约定不存在时,MIME会在必要的时候使用content-type字段中的一个version参数进行声明。
  实现者要注意的问题:在检查MIME-Version的时候,一定要忽略任何在RFC822中所定义的注释部分。详细的说,以下的MIME-Version字段是等价的:

   MIME-Version: 1.0
   MIME-Version: 1.0 (produced by MetaSend Vx.x)
   MIME-Version: (produced by MetaSend Vx.x) 1.0
   MIME-Version: 1.(produced by MetaSend Vx.x)0

  当缺少MIME-Version字段时,接收邮件的代理(无论此代理是否符合MIME要求)都可以按照本地的约定,任意的解释消息体。在当前的使用中存在的许多这样的约定。应该注意到,在实际中非MIME消息可以包含任何内容。
  无法确定一个非MIME邮件消息中只包含US-ASCII字符集的纯文本内容,因为这个消息很可能使用了一些非标准的比MIME更早出现的本地约定,或是包含其它字符集的内容或非文本的内容,这样,消息就无法被自动的识别。(如用UUENCODE方式编码的UNIX tar压缩文件)

5. Content-Type 头字段

  设置Content-Type头字段的目的是为了完整的描述主体(body)中数据的内容。这样,接收代理就可以挑选出适当的代理或机制,来向用户呈现数据内容,或以适当的方式处理数据。这个字段值被称为媒体类型(media type)。
  历史注释:Content-Type头字段最初是在RFC1049中定义的。RFC1049中使用的是相对简单的,不强大的语法,但是在很大程度上与本文档所定义的机制相兼容。
  Content-Type头字段通过指定媒体类型及子类型的标识符来说明实体主体(body of an entity)中数据的原始类型,而且它还会为一些特别的媒体类型提供辅助信息。在媒体类型及子类型名称之后,本字段中的其余部分均为参数,它们以属性=值的形式给出,至于这些参数是按什么顺序给出的,则并不重要。
  总的来说,顶层的媒体类型被用来声明数据的一般类型,而子类型则指明了数据的细节格式。因此,媒体类型image/xyz足以使用户代理知道,接收的数据是一个图像,哪怕这个用户代理并不知道这种特殊的图像类型:xyz。因此,这类信息可以被用来决定是否向用户显示一种拥有不能识别的子类型的原始数据――此操作对于拥有不可识别子类型的文本内容来说是合理的,但不适用于图像(image)和音频(audio)类型的数据。由于这个原因,文本、图像、音频和视频的子类型都不能包含有不同类型的嵌入信息。这种复合的格式应该由类型multipartapplication所描述。
  参数是媒体子类型的修饰成份,而不会影响内容的性质。一组有意义的参数依赖于媒体类型及子类型。大部分的参数只与某单一的子类型相关联。然而,一个顶级的媒体类型可以定义一些与其中的任何子类型都关联的参数。对于所涉及到的内容类型(content type)或子类型(subtype)来说,参数可能是必须的,也可能是可选的。MIME的实现过程中必须忽略所有不能识别的参数。
  例如,charset参数可适用于text类型中的任何子类型,而boundary参数则是multipart类型中所有子类型所必须的。
  不存在适用于所有媒体类型的全局参数。真正的全局机制是通过在MIME原型中定义Content-*头字段而提出的。
  在RFC2046中定义了最初的七个顶级媒体类型。其中的五个是不连续的类型,它们的内容是MIME处理过程所不关心的。另外的两个类型是合成的,它们的内容需要MIME处理器进行额外的处理。
  这组顶级的媒体类型(media type)已被完全定义。希望在对这组媒体类型进行扩充的时候,只是扩充初始类型中的子类型。将来,只可以在扩展本标准的情况下,才能定义更多的顶级媒体类型。无论任何原因,如果需要使用另一个顶级类型,那么这个类型的名称必须以X-开头,以表示它是一个非标准的状态,以避免今后与官方定义的名称冲突。

5.1 Content-Type头字段的语法

  用一种扩充的BNF符号定义Content-Type头字段,如下:

     content := "Content-Type" ":" type "/" subtype
                *(";" parameter)
                ; Matching of media type and subtype
                ; is ALWAYS case-insensitive.

     type := discrete-type / composite-type

     discrete-type := "text" / "image" / "audio" / "video" /
                      "application" / extension-token

     composite-type := "message" / "multipart" / extension-token

     extension-token := ietf-token / x-token

     ietf-token := <An extension token defined by a
                    standards-track RFC and registered
                    with IANA.>

     x-token := <The two characters "X-" or "x-" followed, with
                 no intervening white space, by any token>

     subtype := extension-token / iana-token

     iana-token := <A publicly-defined extension token. Tokens
                    of this form must be registered with IANA
                    as specified in RFC 2048.>

     parameter := attribute "=" value

     attribute := token
                  ; Matching of attributes
                  ; is ALWAYS case-insensitive.

     value := token / quoted-string

     token := 1*<any (US-ASCII) CHAR except SPACE, CTLs,
                 or tspecials>

     tspecials :=  "(" / ")" / "<" / ">" / "@" /
                   "," / ";" / ":" / "\" / <">
                   "/" / "[" / "]" / "?" / "="
                   ; Must be in quoted-string,
                   ; to use within parameter values

  注意,对tspecials的定义与RFC822中对specials的定义是几乎一样的,只是新增了三个字符:/?=,又去掉了一个字符:.
  还要注意到,对子类型(subtype)的定义是强制性的――子类型不可以被Content-Type字段所忽略,因此,也就不存在缺省的子类型(subtype)。
  类型、子类型、参数名称都是大小写无关的。例如:TEXTTextTeXt表示相同的顶级媒体类型。参数值通常都是大小写相关的,但是一些时候也被定义为大小写无关的形式,这依赖于具体的应用。(例如,multipart boundary就是大小写相关的、而access-type则是大小写无关的)
  注意一个用引号括起来的参数值中不包括引号,这就是说,一个被引号括起来的字符串中,引号是不包括在参数值中的,但这仅限于使用引号确定参数值界线的情况下。另外,格式与RFC822规则一致的注释也允许出现在这个字段中,因些,以下两种形式是完全等价的:
  Content-type: text/plain; charset=us-ascii (Plain text)
  Content-type: text/plain; charset=”us-ascii”
  除了这些句法之外,对构成子类型名称的唯一句法约束是它们在使用中不可以相互冲突。这就是说,不可以有两个不同的团体使用Content-Type: application/foobar来表示两种不同东西。定义一个媒体子类型的过程,并不受限制:只需要公布这些类型的定义,并使用它们即可。因此,两种广泛接受的定义媒体子类型的机制如下:

(1)私有值(以X-开头的名称)可以在两个协同工作的代理之间双向的定义,而不需要外部的注册或标准化。这种值不可以被注册或制定为标准。
(2) 可以向IANA注册新的标准,如RFC2048中描述的情况。

  这组文档中的第二篇:RFC2046定义了媒体类型的初始集合。
  5.2 Content-Type的缺省值
  没有Content-Type头字段的RFC822消息被默认为是US-ASCII字符集、纯文本类型的内容。它可以被精确的描述为:

Content-type: text/plain; charset=us-ascii

  这个缺省值是在没有指定Content-Type头字段时而使用的。而且,在遇到句法错误的Content-Type头字段时,也会使用这个缺省值。当消息中存在MIME-Version头字段,而缺少Content-Type头字段时,接收方的用户代理也可以假定发送者所发送的是US-ASCII字符集的纯文本内容。在没有MIME-Version头字段或有错误语法的Content-Type头字段时,仍然可以假定其内容是US-ASCII字符集的纯文本,但是这可能不是发送者的本意。

转载请注明:印迹. » RFC 2045 信体格式说明书

发表我的评论
取消评论

表情