手机开发实战68——MIME介绍3

来源:互联网 发布:举例说明算法的可行性 编辑:程序博客网 时间:2024/05/17 21:26

MIME详述

介绍

  STD11,RFC 882定义了一种信息表示协议,该协议规定了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字符集的文本报头息

  这套文档基于更早的文档RFC934STD 11RFC1049,但对它们进行了扩展和修正。由于RFC822对消息体(message body)涉及太少,所以这套文档与RFC822的相关性不大(不是修正RFC822 )

  本文档说明了用于描述MIME(message)的多种报头;第二个文档RFC2046定义了MIME媒体类型系统的总体结构并且定义了媒体类型的初始集;第三个文档是RFC 2047,它扩展了RFC822,允许在Internet邮件报头中出现非US-ASCII文本;第四个文档RFC2048说明了MIME相关程序的不同 IANA注册过程;第五个也是最后一个文档RFC2049描述了MIME一致性标准,同时提供了一些关于MIME消息格式的说明性示例,还有致谢“ 参考书目

  这些文档都是RFC1521RFC1522RFC1590的修正版,而后面三个RFC又是RFC13411342的修订版。在RFC2049中的附录描述了与以前版本的不同及变化。

详解

自从1982年发布以来,RFC822已经定义了一个在Internet上传输文本邮件的标准格式。RFC822格式是如此的成功,它已经完全或部分的为大家所接受,其程度甚至超越了Internet或在RFC821中定义的Internet SMTP。也正是由于这种格式被广泛的使用,所以许多限制因素日益约束着使用者群体。

  RFC822被制定为用来指定文本信息格式。这样,非文本信息――如包含音频或图像的多媒体信息――就完全没有被提及。甚至对一些文本的情况也是这样。RFC822不适用于那些需要多于USASCII字符集内容的使用者。因为RFC822没有定义一种机制,以允许邮件包含音频视频、亚洲语言的文本甚至一些欧洲的语言文本,所以需要一个额外的规范来进行说明。

  RFC821/822中的一个基于邮件系统的明显限制,就是将电子邮件消息(message) 内容限制在一些由7位的US-ASCII字符组成的短行中(每行1000字节或更少[RFC821])。这就迫使使用者在用本地用户代理(UA—User Agent,用来收发邮件的程序)发送他们的邮件之前,先要将将要发送的非文本数据转换为可打印的7位的US-ASCII字符。当前在Internet使用的编码方式有:纯十六进制、uuencodeRFC1421中说明的base 64ATK(the Andrew Toolkit Representation)及一些其它方式。

  当为在RFC822主机与X.400主机之间交换邮件信息而设计网关时,RFC822的局限性就更加明显了。X.400[X400]指定了一种在电子邮件消息中包含非文本内容的机制。当前,从X.400消息到RFC822消息的映射标准规定,X.400消息中的非文本部分必须要转换为IA5Text格式,否则,这些内容就会被丢弃,并在丢弃即将发生时,通报RFC822的使用者。当一个用户丢掉了他想接收的内容时,这显然是十分另人不快的。即使在用户代理不能处理非文本内容的时候,用户也可以对其采取一些额外的机制,来提取有用的信息。另外,这种处理也没有考虑到:消息最后可能会被网关转发到支持非文本信息的X.400消息处理系统中。

  这篇文档描述了几种机制,将它们联合起来,可以解决大部分的这类问题,而不会引入与RFC822不兼容的问题。详细的说,它描述了:

“MIME-Version”头字段。

  它使用一个版本号来说明消息适用于MIME,而且允许邮件处理代理将这类消息与其它由旧版本或不适用的软件所产生的消息相区别。在RFC1049中归纳的

“Content-Type”头字段

  用来指定消息数据的媒体类型(media type)及子类型,以及指定这些数据的本地表示方法(规范形式)。 “Content-Transfer-Encoding”头字段。用来指定应用于主体(body)的编码转换方式及结果所处的范围。编码转换不同于恒等转换,它通常用于使数据通过那些有数据或字符集限制的邮件传输机制。

