MIME协议详解.docx

上传人:b****6 文档编号:8659728 上传时间:2023-02-01 格式:DOCX 页数:16 大小:134.86KB
下载 相关 举报
MIME协议详解.docx_第1页
第1页 / 共16页
MIME协议详解.docx_第2页
第2页 / 共16页
MIME协议详解.docx_第3页
第3页 / 共16页
MIME协议详解.docx_第4页
第4页 / 共16页
MIME协议详解.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

MIME协议详解.docx

《MIME协议详解.docx》由会员分享,可在线阅读,更多相关《MIME协议详解.docx(16页珍藏版)》请在冰豆网上搜索。

MIME协议详解.docx

MIME协议详解

3.2 MIME协议

RFC822文档定义了邮件内容的主体结构和各种邮件头字段的详细细节,但是,它没有定义邮件体的格式,RFC822文档定义的邮件体部分通常都只能用于表述一段普通的文本,而无法表达出图片、声音等二进制数据。

另外,SMTP服务器在接收邮件内容时,当接收到只有一个“.”字符的单独行时,就会认为邮件内容已经结束,如果一封邮件正文中正好有内容仅为一个“.”字符的单独行,SMTP服务器就会丢弃掉该行后面的内容,从而导致信息丢失。

由于Internet的迅猛发展,人们已不满足于电子邮件仅仅是用来交换文本信息,而希望使用电子邮件来交换更为丰富多彩的多媒体信息,例如,在邮件中嵌入图片、声音、动画和附件。

但是,由于图片和声音等内容是非ASCII码的二进制数据,而RFC822邮件格式只适合用来表达纯文本的邮件内容,所以,要使用RFC822邮件格式发送这些非ASCII码的二进制数据时,必须先采用某种编码方式将它们“编码”成可打印的ASCII字符后再作为RFC822邮件格式的内容。

邮件阅读程序在读取到这种经过编码处理的邮件后,再按照相应的解码方式解码出原始的二进制数据,这样就可以借助RFC822邮件格式来传递多媒体数据了。

这种做法需要解决一下两个技术问题:

(1)邮件阅读程序如何知道邮件中嵌入的原始二进制数据所采用的编码方式;

(2)邮件阅读程序如何知道每个嵌入的图像或其他资源在整个邮件内容中的起止位置。

针对这个问题,人们后来专门为此定义了MIME(MultipurposeInternetMailExtension,多用途Internet邮件扩展)协议。

MIME协议用于定义复杂邮件体的格式,它可以表达多段平行的文本内容和非文本的邮件内容,例如,在邮件体中内嵌的图像数据和邮件附件等。

另外,MIME协议的数据格式也可以避免邮件内容在传输过程中发生信息丢失。

MIME协议不是对RFC822邮件格式的升级和替代,而是基于RFC822邮件格式的扩展应用。

一言以蔽之,RFC822定义了邮件内容的格式和邮件头字段的详细细节,MIME协议则是定义了如何在邮件体部分表达出的丰富多样的数据内容。

一个采用了MIME协议的电子邮件就叫做MIME邮件,MIME邮件在RFC822文档中定义的邮件头字段的基础上,扩充了一些自己专用的邮件头字段,例如,使用MIME-Version头字段指定MIME协议的版本,使用Content-Type头字段指定邮件体的MIME类型,使用Content-Transfer-Encoding头字段指定编码方法,如下所示:

MIME-Version:

1.0

Content-Type:

multipart/mixed;boundary="----=_NextPart_000_0050_01C"

其中,“multipart/mixed”部分说明邮件体中包含有多段数据,每段数据之间使用boundary属性中指定的字符文本作为分隔标识符。

另外,MIME邮件也扩展了RFC822文档中已经定义了的邮件头字段的内涵,例如,定义了subject头字段中的值内容的格式,以便通过编码的方式让邮件主题中也可以使用非ASCII码的字符。

subject头字段中的值嵌套在一对“=?

”和“?

=”标记符之间,标记符之间的内容由三部分组成:

邮件主题的原始内容的字符集、当前采用的编码方式、编码后的结果,这三部分之间使用“?

”进行分隔。

下面是一个对包含有非ASCII码字符的邮件主题进行了编码后的结果:

Subject:

=?

gb2312?

B?

TUlNRdCt0unLtcP308q8/g==?

=

