邮件mime格式

参考:

rfc4021,Registration of Mail and MIME Header Fields,

 

总体来说,MIME消息由消息头和消息体两大部分组成。这里,分别称为为邮件头、邮件体。

邮件头

邮件头包含了发件人、收件人、主题、时 间、MIME版本、邮件内容的类型等重要信息。每条信息称为一个域,由域名后加“: ”和信息内容构成,可以是一行,较长的也可以占用多行。域的首行必须“顶头”写,即左边不能有空白字符(空格和制表符);续行则必须以空白字符打头,且第 一个空白字符不是信息本身固有的,解码时要过滤掉。

邮件头中不允许出现空行。有一些邮件不能被邮件客户端软件识别,显示的是原始码,就是因为首行是空行。

例如:

Date: Mon, 29 Jun 2009 18:39:03 +0800

From: "=?gb2312?B?26zQocHB?=" <gaoxl@legendsec.com>

To: "moreorless" <moreorless@live.cn>

Cc: "gxl0620" <gxl0620@163.com>

BCC: "=?gb2312?B?26zQocHB?=" <venus.oso@gmail.com>

Subject: attach

Message-ID: <200906291839032504254@legendsec.com>

X-mailer: Foxmail 6, 15, 201, 21 [cn]

Mime-Version: 1.0

邮件MIME格式分析_超文本


邮件体

在邮件体中,大致有如下一些域:

邮件MIME格式分析_编码方式_02

有的域除了值之外,还带有参数。值与参数、参数与参数之间以“;”分隔。参数名与参数值之间以“=”分隔。

邮件体包含邮件的内容,它的类型由邮件头的“Content-Type”域指出。常见的简单类型有text/plain(纯文本)和text/html(超文本)。

multipart类型,是MIME邮件的精髓。邮件体被分为多个段,每个段又包含段头和段体两部分,这两部分之间也以空行分隔。常见的multipart类型有三种:multipart/mixed, multipart/related和multipart/alternative。从它们的名称,不难推知这些类型各自的含义和用处。它们之间的层次关系可归纳为下图所示:

邮件MIME格式分析_字符串_03

可以看出,如果在邮件中要添加附件,必须定义multipart/mixed段;如果存在内嵌资源,至少要定义multipart/related段;如果纯文本与超文本共存,至少要定义multipart/alternative段。


示例:

邮件MIME格式分析_客户端_04


MIME编码

参考rfc2047,MIME Part Three:Message Header Extensions for Non-ASCII Text

 ​


MIME编码的两种方法:

对邮件进行编码最初的原因是因为Internet上的很多网关不能正确传输8bit内码的字符,比如汉字等。编码的原理就是把8bit的内容转换成7bit的形式以能正确传输,在接收方收到之后,再将其还原成8bit的内容。

MIME是“多用途网际邮件扩充协议”的缩写,在MIME协议之前,邮件的编码曾经有过UUENCODE等编码方式,但是由于MIME协议算法简单,并且易于扩展,现在已经成为邮件编码方式的主流,不仅是用来传输8 bit的字符,也可以用来传送二进制的文件,如邮件附件中的图像、音频等信息,而且扩展了很多基于MIME的应用。


从编码方式来说,MIME 定义了两种编码方法Base64与QP(Quote-Printable):

Base64

Base64是一种通用的方法,其原理很简单,就是把三个Byte的数据用4个Byte表示,这样,这四个Byte中,实际用到的都只有前面6 bit,这样就不存在只能传输7bit的字符的问题了。Base64的缩写一般是“B”。

Base64将输入的字符串或一段数据编码成只含有{'A'-'Z', 'a'-'z', '0'-'9', '+', '/'}这64个字符的串,'='用于填充。其编码的方法是,将输入数据流每次取6bit,用此6bit的值(0-63)作为索引去查表,输出相应字符。这样,每3个字节将编码为4个字符(3×8 → 4×6);不满4个字符的以'='填充。 Base64的算法很简单,它将字符流顺序放入一个24位的缓冲区,缺字符的地方补零。 然后将缓冲区截断成为4个部分,高位在先,每个部分6位,用64个字符重新表示。如果输入只有一个或两个字节,那么输出将用等号“=”补足。这可以隔断附加的信息造成编码的混乱。

QP

另一种方法是QP(Quote-Printable)方法,通常缩写为“Q”方法,其原理是把一个8 bit 的字符用两个16进制数值表示,然后在前面加“=”。所以我们看到经过QP编码后的文件通常是这个样子:=B3=C2=BF=A1=C7=E5=A3=AC=C4=FA=BA=C3=A3=A1。

QP编码要求编码后每行不能超过76个字符。当超过这个限制时,将使用软换行,用”=”表示编码行的断行,后接CRLF。(76的限制包括”=”)。

“=” 等号被编码为”=3D”。

tab和空格出现在行尾时,需要被编码为”=09”(tab) “=20”(space)

编码格式:encoded-word = "=?" charset "?" encoding "?" encoded-text "?="

编码信息有"=?"和"?="括起来,"=?"后是字符集名称,再一个"?"后是编码方式,再一个"?"后是编码后的字符串。字符集和编码方式都不区分大小写。

字符集可以是任意系统支持的字符集(iso-8859-1、utf-8、gb2312、gbk、gb18030....)


邮件MIME格式分析_编码方式_05

编码方式有两种:"B"或"b"代表base64编码;"Q"或"q"代表QP编码。

Generally, an "encoded-word" is a sequence of printable ASCII characters that begins with "=?", ends with "?=", and has two "?"s in between. It specifies a character set and an encoding method, and also includes the original text encoded as graphic ASCII characters, according to the rules for that encoding method.


SMTP与MIME的关系

邮件MIME格式分析_编码方式_06

从上图可以看出发件人、收件人地址都出现了两次,一次在smtp命令中(SMTP email address),一次在邮件正文中(MIME email address)。需要注意的是:


    1. 邮件正文中可以包含发件人、收件人的别名,smtp命令中不可以
    2. 密送人的地址不一定会出现在邮件正文中。不同客户端实现不同。