两个附加的头字段

   “Content-ID”“Content-Description”。它们被用来更深层的描述主体(body)中的数据。这篇文档中的所有的头字段定义都服从于RFC822中规定的句法规则。特别的,除了“Content-Disposition”以外,所有的这些头字段都可以包含RFC822注释。这些注释没有实际意义,应该在MIME处理过程中忽略。

  最后,为了说明及促进互用性,RFC2049为以上机制的子集提供了一个基本的适用性声明。它定义了与本文档相适应的最低限度。

历史注释

RFC 822STD3RFC1123也提供了MIME的基本背景,符合MIME的实现都不会违背它们。另外,MIME的实现者也许会关心几个另外的RFC档,特别是RFC1344RFC1345RFC1524

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

  虽然这组文档所定义的机制都以文字的形式给出,但仍有一部分是由RFC 822定义的BNF符号所描述。为了了解这组文档,实现者需要熟悉这些符号,并参考RFC 822,以得到这些扩充的BNF符号的完整解释。本文档中的一些扩展BNF所构成的名字参考了RFC 822中的句法规则。或要获得完整的语法则要组合如下内容:本系列每个文档中收集了语法的附录、RFC 822中定义的BNF以及在RFC 1123中对 RFC 822 所进行的修正。(其中给出了“return”“data”“mailbox”的语法变化)

  在这组文档中,所有的数值字及字节的值都由十进制的形式给出。所有的媒体类型(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-ASCIIISO-8859-1的,它们都是从单一字节到单一字符的一对一映射。多字节编码字符集和转换方法使得情况更加复杂。例如,一些团体使用术语“character encoding”,而不是MIME中所使用的术语“character set”来表示字符集,而且使用“coded character set”来抽象的表示从整数(而不是字节)到字符的映射。

  2.3 消息Message

  术语消息Message)在没有进一步限定的时候,表示的是在Internet上传输的(完整或顶层的)RFC822消息,或者表示压缩在“message/rfc822”“message/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 821RFC 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头字段的语法细节会在下面的章节中说明。

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压缩文件)

Content-Type 头字段

  设置“Content-Type”头字段的目的是为了完整的描述主体(body)中数据的内容。这样,接收代理就可以挑选出适当的代理或机制,来向用户呈现数据内容,或以适当的方式处理数据。这个字段值被称为媒体类型media type)。

  历史注释:“Content-Type”头字段最初是在RFC1049中定义的。RFC1049中使用的是相对简单的,不强大的语法,但是在很大程度上与本文档所定义的机制相兼容。

  “Content-Type”头字段通过指定媒体类型及子类型的标识符来说明实体主体body of an entity)中数据的原始类型,而且它还会为一些特别的媒体类型提供辅助信息。在媒体类型及子类型名称之后,本字段中的其余部分均为参数,它们以属性 = 值的形式给出,至于这些参数是按什么顺序给出的,则并不重要。

  总的来说,顶层的媒体类型被用来声明数据的一般类型,而子类型则指明了数据的细节格式。因此,媒体类型“image/xyz”足以使用户代理知道,接收的数据是一个图像,哪怕这个用户代理并不知道这种特殊的图像类型:“xyz”。因此,这类信息可以被用来决定是否向用户显示一种拥有不能识别的子类型的原始数据――此操作对于拥有不可识别子类型的文本内容来说是合理的,但不适用于图像image)和音频(audio)类型的数据。由于这个原因,文本、图像、音频和视频的子类型都不能包含有不同类型的嵌入信息。这种复合的格式应该由类“multipart”“application”所描述。

  参数是媒体子类型的修饰成份,而不会影响内容的性质。一组有意义的参数依赖于媒体类型及子类型。大部分的参数只与某单一的子类型相关联。然而,一个顶级的媒体类型可以定义一些与其中的任何子类型都关联的参数。对于所涉及到的内容类型content type)或子类型(subtype)来说,参数可能是必须的,也可能是可选的。MIME的实现过程中必须忽略所有不能识别的参数。

  例如,“charset”参数可适用于“text”类型中的任何子类型,而“boundary”参数则是“multipart”类型中所有子类型所必须的。

  不存在适用于所有媒体类型的全局参数。真正的全局机制是通过在MIME原型中定义“Content-*”头字段而提出的。

  在RFC2046中定义了最初的七个顶级媒体类型。其中的五个是不连续的类型,它们的内容是MIME处理过程所不关心的。另外的两个类型是合成的,它们的内容需要MIME处理器进行额外的处理。

  这组顶级的媒体类型(media type)已被完全定义。希望在对这组媒体类型进行扩充的时候,只是扩充初始类型中的子类型。将来,只可以在扩展本标准的情况下,才能定义更多的顶级媒体类型。无论任何原因,如果需要使用另一个顶级类型,那么这个类型的名称必须以“X-”开头,以表示它是一个非标准的状态,以避免今后与官方定义的名称冲突。