其中,“gb2312”部分说明邮件主题的原始内容为gb2312编码的字符文本,“B”部分说明对邮件主题的原始内容按照BASE64方式进行了编码,“TUlNRdCt0unLtcP308q8/g==”为对邮件主题的原始内容进行了BASE64编码后的结果。

可见,MIME邮件与普通的RFC822邮件的关系犹如Java编程语言中的子类与父类的关系,子类是对父类的扩展,子类功能更强大,但子类离不父类的支持。

如果需要了解MIME的详细细节,可以查阅RFC2045~2049系列文档。

3.3 MIME邮件的组织结构

一封MIME邮件可以由多个不同类型的MIME消息组合而成,一个MIME消息表示邮件中的一个基本MIME资源或若干基本MIME消息的组合体。

每个MIME消息的数据格式与RFC822数据格式相似,也包括头和体两部分,分别称为MIME消息头和MIME消息体,它们之间使用空行分隔。

MIME消息体中包含了资源的具体内容,MIME消息头中则包含了对资源的描述信息。

多个相同层次的MIME消息必须形成一个MIME组合消息,它们共同作为所形成的MIME组合消息的MIME消息体,相互之间采用某种分隔标识符进行分隔,MIME组合消息的消息头中需要描述其中的多个MIME消息的组合类型和分隔标识符。

一个MIME组合消息还可以再与其他MIME消息共同形成一个更大的MIME组合消息,这样就形成了一种多层嵌套的组合关系,一封MIME邮件就是按这种组合方式所形成的一个最顶层的MIME组合消息。

MIME协议采用这种多层组合方式可以表达出复杂的邮件内容,例如,对于在OutLookExpress中显示出的如图3.4所示效果的一封复杂邮件,可以采用图3.5所示的MIME组合结构来表达。

图3.4中的邮件正文为一段HTML格式的文本和其引用的一个图片资源,该邮件还包含两个附件:

一个是WAV声音文件,一个是EXE可执行文件。

该邮件的MIME结构如图3.5所示,其中的HTML文本内容、图片资源和两个附件用四个独立的MIME消息表示,HTML文本内容和图片资源又组合成一个表示邮件正文的MIME组合消息,这个MIME组合消息再与两个附件对应的MIME消息组合成了一个更大的MIME组合消息,这就形成了整封邮件的MIME消息。

图3.4

3.4 MIME消息的头字段

3.4.1 Content-Type

对于表示某个具体资源的MIME消息,它的消息头中需要指定资源的数据类型;对于MIME组合消息,它的消息头中需要指定组合关系。

具体资源的数据类型和组合消息的组合关系,都是通过消息头中的Content-Type头字段来指定的。

Content-Type字段中的内容以“主类型/子类型”的形式出现,主类型有text、image、audio、video、application、multipart、message等,分别表示文本、图片、音频、视频、应用程序、组合结构、消息等。

每个主类型下面都有多个子类型,例如text主类型包含plain、html、xml、css等子类型。

multipart主类型用于表示MIME组合消息,它是MIME协议中最重要的一种类型。

一封MIME邮件中的MIME消息可以有三种组合关系:

混合、关联、选择,它们对应MIME类型如下:

— multipart/mixed

表示消息体中的内容是混和组合类型,内容可以是文本、声音和附件等不同邮件内容的混和体,例如图3.5中的整封邮件的MIME类型就必须定义为multipart/mixed。

— multipart/related

表示消息体中的内容是关联(依赖)组合类型,例如图3.5中的邮件正文要使用HTML代码引用内嵌的图片资源,它们组合成的MIME消息的MIME类型就应该定义为multipart/related,表示其中某些资源(HTML代码)要引用(依赖)另外的资源(图像数据),引用资源与被引用的资源必须组合成multipart/related类型的MIME组合消息。

— multipart/alternative

表示消息体中的内容是选择组合类型,例如一封邮件的邮件正文同时采用HTML格式和普通文本格式进行表达时,就可以将它们嵌套在一个multipart/alternative类型的MIME组合消息中。

这种做法的好处在于如果邮件阅读程序不支持HTML格式时,可以采用其中的文本格式进行替代。

一封最复杂的电子邮件的基本情况为:

含有邮件正文和邮件附件,邮件正文可以同时使用HTML格式和普通文本格式表示,并且HTML格式的正文中又引用了其他的内嵌资源。

对于这种最复杂的电子邮件,可以采用如图3.6所示的MIME消息结构进行描述。

