1.如同其他电子文档格式一样,电子邮件内容也必须遵循一定的格式要求,各种处理程序才能从中分析和提取发件人,收件人,主题和附件等信息,邮件的基本内容和具体格式分别由RFC822和MIME协议定义。
1.1RFC822邮件格式:
邮件内容的格式在RFC822文档定义,它包括两个主要的组成部分:邮件头和邮件体。如图列出了邮件的内容:
上图的1-15行是邮件的邮件头,第17行是邮件的邮件体,邮件头和邮件体之间以一个空格进行分隔。这封邮件的邮件体内容非常少,只有一行test!!!文本。邮件头部分由多个头字段和字段内容组成,各种头字段分别用于表示邮件的发件人,收件人,发件时间和主题信息等。还有一些信息是各个SMTP服务器在传送邮件的过程中加上的。SMTP服务器在传递邮件时,会把一些相关的信息增加到邮件的邮件头中,这种情况类似于现实生活中的邮局在处理邮件时,通常会在信封上加盖邮戳一样,表示这份邮件在什么时候经过了哪个邮局有那个工作人员经手处理。SMTP服务器按从下往上的方式添加各个字段,即先添加的字段位于后添加的字段下面,例如上图邮件是有sina发给sohu的,它首先经过sina的SMTP服务器,然后经过sohu的SMTP服务器,所以sohu的SMTP服务器添加的头字段(1-5行)位于sina的SMTP服务器添加的头字段(6-8行)的上面。另外pop3服务器也会在邮件头中增加一些头字段,例如上图的12-15行,第17行是邮件的邮件体,邮件头和邮件体用一个空格分隔。
每个邮件头以“字段名: 字段值”的格式出现,即每一行的邮件头的内容依次由字段名,冒号,空格,字段值,回车换行组成。RFC822文档中定义了多个标准的邮件头字段,每个邮件头字段表示一种特定的信息。邮件头中也可以包含自定义的头字段,不过这种自定义的头字段一般是由某个组织或者某个机构内部专用。下面介绍一下一些主要的邮件头字段的解释。
~~Return-Path: 该字段代表邮件回复的地址,该字段内容由接收邮件的SMTP服务器填写,接收邮件的SMTP服务器从邮件发送程序发出的mail from命令中获得该字段内容。
~~Received: 该字段的基本格式为 Received from A by B for C,其中A为发送方,B为接收方,C为收件人的邮箱地址。该字段的内容由接收邮件的SMTP服务器填写,常常被用来追踪邮件传输的路线和分析邮件的来源,例如上图的Received字段中,可以知道这封邮件的传输路径:从IP地址为【218.246.5.151】的机器上发出--》【smtp.sina.com】--》【sohumx.sohu.com】-->【it315_test@sohu.com】.上图中的第6行的“Received:(qmail49221 invoked from network)”是sina的SMTP服务器接收到邮件后在通过这个邮件发送模板将邮件转发出去。显然,通过分析这封邮件的源内容,就可以知道发件人的IP地址。
~~From:该字段用于指定发件人的地址,邮件阅读程序显示的发件人地址来源于这个字段。Form字段中指定的发件人地址可以随意填写,甚至不写,所以邮件程序阅读显示的发件人地址不一定是真实的,这通常可以通过查收邮件头中的Return-Path字段来判断发件人的真实性。注意SMTP协议中 mail from命令中指定的发件人地址可以伪造,所以邮件头中的Return-Path字段也不是完全可以信赖的,对于比较重要的邮件,还是打电话确认一下。
to:该字段用于指定收件人地址
subject:用于指定邮件的主题,如果主题中包含有ASCII码以外的字符,通常要对其内容进行编码。
data:该字段用于指定邮件的发送时间
邮件头中除了包含上面的这些字段以外,还有另外两个比较常用的字段,~~cc:该字段用于指定邮件的抄送人地址。~~bcc:该字段用于指定邮件的暗送地址。
抄送地址和暗送地址的区别在于:邮件阅读程序通常只显示抄送地址而不会显示暗送地址。
邮件阅读程序在显示邮件信息时,所显示出来的发件人,收件人和主题等信息就是从相应的邮件头字段中提取出来的。
2.MIME协议:
RFC822文档定义了邮件内容的主体结构和各种邮件头字段的详细细节,但是,它没有定义邮件体格式,RFC822文档定义的邮件体部分通常只能用于表述一段普通文本,而无法表达出图片,声音等二进制数据。另外SMTP服务器在接收邮件内容时,当接收到一个“.”字符的单独行时,就会认为邮件内容已经结束。如果一封邮件正文中正好内容仅为一个“.”字符的单独行时,SMTP服务器就会丢弃掉改行后面的内容,从而导致信息丢失。
由于社会的发展人们已经不满足于邮件仅仅用来文本信息,由于声音,图片,动画和附件等内容都是非ASCII编码的二进制数据,所以我们采用某种编码方式将他们编码成可打印的ASCII字符串后在做RFC822邮件格式内容。邮件阅读程序在读取到这种编码处理的邮件后,在按照相应的解码方式解码出原始的二进制数据,这样就可以借助RFC822邮件格式来传递多媒体数据了。这种方式需要解决2个技术点
1.邮件阅读程序如何知道邮件中嵌入的原始二进制数据采用的编码方式
2.邮件阅读程序如何知道每个嵌入的图像或其他资源在整个邮件中的起始位置。
针对这个问题人们定义了MIME邮件协议
MIME协议用于定义复杂邮件体的格式,它可以表达多段平行的文本内容和非文本的邮件内容,例如在邮件中嵌套图片数据和附件等。MIME邮件协议也可以避免邮件内容在传输过程中信息丢失。
另外,MIME邮件也扩展了RFC822文档中定义的邮件头的内涵。例如,定义了subject头字段中的值的内容格式,以便通过编码的方式让邮件主题中也可以使用非ASCII编码的字符,subject头字段的值嵌套在一对“=?”和“?=”标记符之间,标记符之间的内容有3部分组成:邮件主题的原始内容字符集,当前采用的编码方式,编码后的结果,这3部分之间使用“?”进行分隔。下面是例子:
其中gb2312部分说明主题内容的编码方式为gb2312编码的字符文本,B部分说明对邮件主题的原始内容按照BASE64方式进行编码,后面一段为BASE64编码的结果。
2.2MIME邮件的组织结构:
一封MME邮件可以由多个不同类型的MIME消息组合而成,一个MIME消息表示邮件中的一个基本MIME资源或若干个基本的MIME消息的组合体。每个MIME消息的数据格式与RFC822数据格式相似,也包括头和体两部分,分别称为MIME消息头和MIME消息体,他们之间使用空格分隔。MIME消息体中包含了资源的具体内容,MIME消息头中则包含了对资源信息的描述。多个相同层次的MIME消息必须形成一个MIME组合消息,他们共同作为所形成的MIME组合消息的MIME消息体,相互之间采用某种分隔标识符进行分隔,MIME组合消息的消息头中需要描述其中多个MIME消息的组合类型和分隔标识符。一个MIME组合消息还可以在与其他MIME消息共同形成一个更大的MIME组合消息,这样就形成了一种多层嵌套的组合关系,一封MIME邮件就是按照这种组合方式所形成的一个最顶层的MIME组合消息。
如下图的一封邮件:
这封邮件的正文由一段HTML格式的文本和其引用的一个图片,以及两个附件:一个WAV声音文件,一个EXE可执行文件。其中HTML,图片,WAV,EXE用4个独立的MIME消息表示,HTML文本内容和图片资源又组合成一个表示正文的MIME组合消息,这个MIME组合消息在于两个附件对应的MIME消息组合成一个更大的MIME组合消息,这就形成了整封邮件的MIME消息。如下图:
2.3MIME消息的头字段:
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消息可以由3中组合关系:混合,关联,选择,他们对应的MIME类型如下:
~~multipart/mixed:表示消息体的内容是混合组合类型,内容可以是文本,声音和附件等不同的邮件内容的混合体。如上图的整封邮件的MIME就必须是multipart/mixed类型,
~~multipart/related:表示消息体中的内容是关联(依赖)的类型,例如上图中的邮件正文使用HTML代码引用内嵌的图片资源,他们组合成的MIME消息的MIME类型就是multipart/related,表示其中某些资源(HTML代码)要引用(依赖)另外的资源(图片或者数据),引用资源与被引用的资源必须组合成multipart/related类型的MIME组合消息。
~~multipart/alternative:表示消息体中的内容是选择组合类型,例如一封邮件的邮件正文同时采用HTML格式和普通文本格式进行表达时,就可以将他们嵌套在一个multipart/alternative类型的MIME组合消息中。这种做法的好处在于如果邮件阅读程序不支持HTML格式时,可以采用文本的格式进行替代。
一封最复杂的邮件的基本情况为:含邮件正文和邮件附件,邮件正文可以同时使用HTML格式和普通文本格式表示,并且HTML格式的正文中又引入了其他内嵌资源。对于这种最复杂的电子邮件,可以采用如下的MIME消息结构:
在Content-Type头字段中除了定义消息体的MIME类型外,还可以在MIME类型后面包含相应的属性,属性以“属性名=属性值”的形式出现,属性与MIME类型之间采用;分隔,如下所示:
2.Content-Transfer-Encoding头字段
Content-Transfer-Encoding头字段用于指定MIME消息体中的内容所采用的邮件编码方式。
3.Content-Disposition:
Content-Disposition头字段用于指定邮件阅读程序处理数据的内容方式,与inline和attachement两种标准方式;inline表示直接处理,attachement表示当做附件处理。如果将Content-Disposition设置为attachement,在其后还可以指定filename属性,如下所示:
上面的MIME头字段表示MIME消息体的内容为邮件附件,附件名为“1.bmp”
4.Content-ID头字段:
Content-ID头字段用于为“multipart/related”组合消息中的内嵌资源指定一个唯一标识号,在HTML的正文格式中可以使用这个唯一标识号来引用该内嵌资源。例如,假设将一个表示内嵌图片的MIME消息的Content-ID头字段设置为如下形式:
那么,在HTML正文中就需要使用如下HTML语句来引用该图片资源
注意:引用Content-ID头字段标识的内嵌资源时,要在资源的唯一标识号前面加上“cid”,以说明要采用唯一标识号对资源进行引用。
5.Content-Location头字段:
Content-Location头字段用于为内嵌资源设置一个URI地址,这个URI地址可以是绝对或者相对的。当使用Content-Location头字段为一个内嵌资源指定一个URI后,在HTML格式的正文中也可以使用这个URI来引用该内嵌资源。例如:假设将一个表示内嵌图片的MIME消息的Content-Location头字段设置如下:
那么,在HTML正文中就可以使用如下语句来引用该图片资源:
6.Content-Base头字段:
Content-Base头字段用于为内嵌资源设置一个基准路径,只有这样Content-Location头字段中设置的URI才可以采用相对地址,例如,假设将一个表示内嵌图片的MIME消息的Content-Base和Content-Location头字段设置为如下格式:
那么,内嵌资源的完整路径就是Content-Base头字段设置的基准路径与Content-Location头字段设置的相对路径相加的结果,那么就可以在HTML正文中就可以使用如下HTML语句引用该图片资源:
3.MIME邮件的编码方式:
有两种编码方式BASE64和