Content-Type头字段的语法

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

  content := "Content-Type" ":" type "/" subtype

  *(";" parameter)

  匹配媒体类型或子类型时,是大小写无关的

  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

  匹配属性( attributes)时,

  总是大小写无关的

  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)

  类型、子类型、参数名称都是大小写无关的。例如:“TEXT”“Text”“TeXt”示相同的顶级媒体类型。参数值通常都是大小写相关的,但是一些时候也被定义为大小写无关的形式,这依赖于具体的应用。(例如,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定义了媒体类型的初始集合。

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字符集的纯文本,但是这可能不是发送者的本意。

Content-Transfer-Encoding头字段

  通过邮件传输的一些数据可能会被声明成它们的原始格式,如8位字符(8bit character)或二进制数据(binary data)。这些数据不通过一些传输协议进行传输。如:RFC821SMTP)中限制邮件消息中只可以由一些包括行结束符CRLF序列在内,长度不超过 1000字节的行组成,而且所有的字符都是7位的US-ASCII字符。

  因此需要定义一种机制来将这些数据编码为7位数据(7bit data)的短行。并且,当在限制很少的系统中直接传输无限制的格式时,需要对其中未编码内容进行适当的标记。本文档通过一个新的“Content- Transfer-Encoding”头字段来指定这类编码。这个头字段并没有在以前的标准中进行过定义。

Content-Transfer-Encoding 句法

  “Content-Transfer-Encoding”头字段中只有一个值,它指定了编码类型,格式如下:

  encoding := "Content-Transfer-Encoding" ":" mechanism

  mechanism := "7bit" / "8bit" / "binary" /

  "quoted-printable" / "base64" /

  ietf-token / x-token

  这些值都是大小写无关的,“Base64”“BASE64”“bAsE64”的意义相同。

  编码方式“7bit”要求实体体中的内容都是7位字节。而且它也是缺省值,这就是说,如果没有“Content-Transfer-Encoding”头字段,则假定其为:“"Content-Transfer-Encoding: 7BIT”