图3.6

从图3.6中可以看出,如果要在邮件中要添加附件,就必须将整封邮件的MIME类型定义为multipart/mixed;如果要在HTML格式的正文中引用内嵌资源,那就要定义multipart/related类型的MIME消息;如果普通文本内容与HTML文本内容共存,那就要定义multipart/alternative类型的MIME消息。

注意:

如果整封邮件中只有普通文本内容与HTML文本内容,那么整封邮件的MIME类型则应定义为multipart/alternative;如果整封邮件中包含有HTML文本内容和内嵌资源,但不包含附件,那么整封邮件的MIME类型则应定义为multipart/related。

在Content-type头字段中除了可以定义消息体的MIME类型外,还可以在MIME类型后面包含相应的属性,属性以“属性名=属性值”的形式出现,属性与MIME类型之间采用分号(;)分隔,如下所示:

Content-Type:

multipart/mixed;boundary="----=_NextPart_000_0050_01C"

常用的属性如表3.1所示。

表3.1

主 类 型

属 性 名

说   明

text

charset

用于说明文本内容的字符集编码

image

name

用于说明图片文件的文件名

application

name

用于说明应用程序的文件名

multipart

boundary

用于定义MIME消息之间的分隔符

3.4.2 其他头字段

除了Content-Type头字段之外,MIME协议中还定义Content-Transfer-Encoding、Content-Disposition、Content-ID、Content-Location、Content-Base等几个重要的头字段,这几个头字段需要与Content-type头字段配合使用,它们的作用如下:

— Content-Transfer-Encoding头字段

Content-Transfer-Encoding头字段用于指定MIME消息体中的内容所采用的邮件编码方式,详细细节请参看3.4节的讲解。

— Content-Disposition头字段

Content-Disposition头字段用于指定邮件阅读程序处理数据内容的方式,有inline和attachment两种标准方式,inline表示直接处理,而attachment表示当做附件处理。

如果将Content-Disposition设置为attachment,在其后还可以指定filename属性,如下所示:

Content-Disposition:

attachment;filename="1.bmp"

上面的MIME头字段表示MIME消息体的内容为邮件附件,附件名"1.bmp"。

— Content-ID头字段

Content-ID头字段用于为“multipart/related”组合消息中的内嵌资源指定一个唯一标识号,在HTML格式的正文中可以使用这个唯一标识号来引用该内嵌资源。

例如,假设将一个表示内嵌图片的MIME消息的Content-ID头字段设置为如下形式:

Content-ID:

it315logo_gif

那么,在HTML正文中就需要使用如下HTML语句来引用该图片资源:

it315logo_gif">

注意,在引用Content-ID头字段标识的内嵌资源时,要在资源的唯一标识号前面加上“cid:

”,以说明要采用唯一标识号对资源进行引用。

— Content-Location头字段

Content-Location头字段用于为内嵌资源设置一个URI地址,这个URI地址可以是绝对或相对的。

当使用Content-Location头字段为一个内嵌资源指定一个URI地址后,在HTML格式的正文中也可以使用这个URI来引用该内嵌资源。

例如,假设将一个表示内嵌图片的MIME消息的Content-Location头字段设置为如下形式:

Content-Location:

http:

//www.it315.org/images/it315logo.gif

那么,在HTML正文中就可以使用如下HTML语句来引用该图片资源:

//www.it315.org/images/it315logo.gif">

— Content-Base头字段

Content-Base头字段用于为内嵌资源设置一个基准路径,只有这样,Content-Location头字段中设置的URI才可以采用相对地址。

例如,假设将一个表示内嵌图片的MIME消息的Content-Base和Content-Location头字段设置为如下形式:

Content-Base:

http:

//www.it315.org/images/

Content-Location:

it315logo.gif 

那么,内嵌资源的完整路径就是Content-Base头字段设置的基准路径与Content-Location头字段设置的相对路径相加的结果,在HTML正文中就可以使用如下HTML语句来引用该图片资源:

//www.it315.org/images/it315logo.gif">

3.5 MIME邮件的编码方式

由于每个ASCII码字符只占用一个字节(8个bit位),且最高bit位总为0,即ASCII码字符中的有真正意义的信息只是后面的7个低bit位,而传统的SMTP协议又是基于ASCII码字符设计的,因此,一些基于传统SMTP协议设计的SMTP服务器在处理邮件内容时只取出每个字节中的7个低bit位进行处理,而将最高bit位忽略不计。