Content-Transfer-Encoding 语义

  字符串“Content-Transfer-Encoding”实际上提供了两条信息。它指明了在传输主体(body)的时候,采用了哪种编码方式及必须用哪种解码方式将数据解码成它的原始状态。同时,它还指明了解码结果所处的范围。任何“Content-Transfer-Encoding”的转换部――无论是确定的还是缺省的――都指定了一个单一的、详细定义的解码算法。这个算法可以将编码后的任意字节序列转换为编码前的原始序列,或说明某部分内容是非法的编码序列。“Content-Transfer-Encoding”转换永远不会依赖于附加的外部信息。注意,解码器必须为每一个合法的编码内容提供一个单一的、详细定义的输出。而对于编码器却不存在这样的限制。对同一个输入序列,编码器可以给出不同的,等价的编码序列――这是完全合法的。目前定义了三种转换方式:恒等的、“quoted-printable”编码、“base64”编码。范围是“binary”“8bit”“7bit”

  “Content-Transfer-Encoding”的值为“7bit” “8bit”“binary”时,说明编码转换已经完成(也就是没有编码),同时,作为简单的标识符,它们给出了实体体数据的范围,并提供了在某个特定的传输系统中传输数据时可能会采用某种编码方式的相关信息。术语“7bit data”“8bit data”“binary data”的定义见第二节。

  “quoted-printable”“base64”会将任意的输入内容转换到“7bit”范围中,以使数据可以在受限制的系统中传输。转换的定义将在下文中给出。

  必须始终使用正确的“Content-Transfer-Encoding”标志。不允许将未编码的8位字符(8bit characters)标志为“7bit”。而且,未编码的与行无关的内容只能被标识为“binary”

  与媒体子类型不同,“Content-Transfer-Encoding”值不需要有子类型值。然而,不可能只建立一个单一的到“7bit”的转化方式。因为要在以下两个方面进行权衡:对较长的二进制内容进行简洁、高效的编码,或是需要一个更易读的编码内容,而编码可以不完全是7bit的。由于这个原因,至少要提供两种编码机制:或多或少可读的编码(quoted-printable)和紧凑 ”均匀的编码(base64)。

  在RFC1652中定义了传输未编码的8位数据的方式。到最初公布本文档时为止,还没有为在因特网上传输包含未编码二进制数据邮件而制定的标准。因此就不存在二进制”(binary) Content-Transfer-Encoding类型值合法的出现在因特网邮件中的情况。然而,当传输二进制邮件成为可能时,或MIME被用来连接其它任何的可传输二进制邮件的邮件传输机构时,就必须用这种机制对二进制内容进行标识。

  注意:为“Content-Transfer-Encoding”头字段所定义的五个值只是为媒体类型提供了编码或解码的算法。

新的Content-Transfer-Encoding

  如果需要,实现者可以定义私有的“Content-Transfer-Encoding”值。但是必须使用x标记,就是指要在名字前面加上“X-”,以说明它是一个非标准的状态。如,“Content-Transfer-Encoding: x-my-new-encoding”其它的“Content-Transfer-Encoding”标准值,则必须通过标准途径RFC来定义。在RFC2048中给出了这些说明须符合的要求。同样的,除了以“X-”开头的“Content-Transfer-Encoding”名字之外,所有的名字都是为IETF将来的使用而保留的。

  与媒体类型及子类型不同,不提倡创建新的“Content-Transfer-Encoding”值。因为它会阻碍互用性,并且几乎没有一点潜在的好处。

解释及使用

  如果“Content-Transfer-Encoding”头字段是消息头信息的一部分,那么它对这个消息中的全部主体(body)都适用。如果 “Content-Transfer-Encoding”头字段是实体(entity)头信息的一部分,那么它只适用于这个实体(entity)的主体body)。如果实体类型是“multipart”,则“Content-Transfer-Encoding”只能是“7bit”“8bit” “binary”中的一个。一些更为严格的约束将应用于“message”媒体类型的子类型。