显然,这样的SMTP服务器在处理包含有非ASCII码字符的邮件内容时,会出现严重的问题,这就限制了邮件中只能出现英文的ASCII码字符,而不能出现中文字符或二进制数据。

为了能够在邮件内容中包含中文、图像或声音等非ASCII字符的数据,人们想到了采用某种编码方式将非ASCII字符的数据转换成可打印的ASCII字符后再发送,邮件阅读程序则按照相应的解码方式从邮件中还原出原始数据即可,比较常用的两种邮件编码方式为BASE64和Quoted-printable。

后来的扩展SMTP协议允许直接在邮件中传递二进制数据,而不用对它们进行邮件编码,人们将这种没有进行邮件编码的二进制数据的邮件内容称为8bit编码,为了与此相区别,人们将没有进行邮件编码的纯ASCII码字符的邮件称为7bit编码。

MIME消息体的邮件编码方式通过MIME消息头中的Content-Transfer-Encoding头字段指定,每种邮件编码方式的介绍如下:

— 7Bit

指消息体内容全部是没有经过编码的ASCII字符。

— 8Bit

指消息体内容是没有经过编码的原始数据,且其中包含有非ASCII字符的数据。

现在的邮件服务器基本上都支持8Bit编码,使用支持8Bit编码的邮件服务器可以简化邮件的处理过程。

— BASE64

Base64是将二进制数据转换成可打印的ASCII字符的一种最常见的编码方式,它的基本原理是将一组连续的字节数据按6个bit位进行分组,然后对每组数据用一个ASCII字符来表示。

6个bit位最多能表示26=64个数值,因此可以使用64个ASCII字符来对应这64个数值,这64个ASCII字符为:

"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

其中每个字符表示的数值就是该字符在上面的排列中的索引号,索引号从0开始编号。

假设在内存中有如下三个连续的字节数据:

[0110,0001][0110,0010][0110,0011]

将它们按6个bit位进行分组后的形式如下:

[0110,00][01,0110,][0010,01][10,0011]

分组后得到了四组数据,每组数据对应的十进制数值分别为24、22、9、35,它们分别对应Y、W、J、j这四个字符,所以,对[0110,0001][0110,0010][0110,0011]这三个字节的数据进行BASE64编码后的结果是“YWJj”。

BASE64编码要求把3个8位字节(即24个bit)的数据转化为4个6位字节(也是24个bit)的数据,如果原来的8位字节数据的字节个数不能被3整除,其余数只能是1或2,那么如何对余下的1个或2个8位字节数据进行处理呢?

对于这种情况,仍然按6个bit位对剩余的字节进行分组,在最后不够6个bit位的内容后面添加几个为0的bit位来凑成6个bit位,例如,如果最后剩下的一个8位字节的内容如下:

[0110,0001]

对它进行分组后的结果如下:

[0110,00][01,0000]

其中用黑斜体标识的0为填充的bit位,所以,最后剩下的这个字节的BASE64编码结果为“YQ”。

BASE64编码还有规定,如果编码后的整个结果文本的字符个数不是4的整数倍,那么需要在最后填充“=”字符来凑成4的倍数,所以,在最后这个字节编码的结果后面还要添加两个“=”字符,即“YQ==”。

显然,如果最后剩下两个8位字节的内容,它可以被编码成三个字符,最后还需要添加一个“=”字符。

对一大段数据进行BASE64编码时,可以在编码结果中的适当位置加入回车换行,MIME规范建议BASE64编码结果中的每行最多76个字符。

— Quoted-printable

Quoted-printable也是一种将二进制数据转换成可打印的ASCII字符的编码方式,它对ASCII字符不进行转换,只对非ASCII字符的数据进行编码转化。

每个非ASCII字符的字节数据,都被转换成一个"="号后跟这个字节的十六进制数据,例如,“ab中国”的Quoted-printable编码结果为“ab=d6=d0=b9=fa”。

显然,由于"="号在Quoted-printable编码中具有的特殊意义,所以,原始数据中的"="号字符也需要进行编码转换,用“=3d”表示。

对一大段数据进行Quoted-printable编码时,可以在编码结果中的适当位置加入回车换行,在回车换行前需要额外再加入一个“=”字符,以表示后面的换行是因编码而造成的软回车,而非原始数据中原有的回车换行。

例如,对于下面一段Quoted-printable编码后的数据:

=D5=E2=CA=C7=CD=A8=D0=C5=B5=C4=B3=CC=D0=

=F2,=C7=EB=D6=B8=BD=CC!

在第一行末尾的“=”字符和换行,都是由于编码后生成的。

3.6 MIME实例分析

了解MIME协议的基本组织结构后,下面用OutlookExpress撰写出一封显示效果如图3.4所示的电子邮件,然后分析该邮件的源文件,以便读者更加深入地了解MIME协议。

 启动OutlookExpress,单击工具栏中的“创建邮件”按钮,在打开的“新邮件”对话框中输入收件人地址、主题和邮件正文,然后选中邮件正文,单击编辑窗口的工具栏上的“》”按钮,在弹出的菜单栏中单击表示超链接的图标,如图3.7所示。

图3.7

 在打开的“超级链接”对话框中输入如图3.8所示的内容,然后单击“OK”按纽。

图3.8

 再次单击编辑窗口的工具栏上的“》”按钮,在打开的如图3.7所示的菜单栏中单击表示图片的图标,在打开的“图片”对话框中单击“浏览”按钮,然后通过打开的对话框选择一个图片文件,结果如图3.9所示。

 单击图3.9中的“OK”按钮,结果如图3.10所示。

图3.9

图3.10

 单击图3.10所示窗口中的“插入”à“文件附件”菜单项,在打开的“插入附件”对话框窗口中选择需要发送的附件,如图3.11所示。

单击“附件”按钮,插入所选中的附件。

 单击图3.10所示窗口中的“文件”à“保存”菜单项,在OutlookExpress主窗口的“草稿”目录中就可以看到这封邮件,如图3.12所示。

图3.11

图3.12

 将这封邮件从“草稿”目录中移动到“发件箱”目录中,接着按照3.1节中讲解的查看邮件源文件步骤,打开刚才撰写的这封邮件的源文件。

或者在“草稿”目录中选中这封邮件,将它另存为一个eml文件,再用任意一种文本编辑程序打开这个eml文件,这样也可以查看到刚才撰写的这封邮件的源文件。

为了便于读者看清邮件内容的组织结构关系,笔者专门为此画了一个描述邮件中的各个MIME消息分隔符的层次关系的示意图,如图3.13所示。

从图3.13中可以看出,在MIME组合消息的消息体中的每个消息单元都要以一个分割符开始,在组合消息的消息体结束时还需要用一个结束分割符。

MIME消息中的分隔符的层次关系与一篇文章中的标题之间的层次关系非常相似,只是在每个组合消息结束时还要增加一个结束“标题”。

为了便于讲解,笔者对刚才撰写的邮件源文件内容进行了适当修改,并添加了相应的注释,如下所示:

图3.13

1:

From:

"it315"<*******************>

2:

To:

<*******************>

3:

Subject:

=?

gb2312?

B?

TUlNRdCt0unLtcP308q8/g==?

=

4:

Date:

Thu,1Dec200520:

46:

53+0800

5:

MIME-Version:

1.0

6:

Content-Type:

multipart/mixed;//定义邮件体类型为mixed

7:

boundary="----=_NextPart_000_0050_01C"//定义整个邮件内容的分隔符

8:

X-Priority:

3

9:

X-MSMail-Priority:

Normal

10:

X-Mailer:

MicrosoftOutlookExpress6.00.2900.2670

11:

X-MimeOLE:

ProducedByMicrosoftMimeOLEV6.00.2900.2670

12:

13:

Thisisamulti-partmessageinMIMEformat.//邮件注释

14:

//整个邮件内容的第一部分(即邮件正文)的开始标记

15:

------=_NextPart_000_0050_01C

16:

Content-Type:

multipart/related;

17:

type="multipart/alternative";

18:

boundary="----=_NextPart_001_0051_01C"//定义邮件正文内部的分隔符

19:

   //邮件正文内部的第一部分的开始标记

20:

------=_NextPart_001_0051_01C

21:

Content-Type:

multipart/alternative;

       //定义邮件正文内部的第一部分的内部分隔符

22:

boundary="----=_NextPart_002_0052_01C"

23:

       //邮件正文内部的第一部分的第一部分的开始标记

24:

------=_Ne

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 职业教育 > 职高对口

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1