注意

  应该注意到,大部分的媒体类型都是按照字节而不是位而定义的,因此,这里描述的机制是解码任意字节流而非位流。如果需要通过这些机制对位流进行编码,则必须要先使用网络位顺序标准(大端字节序[big-endian])将位流转换成8位字节流――位流中靠前的位出现在字节的高位中。如果位流中剩下的部分不足8位,则必须补0RFC2046中提供了用参数为“padding”“application/octet-stream”媒体类型来说明上述这种填充机制。

  这里定义的编码机制可以将任何数据编码为US-ASCII字符集的内容。因此,如果假设一个实体有如下头字段:

  Content-Type: text/plain; charset=ISO-8859-1

  Content-transfer-encoding: base64

  则必须被解释为:实体内容是BASE64 US-ASCII编码的数据,而原始数据为ISO-8859-1字符集内容,而且解码后内容也处于同一字符集ISO-8859-1中。

  特定的“Content-Transfer-Encoding”值可以被用于特定的媒体类型。特别的,明确禁止将除“7bit”“8bit”“binary”之外的编码方式应用于任何复合的媒体类型,如递归包含其它“Content- Type”头字段的媒体类型。当前仅有的复合媒体类型是“multipart”“message”。想要对“multipart”“message” 类型的实体编码时,必须在最里面的一层中,对需要编码的真实实体进行编码。

  同样要注意,如果一个实体的编码类型被定义为“7bit”,而其中还包含有一个编码类型为 “8bit”的实体。这时,或者外部的“7bit”标签是错误的,因为它包含了8位的数据;或者内部的“8bit”标签对传输系统提出了不必要的要求,因为实际上它包含的数据类型只是7位的。

  关于编码约束的注释:虽然禁止在复合结构中使用“Content-Transfer- Encoding”可能有些过度严格,但是必须要防止嵌套编码――这样会导致对数据进行多次编码,以及为正确显示出数据内容必须进行多次解码。嵌套编码会给用户代理的工作增加很大的复杂度:多次编码除了会带来效率问题,还会使消息的原始结构变得含糊。特别的,它们暗示了只有在进行所有的解码操作之后,才可以知道消息内容的类型是什么。禁止嵌套编码会使邮件网关的工作变得复杂,但是,与重复编码可能给用户代理所带来的影响相比,这个问题要小得多。

  对于任何带有不可识别的“Content-Transfer-Encoding”值的实体,不论其“Content-Type”真实值是什么,都要将其看作为“application/octet-stream”类型。

  “Content-Type”“Content-Transfer-Encoding”的关系:看起来似乎可以通过被编码媒体的特征来推断出“Content-Transfer-Encoding”的值,或者至少可以通过对一些特定媒体类型的使用来确定“Content-Transfer-Encoding”。但实际上,这些假设是不正确的,这里给出几个原因:首先,对于邮件,存在不同的传输方式,一些编码可能只适用于某些而不是全部的媒体类型或传输方式。(如,在8位传输系统中,不需要对特定字符集中的文本进行编码,而在7位传输系统中,却一定需要编码。)

  其次,同一媒体类型在不同的环境中,可能会需要不同的传输编码方式。例如,许多邮件的附言PostScript)部分完全是由7位数据的短行组成,因此不需要编码。而其它的(特别是那些使用Level 2 PostScript二进制编码机制的)附言可能需要使用二进制传输编码进行描述。

  最后,因为“Content-Type”已经被制定为可扩充式的规范机制,所以,如果严格定义媒体类型与编码的关系,就会将应用协议的定义与更低层的传输细节相结合。而这是不合乎 要求的,因为媒体类型的设计者不一定需要知道所有会被使用的传输方式及其局限性。

编码转换

  可以在“quoted-printable”“base64”编码方式之间进行转换操作。只有当需要在“quoted-printable”编码中强制输出换行符的时候才需要这种操作。从“quoted-printable”转换到“base64”格式的时候,“quoted-printable”码中的换行符被表示为CRLF序列。因此,它必须被转换为用“base64”方式编码后的相应内容。同样,解码后数据中的CRLF序列也必须被转换成 “quoted-printable”的强制换行符,但这只适用于文本情况。

规范的编码模式

  (Canonical Encoding Model

  何时将邮件数据转换为标准形式并编码、这个过程如何处理CRLF(新行符,并且在不同的系统中具有不同的形式)、传输编码与字符集之间有什么关系――在以前版本的RFC中,关于这些方面的问题都很混乱。由于这个原因,RFC2049给出了编码的规范模型。

Quoted-Printable编码

  Quoted-Printable编码适用于内容多为US-ASCII字符集中可打印字符的情况。经过它编码的数据不再需要邮件传输系统进行转换。如果被编码的数据多为US-ASCII字符,则编码后的内容会保留那些可人为识别的部分。完全由US-ASCII字符构成的内容也可以进行Quoted- Printable编码,以确保可以通过字符转换及(或)行封装的网关来传递所有的消息 数据。

0 0
原创粉丝点击