全面理解电子邮件

电子邮件系统的组成

传统电子邮件系统

一个电子邮件系统应具有三个主要组成部分:用户代理、邮件服务器、邮件发送协议(如SMTP)与邮件读取协议(如POP)。
在这里插入图片描述
用户代理(User Agent)就是用户与电子邮件系统的接口,在大多数情况下它就是运行在用户PC机中的一个程序。一般具有撰写、显示、处理、通信等功能。

因特网上有许多邮件服务器可供用户选择,邮件服务器24小时不间断地工作,并且具有大容量的邮件信箱。邮件服务器的功能是发送和接收邮件,同时还要向发信人报告邮件传送的情况(已交付、被拒绝、丢失等)。邮件服务器按照客户服务器方式工作。邮件服务器需要使用发送和读取两个不同的协议。

应当注意的是,一个邮件服务器既可以作为客户,也可以作为服务器。

例如,当邮件服务器 A 向另一个邮件服务器 B 发送邮件时,邮件服务器 A就作为 SMTP 客户,而 B 是 SMTP 服务器。

当邮件服务器 A 从另一个邮件服务器 B 接收邮件时,邮件服务器 A就作为 SMTP 服务器,而 B 是 SMTP 客户。

发送和接收电子邮件的几个重要步骤:

(1)发件人调用 PC 中的用户代理撰写和编辑要发送的邮件。

(2)发件人的用户代理把邮件用SMTP 协议发给发送方邮件服务器。

(3)SMTP 服务器把邮件临时存放在邮件缓存队列中,等待发送。

(4)发送方邮件服务器的SMTP 客户与接收方邮件服务器的 SMTP 服务器建立 TCP 连接,然后就把邮件缓存队列中的邮件依次发送出去

(5)运行在接收方邮件服务器中的SMTP服务器进程收到邮件后,把邮件放入收件人的用户邮箱中,等待收件人进行读取。

(6)收件人在打算收信时,就运行 PC 机中的用户代理,使用 POP3(或 IMAP)协议读取发送给自己的邮件。请注意,POP3 服务器和 POP3 客户之间的通信是由 POP3 客户发起的。

基于万维网的电子邮件系统

现在我们大多数情况下都是使用基于万维网的电子邮件,outlook之类的用户代理客户端已经渐渐退出了市场。

不管在什么地方,只要能够上网,就可以借助浏览器收发电子邮件。这时,邮件系统中的用户代理就是普通的万维网浏览器。

需要注意的是,浏览器从邮件服务器读取邮件,或者向邮件服务器发送邮件使用的是HTTP协议,而不是IMAP(POP)或SMTP。

例如,一个网易邮箱用户向新浪邮箱用户通过浏览器发送邮件,各阶段使用的协议如下:
在这里插入图片描述


相关应用层协议

邮件发送协议SMTP

1、SMTP协议简介

SMTP称为简单邮件传输协议(Simple Mail Transfer Protocal),目标是向用户提供高效、可靠的邮件传输。它的一个重要特点是它能够在传送中接力传送邮件,即邮件可以通过不同网络上的主机接力式传送。通常它工作在两种情况下:一是邮件从客户机传输到服务器;二是从某一个服务器传输到另一个服务器。SMTP是一个请求/响应协议,它监听25号端口,用于接收用户的Mail请求,并与远端Mail服务器建立SMTP连接。

2、SMTP协议工作机制
SMTP通常有两种工作模式。发送SMTP和接收SMTP。具体工作方式为:发送SMTP在接收到用户的邮件请求后,判断此邮件是否为本地邮件,若是直接投送到用户的邮箱,否则向DNS查询远端邮件服务器的MX记录,并建立与远端接收SMTP之间的一个双向传送通道,此后SMTP命令由发送SMTP发出,由接收SMTP接收,而应答则反方向传送。一旦传送通道建立,SMTP发送者发送MAIL命令指明邮件发送者。如果SMTP接收者可以接收邮件则返回OK应答。SMTP发送者再发出RCPT命令确认邮件是否接收到。如果SMTP接收者接收,则返回OK应答;如果不能接收到,则发出拒绝接收应答(但不中止整个邮件操作),双方将如此反复多次。当接收者收到全部邮件后会接收到特别的序列,入伏哦接收者成功处理了邮件,则返回OK应答。

3、SMTP的连接和发送过程

(a)建立TCP连接

(b)客户端发送HELO命令以标识发件人自己的身份,然后客户端发送MAIL命令;

     服务器端正希望以OK作为响应,表明准备接收

(c)客户端发送RCPT命令,以标识该电子邮件的计划接收人,可以有多个RCPT行;

     服务器端则表示是否愿意为收件人接收邮件

(d)协商结束,发送邮件,用命令DATA发送

(e)以.表示结束输入内容一起发送出去

(f)结束此次发送,用QUIT命令退出

一个发送示例如下:

C: telent SMTP.163.com 25  //以telenet方式连接163邮件服务器
S: 220 163.com Anti-spam GT for Coremail System //220为响应数字,其后的为欢迎信息
C: HELO SMTP.163.com //除了HELO所具有的功能外,EHLO主要用来查询服务器支持的扩充功能 
S: 250-mail
S: 250-AUTH LOGIN PLAIN
S: 250-AUTH=LOGIN PLAIN
S: 250 8BITMIME //最后一个响应数字应答码之后跟的是一个空格,而不是'-' 
C: AUTH LOGIN   //请求认证
S: 334 dxNlcm5hbWU6  //服务器的响应——经过base64编码了的“Username”=
C: Y29zdGFAYW1heGl0Lm5ldA==  //发送经过BASE64编码了的用户名
S: 334 UGFzc3dvcmQ6  //经过BASE64编码了的"Password:"=
C: MTk4MjIxNA==  //客户端发送的经过BASE64编码了的密码
S: 235 auth successfully  //认证成功 
C: MAIL FROM: [email protected]  //发送者邮箱
S: 250 … .  //“…”代表省略了一些可读信息
C: RCPT TO: [email protected] //接收者邮箱
S: 250 … .    // “…”代表省略了一些可读信息
C: DATA //请求发送数据
S: 354 Enter mail, end with "." on a line by itself
C: Enjoy Protocol Studing
C: .
S: 250 Message sent
C: QUIT //退出连接 
S: 221 Bye

其他命令:

VRFY——用于验证给定用户邮箱是否存在,以及接收关于该用户的详细信息;

EXPN——用于扩充邮件列表

4、邮件的路由过程

SMTP服务器是基于“域名服务DNS中计划收件人的域名来路由电子邮件”。SMTP服务器基于DNS中的MX记录来路由电子邮件,MX记录注册了域名和相关的SMTP中的主机,属于该域的电子邮件都应向该主机发送。

若SMTP服务器mail.abc.com收到一封信要发送到[email protected]

a: SendMail请求DNS给出主机sh.abc.com的CNAME记录,如有,假若CNAME到shmail.abc.com,则再次请求shmail.abc.com的CNAME记录,直到没有为止;

b: 假定被CNAME到shmail.abc.com,然后SendMail请求@abc.com域的DNS给出shmail.abc.com的MX记录,

shmail MX 5 shmail.abc.com

10 shmail2.abc.com

c: SendMail做好请求DNS给出shmail.abc.com的A记录,即IP地址,若返回值为1.2.3.4

d: SwndMail与1.2.3.4连接,传送这封信给[email protected]的信到1.2.3.4这台服务器的SMTP后台程序。

5、SMTP常用的命令

SMTP命令不区分大小写,但参数区分大小写。常用命令如下(<CRLF>表示回车换行):

命令 含义
HELO <domain> <CRLF> 向服务器标识用户身份发送者能欺骗、说谎,但一般情况下服务器都能检测到
RCPT TO: <forward-path> <CRLF> <forward-path>用来标志邮件接收者的地址,常用在MAIL FROM后,可以有多个RCPT TO
DATA <CRLF> 将之后的数据作为数据发送,以<CRLF>.<CRLF>标志数据的结尾
REST <CRLF> 重置会话,当前传输被取消
NOOP <CRLF> 要求服务器返回OK应答,一般用作测试
QUIT <CRLF> 结束会话
VRFY <string> <CRLF> 验证指定的邮箱是否存在,由于安全方面的原因,服务器大多禁止此命令
EXPN <string> <CRLF> 验证给定的邮箱列表是否存在,由于安全方面的原因,服务器大多禁止此命令
HELP <CRLF> 查询服务器支持什么命令

6、SMTP常用的响应

响应 含义
501 参数格式错误
502 命令不可实现
503 错误的命令序列
504 命令参数不可实现
211 系统状态或系统帮助响应
214 帮助信息
220<domain> 服务器就绪
221<domain> 服务关闭
421<domain> 服务器未就绪,关闭传输信道
250 要求的邮件操作完成
251 用户非本地,将转发向
450 要求的邮件操作未完成,邮箱不可用
550 要求的邮件操作未完成,邮箱不可用
451 放弃要求的操作,处理过程中出错
551 用户非本地,请尝试
452 系统存储不足,要求的操作未执行
552 过量的存储分配,要求的操作未执行
553 邮箱名不可用,要求的操作未执行
354 开始邮件输入,以“.”结束
554 操作失败

7、使用SMTP的必要性

一般的PC资源不够,处理能力不够,不可能全天候地连接在因特网上来收发邮件。所以使用SMTP服务器,可以让多个用户共用服务器,有效地降低了成本。

8、SMTP和邮件格式的关系

可以用一个比较形象的例子来说明:甲与乙书信来往,甲通过邮局向乙发送信件,邮局见转交邮件可看成使用了SMTP协议,至于书信的格式则会因为地区习惯等的不同而不同,这个书信格式可看成是邮件格式的标准。

9、浏览器发送邮件使用的协议

浏览器发送邮件的过程:

例如:[email protected]可通过登陆www.126.com来收发邮件

[email protected]在www.126.com提供的邮件页面上填写的相应信息(如发信人邮箱、收信人邮箱等),通过http协议被提交给126服务器;126服务器根据这些信息组装一封符合邮件规范的邮件(就像用户代理一样);然后smtp.126.com通过SMTP协议将这封邮件发送到接收端邮件服务器。

由此可知,浏览器发送邮件只是用户代理的功能直接放到邮件服务器上去做了,至于邮件服务器见发送邮件仍然采用的是SMTP协议。

邮件接收协议POP3

1、POP3概述
POP3全称为Post Office Protocol version3,即邮局协议第3版。它被用户代理用来邮件服务器取得邮件。POP3采用的也是C/S通信模型,对应的RFC文档为RFC1939。该协议非常简单,所以我们只重点介绍其通信过程,而相关的一些概念和术语请参考RFC文档或另外一篇文章《SMTP协议分析》

2、通信过程
用户从邮件服务器上接收邮件的典型通信过程如下。

  1. 用户运行用户代理(如Foxmail, OutlookExpress)。

  2. 用户代理(以下简称客户端)与邮件服务器(以下简称服务器端)的110端口建立TCP连接。

  3. 客户端向服务器端发出各种命令,来请求各种服务(如查询邮箱信息,下载某封邮件等)。

  4. 服务端解析用户的命令,做出相应动作并返回给客户端一个响应。

  5. 3)和4)交替进行,直到接收完所有邮件转到步骤6),或两者的连接被意外中断而直接退出。

  6. 用户代理解析从服务器端获得的邮件,以适当地形式(如可读)的形式呈现给用户。

其中2)、3)和4)用POP3协议通信。可以看出命令和响应是POP3通信的重点,我们将予以重点讲述。

3、pop3命令与响应
POP3的命令不多,它的一般形式是:COMMAND [Parameter]<CRLF>。其中COMMAND是ASCII形式的命令名,Parameter是相应的命令参数,<CRLF>是回车换行符(0DH, 0AH)。<SP>是空格

服务器响应是由一个单独的命令行组成,或多个命令行组成,响应第一行“+OK”或“-ERR”开头,然后再加上一些ASCII文本。“+OK”和“-ERR”分别指出相应的操作状态是成功的还是失败的。

POP3命令格式 说明
user<SP>username<CRLF> user 命令是POP3客户端程序与POP3邮件服务器建立连接后通常发送的第一条命令,参数 username 表示收件人的帐户名称。
pass<SP>password<CRLF> pass 命令是在user命令成功通过后,POP3客户端程序接着发送的命令,它用于传递帐户的密码,参数 password 表示帐户的密码。
apop<SP>name,digest<CRLF> apop 命令用于替代user和pass命令,它以MD5 数字摘要的形式向POP3邮件服务器提交帐户密码。
stat<CRLF> stat 命令用于查询邮箱中的统计信息,例如:邮箱中的邮件数量和邮件占用的字节大小等。
uidl<SP>msg#<CRLF> uidl 命令用于查询某封邮件的唯一标志符,参数msg#表示邮件的序号,是一个从1开始编号的数字。
list<SP>[MSG#]<CRLF> list 命令用于列出邮箱中的邮件信息,参数 msg#是一个可选参数,表示邮件的序号。当不指定参数时,POP3服务器列出邮箱中所有的邮件信息;当指定参数msg#时,POP3服务器只返回序号对应的邮件信息。
retr<SP>msg#<CRLF> retr 命令用于获取某封邮件的内容,参数 msg#表示邮件的序号。
dele<SP>msg# dele 命令用于在某封邮件上设置删除标记,参数msg#表示邮件的序号。POP3服务器执行dele命令时,只是为邮件设置了删除标记,并没有真正把邮件删除掉,只有POP3客户端发出quit命令后,POP3服务器才会真正删除所有设置了删除标记的邮件。
rest<CRLF> rest 命令用于清除所有邮件的删除标记。
top<SP>msg#<SP>n<CRLF> top 命令用于获取某封邮件的邮件头和邮件体中的前n行内容,参数msg#表示邮件的序号,参数n表示要返回邮件的前几行内容。使用这条命令以提高 Web Mail系统(通过Web站点上收发邮件)中的邮件列表显示的处理效率,因为这种情况下不需要获取每封邮件的完整内容,而是仅仅需要获取每封邮件的邮件头信息。
noop<CRLF> noop 命令用于检测POP3客户端与POP3服务器的连接情况。
quit<CRLF> quit 命令表示要结束邮件接收过程,POP3服务器接收到此命令后,将删除所有设置了删除标记的邮件,并关闭与POP3客户端程序的网络连接。

4、协议状态
POP3协议中有三种状态,认证状态,处理状态,和更新状态。命令的执行可以改变协议的状态,而对于具体的某命令,它只能在具体的某状态下使用,这些请参看表1和RFC193。

客户机与服务器刚与服务器建立连接时,它的状态为认证状态;一旦客户机提供了自己身份并被成功地确认,即由认可状态转入处理状态;在完成相应的操作后客户机发出QUIT命令(具体说明见后续内容),则进入更新状态,更新之后又重返认可状态;当然在认可状态下执行QUIT命令,可释放连接。状态间的转移如图 1所示。

---建立连接---|认可|--认证成功--|处理|--执行QUIT--|更新| 
                 |_______ -QUIT结束_________________|

5、一个例子
命令和响应的格式是语法,各命令和响应的意思则是语义,各命令和各响应在时间上的关系则是同步。我们还是通过以个简单的POP3通信过程来说明协议的这三个要素。

C:telnetpop3.126.com 110   /* 以telnet方式连接126邮件服务器 */

S:+OKWelcome to coremail Mail Pop3 Server(126coms[3adb99eb4207ae5256632eecb8f8b4855])/* +OK,代表命令成功,其后的信息则随服务器的不同而不同*/

C:USER bripengandre /*采用明文认证*/

S:+OKcore mail

C:PASS Pop3world /*发送邮箱密码*/

S:+OK654 message(s) [30930370 byte(s)] /*认证成功,转入处理状态 */

C:LIST 1 /*显示第一封邮件的信息 */

S:+OK1 5184 ./*第一封邮件的大小为5184字节 */

C:UIDL1 /*返回第一封邮件的唯一标识符 */

S:+OK1 1tbisBsHaEX9byI9EQAAsd /*数字1后的长字符串就是第一封邮件的唯一标志符 */

C:RETR 1 /*下载第一封邮件 */

S:+OK5184 octets /*第一封邮件的大小为5184字节 */

S:Receive…  /* 第一封邮件的具体内容 */

S:…

C:QUIT/*转入更新状态,接着再转入认证状态 */

S:+OK

C: QUIT /* 退出连接 */

S:+OKcore mail /*成功地退出了连接*/

对于上述的过程,补充如下几点内容。

  1. “C:”开头的行(不包括"C:")是客户端的输入,而以“S:”开头的行(不包括"S:")则是服务器的输出。

  2. 上述的命令并不一定会一次性成功,服务器会返回错误响应(以“-ERR”开头),客户端应该按照协议规定的时序,来输入后续的命令(或重复执行失败的命令,或重置会话,或退出会话等等)。

  3. 上述过程是示意性的,实际过程可能与其有较大不同。例如,实际过程中可能使用加密认证(MD5摘要认证)。

  4. RETR下载下来的邮件可能会难以看懂,这是因为其可能使用了quoted-printable编码或base64编码,我们可用Foxmail等用户代理软件来解码它。

注意:命令与参数之间是空格分隔的。包括服务器返回的邮件信息中,邮件正文内容与其它信息也是用空格分隔的。当编写邮件程序时,就是利用空格符来判断哪是邮件内容,哪是邮件发送信息(如接收日期、发送地址等等,这些信息又是通过“:”来分隔的)。

6、另一个例子:

使用 telnet 连接本地pop服务器收信
例如:安装邮件服务器 IP 是 127.0.0.1(蓝色字体内容由客户端输入,红色字体内容是服务返回的,黑色为说明内容)

telnet 127.0.0.1 110(使用 telnet 命令连接服务器 110 端口 )
 Trying 127.0.0.1… (正在连接服务器 110 端口)

Connected to 127.0.0.1( 连接服务器 110 端口成功)
 +OK Mail Server POP3 ready 
 
user username(输入用户名, username 为具体的用户名)
 +OK(执行命令成功 )
 
pass password (输入用户密码,password 为具体的密码)
 +OK 2 messages(密码认证通过)  (-ERR authorization failed --密码认证失败)

stat (邮箱状态 )
 +OK 2 6415 (2 为该信箱总邮件数,6415 为总字节数)

list (列出每封邮件的字节数 )
  +OK ( 执行命令成功,开始显示,左边为邮件的序号,右边为该邮件的大小 )
  1 537 (第 1 封邮件,大小为 537 字节)

  2 5878 ( 第 2 封邮件,大小为 5878 字节 )
  
top 1 (接收第 1 封邮件 )
      +OK (接收成功, 返回第 1 封邮件头 )

Return-Path: <[email protected]> 

Delivered-To: [email protected] 

Received: (server invoked for smtp delivery); Mon, 25 Oct 2004 14:24:27 +0800  

From: [email protected]

To: [email protected] 

Date: Mon, 25 Oct 2004 14:24:27 +0800

Subject: test mail  

. (这个点是邮件结束标志)

retr 1 (接收第 1 封邮件 )
+OK (接收成功, 返回第 1 封邮件全部内容)

Return-Path: <[email protected]>  (退信地址,回复地址)

Delivered-To: [email protected]   ([dɪ'lɪvəd]发送地址)

Received: (server invoked for smtp delivery); Mon, 25 Oct 2004 14:24:27 +0800  

From: [email protected]  

To: [email protected] 

Date: Mon, 25 Oct 2004 14:24:27 +0800  

Subject: test mail   

 Hi, test2 (邮件正文前有一空格与前述信息分隔!)

    This is a test mail, you don’t reply it.  

.(这个点是邮件结束标志)

dele 1(删除第 1 封邮件)
 +OK(删除成功 )
 
dele 2 (删除第 2 封邮件)
 +OK(删除成功)  

quit (结束会话 )
  +OK (执行命令成功)

邮件接收协议IMAP

1、IMAP概述
IMAP协议在RFC2060文档中定义,目前使用的是第4个版本,所以也称为IMAP4。IMAP协议相对于POP3协议而言,它定了更为强大的邮件接收功能,主要体现在以下一些方面:
IMAP具有摘要浏览功能,可以让用户在读完所有邮件的主题、发件人、大小等信息后,再由用户做出是否下载或直接在服务器上删除的决定。
IMAP可以让用户有选择性地下载邮件附件。例如一封邮件包含3个附件,如果用户确定其中只有2个附件对自已有用,就可只下载这2个附件,而不必下载整封邮件,从而节省了下载时间。
IMAP可以让用户在邮件服务器上创建自己的邮件夹,分类保存各个邮件。

2、IMAP与POP3的比较  
1、IMAP提供Webmail 与电子邮件客户端之间的双向通信,客户端收取的邮件仍然保留在服务器上,(而pop3协议的一个在特点就是用户只要从pop服务器读取了邮件,该邮件就会在服务器上删除)同时在客户端上的操作都会反馈到服务器上(如:删除邮件,标记已读等,服务器上的邮件也会做相应的动作(因此IMAP是一个联机协议)。所以无论从浏览器登录邮箱或者客户端软件登录邮箱,看到的邮件以及状态都是一致的。)。而POP3在客户端的操作不会反馈到服务器上。

2、IMAP更好地支持了从多个不同设备中随时访问新邮件。

3、IMAP提供的摘要浏览功能可以让你在阅读完所有的邮件到达时间、主题、发件人、大小等信息后才作出是否下载的决定。

4、POP3需要下载未阅读的邮件,IMAP可以不用把所有的邮件全部下载,而是通过客户端直接对服务器上的邮件进行操作。所有通过IMAP传输的数据都会被加密,从而保证通信的安全性。

5、IMAP 整体上为用户带来更为便捷和可靠的体验。POP3 更易丢失邮件或多次下载相同的邮件。

6、pop3协议的实现要比IMAP简单的多,因此成本要低很多,使用也更加广泛。

注:虽说 POP3在客户端的操作不会反馈到服务器上。但还是会有些设置能影响到服务器的,比如outlook上就会有设置在服务器收取下来的邮件在服务器上要不要保存14天后删除,诸如此类。


电子邮件的信息格式

电子邮件的格式
一个电子邮件分为信封和内容两大部分,在RFC-5332文档中只规定了邮件内容中的首部格式,邮件内容中的主体则由用户撰写。用户写好首部后邮件系统自动将信封所需的信息提取出来并写在信封上,不喜爱用户手动填写,一下是一些典型的邮件把内容首部。

首部 含义
To: 后面填入一个或多个收件人的电子邮件地址。
Subject: 邮件的主体,反映了邮件的主要内容,方便用户查找
From: 表示发件人的电子邮件地址
Date: 发信日期
Reply-To: 对方回信地址,不一定要与发信地址相同

电子邮件地址的格式
用户名@邮件服务器域名
这个用户名在这个邮件服务器中是唯一的(由邮件服务器通过校验保证),这样就保证了一个电子邮箱地址在全世界范围内的唯一


通用英特网邮件扩充MIME

MIME概述

SMTP有以下不足:

SMTP 不能传送可执行文件或其他的二进制对象。

SMTP 限于传送 7 位的 ASCII 码。许多其他非英语国家的文字(如中文、俄文,甚至带重音符号的法文或德文)就无法传送。

SMTP 服务器会拒绝超过一定长度的邮件。

于是在这种情况下就提出了MIME(Multipurpose InternetMail Extensions)。MIME 并没有改动 SMTP 或取代它。MIME 的意图是继续使用目前的格式,但增加了邮件主体的结构,并定义了传送非 ASCII 码的编码规则。

MIME 和 SMTP 的关系如下:
在这里插入图片描述

MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

MIME主要包括以下三个部分的内容:

1)五个新的邮件首部字段,他们可以包含在原来的邮件首部中,这些字段提供了有关邮件的主体的信息。
2)定义了许多邮件内容的格式,对多媒体电子邮件的表示方法进行了标准化,
3)定义了传送编码,可对任何格式内容进行转换,而不会被邮件系统改变。
下面是MIME新增的5个新的邮件首部的名称及意义(有的为可选项)

首部 含义
MIME-Version 标志MIME的版本,现在的版本号为1.0。若无此行则为英文文本
Content-Description 这是可读字符串,说明此邮件的主体是否是图像、音频或视频。
Content-id 邮件的唯一标识符
Content-Transfer-Encoding 在传送时邮件的主体是如何编码的
Content-Type 说明邮件的主体的数据类型和子类型

常见的MIME类型如下:

主类型 常见属性 参数含义
text charset 文本信息所使用的字符集
image name 图像的名称
application name 应用程序的名称
multipart boundary 邮件分段边界标识

下面重点说一下multipart类型

multipart类型有三种:multipart/mixed, multipart/related和multipart/alternative。从它们的名称,不难推知这些类型各自的含义和用处。它们之间的层次关系可归纳为下图所示:

±------------------------ multipart/mixed ----------------------------+
| |
| ±---------------- multipart/related ------------------+ |
| | | |
| | ±---- multipart/alternative ------+ ±---------+ | ±-----+ |
| | | | | 内嵌资源 | | | 附件 | |
| | | ±-----------+ ±-----------+ | ±---------+ | ±-----+ |
| | | | 纯文本正文 | | 超文本正文 | | | |
| | | ±-----------+ ±-----------+ | ±---------+ | ±-----+ |
| | | | | 内嵌资源 | | | 附件 | |
| | ±---------------------------------+ ±---------+ | ±-----+ |
| | | |
| ±-----------------------------------------------------+ |
| |
±---------------------------------------------------------------------+

可以看出,如果在邮件中要添加附件,必须定义multipart/mixed段;如果存在内嵌资源,至少要定义multipart/related段;如果纯文本与超文本共存,至少要定义multipart/alternative段。什么是“至少”?举个例子说,如果只有纯文本与超文本正文,那么在邮件头中将类型扩大化,定义为multipart/related,甚至multipart/mixed,都是允许的。

multipart诸类型的共同特征是,在段头指定“boundary”参数字符串,段体内的每个子段以此串定界。所有的子段都以“–”+boundary行开始,父段则以“–”+boundary+“–”行结束。段与段之间也以空行分隔。在邮件体是multipart类型的情况下,邮件体的开始部分(第一个“–”+boundary行之前)可以有一些附加的文本行,相当于注释,解码时应忽略。段间也可以有一些附加的文本行,不会显示出来,如果有兴趣,不妨验证一下。

实例

下面通过各种类型的邮件原文来说明上面的内容。以163邮箱发送的邮件为例。

1.最简单的纯文本邮件

 1 Received: from 15616xxxxx$163.com ( [122.207.54.20] ) by
 2  ajax-webmail-wmsvr14 (Coremail) ; Fri, 19 May 2017 19:40:51 +0800 (CST)
 3 X-Originating-IP: [122.207.54.20]
 4 Date: Fri, 19 May 2017 19:40:51 +0800 (CST)
 5 From: 15572483149 <[email protected]>
 6 To: [email protected]
 7 Subject: ss
 8 X-Priority: 3
 9 X-Mailer: Coremail Webmail Server Version SP_ntes V3.5 build
10  20160729(86883.8884) Copyright (c) 2002-2017 www.mailtech.cn 163com
11 Content-Transfer-Encoding: 7bit
12 Content-Type: text/plain; charset=GBK
13 MIME-Version: 1.0
14 Message-ID: <[email protected]>
15 X-Coremail-Locale: zh_CN
16 
17 ss

上面的邮件只包含一个文本(ss),所以第11,12行说明了正文格式和编码,下面的就是数据内容(段头和段体隔一行如16行)

2.包含一个文本和一个超文本(正常发送的邮件一般至少有一个正文一个超文本,除非特别指定为纯文本)

Received: from 15616104472$163.com ( [122.207.54.20] ) by
 ajax-webmail-wmsvr14 (Coremail) ; Fri, 19 May 2017 19:51:31 +0800 (CST)
X-Originating-IP: [122.207.54.20]
Date: Fri, 19 May 2017 19:51:31 +0800 (CST)
From: 15572483149 <[email protected]>
To: [email protected]
Subject:   ss
X-Priority: 3
X-Mailer: Coremail Webmail Server Version SP_ntes V3.5 build
 20160729(86883.8884) Copyright (c) 2002-2017 www.mailtech.cn 163com
X-CM-CTRLDATA: hN4rXGZvb3Rlcl9odG09ODU6NDI1
Content-Type: multipart/alternative; 
    boundary="----=_Part_214835_1240140699.1495194691872"
MIME-Version: 1.0
Message-ID: <[email protected]>
X-Coremail-Locale: zh_CN

------=_Part_214835_1240140699.1495194691872
Content-Type: text/plain; charset=GBK
Content-Transfer-Encoding: base64

c3Nz
------=_Part_214835_1240140699.1495194691872
Content-Type: text/html; charset=GBK
Content-Transfer-Encoding: base64

PGRpdiBzdHlsZT0ibGluZS1oZWlnaHQ6MS43O2NvbG9yOiMwMDAwMDA7Zm9udC1zaXplOjE0cHg7
Zm9udC1mYW1pbHk6QXJpYWwiPnNzczwvZGl2Pjxicj48YnI+PHNwYW4gdGl0bGU9Im5ldGVhc2Vm
b290ZXIiPjxkaXYgaWQ9Im5ldGVhc2VfbWFpbF9mb290ZXIiPjxkaXYgc3R5bGU9ImJvcmRlci10
b3A6I0NDQyAxcHggc29saWQ7cGFkZGluZzoxMHB4IDVweDtmb250LXNpemU6MTVweDtjb2xvcjoj
Nzc3O2xpbmUtaGVpZ2h0OjIycHgiPjxhIGhyZWY9Imh0dHA6Ly95b3UuMTYzLmNvbS9pdGVtL2xp
c3Q/Y2F0ZWdvcnlJZD0xMDEwMDAwJnN1YkNhdGVnb3J5SWQ9MTAxNTAwMSZmcm9tPXdlYl9nZ19t
YWlsX2ppYW9iaWFvXzgiIHRhcmdldD0iX2JsYW5rIiBzdHlsZT0iY29sb3I6IzMzNjZGRjt0ZXh0
LWRlY29yYXRpb246bm9uZSI+ob7P3sqxob9NVUpJoaLArbfywM3C17XI1sbU7MnM1rG5qdDCv+60
us/EVND0vfYz1du826Ohz97KsTQ51KrG8KOswu3Jz8fAJmd0OyZndDsgJm5ic3A7PC9hPgogJm5i
c3A7ICZuYnNwOzwvZGl2PjwvZGl2Pjwvc3Bhbj4=
------=_Part_214835_1240140699.1495194691872--

上面的包含一个文本和一个超文本,故12行Content-Type: multipart/alternative;接着为boundary参数。下面为两个元素,每个元素以“–”+boundary开头,然后是content-type,如18,19,20行。注意:上一个元素的数据和下一个元素的头之间无需空行。段以“–”+boundary+“–”结束,如37行。

4.文本,超文本,附件

 1 Received: from 15616104472$163.com ( [122.207.54.20] ) by
 2  ajax-webmail-wmsvr14 (Coremail) ; Fri, 19 May 2017 20:24:26 +0800 (CST)
 3 X-Originating-IP: [122.207.54.20]
 4 Date: Fri, 19 May 2017 20:24:26 +0800 (CST)
 5 From: 15572483149 <[email protected]>
 6 To: [email protected]
 7 Subject: ss
 8 X-Priority: 3
 9 X-Mailer: Coremail Webmail Server Version SP_ntes V3.5 build
10  20160729(86883.8884) Copyright (c) 2002-2017 www.mailtech.cn 163com
11 X-CM-CTRLDATA: pQoIAGZvb3Rlcl9odG09ODY6NDI1
12 Content-Type: multipart/mixed; 
13     boundary="----=_Part_217443_152692695.1495196666093"
14 MIME-Version: 1.0
15 Message-ID: <[email protected]>
16 X-Coremail-Locale: zh_CN
17 
18 ------=_Part_217443_152692695.1495196666093
19 Content-Type: multipart/alternative; 
20     boundary="----=_Part_217445_839318381.1495196666093"
21 
22 ------=_Part_217445_839318381.1495196666093
23 Content-Type: text/plain; charset=GBK
24 Content-Transfer-Encoding: base64
25 
26 c2RmYQ==
27 ------=_Part_217445_839318381.1495196666093
28 Content-Type: text/html; charset=GBK
29 Content-Transfer-Encoding: base64
30 
31 PGRpdiBzdHlsZT0ibGluZS1oZWlnaHQ6MS43O2NvbG9yOiMwMDAwMDA7Zm9udC1zaXplOjE0cHg7
32 Zm9udC1mYW1pbHk6QXJpYWwiPnNkZmE8L2Rpdj48YnI+PGJyPjxzcGFuIHRpdGxlPSJuZXRlYXNl
33 Zm9vdGVyIj48ZGl2IGlkPSJuZXRlYXNlX21haWxfZm9vdGVyIj48ZGl2IHN0eWxlPSJib3JkZXIt
34 dG9wOiNDQ0MgMXB4IHNvbGlkO3BhZGRpbmc6MTBweCA1cHg7Zm9udC1zaXplOjE1cHg7Y29sb3I6
35 Izc3NztsaW5lLWhlaWdodDoyMnB4Ij48YSBocmVmPSJodHRwOi8veW91LjE2My5jb20vaXRlbS9s
36 aXN0P2NhdGVnb3J5SWQ9MTAxMDAwMCZzdWJDYXRlZ29yeUlkPTEwMTUwMDEmZnJvbT13ZWJfZ2df
37 bWFpbF9qaWFvYmlhb184IiB0YXJnZXQ9Il9ibGFuayIgc3R5bGU9ImNvbG9yOiMzMzY2RkY7dGV4
38 dC1kZWNvcmF0aW9uOm5vbmUiPqG+z97KsaG/TVVKSaGiwK238sDNwte1yNbG1OzJzNaxuanQwr/u
39 tLrPxFTQ9L32M9XbvNujoc/eyrE0OdSqxvCjrMLtyc/HwCZndDsmZ3Q7ICZuYnNwOzwvYT4KICZu
40 YnNwOyAmbmJzcDs8L2Rpdj48L2Rpdj48L3NwYW4+
41 ------=_Part_217445_839318381.1495196666093--
42 
43 ------=_Part_217443_152692695.1495196666093
44 Content-Type: text/plain; name="first.txt"
45 Content-Transfer-Encoding: base64
46 Content-Disposition: attachment; filename="first.txt"
47 
48 MTIzNA==
49 ------=_Part_217443_152692695.1495196666093
50 Content-Type: text/plain; name="first.txt"
51 Content-Transfer-Encoding: base64
52 Content-Disposition: attachment; filename="first.txt"
53 
54 MTIzNA==
55 ------=_Part_217443_152692695.1495196666093--

上面的邮件体包含了一个文本,一个超文本和两个文本附件。注意看12行的content-type和boundary参数和19行,19行是12行的子元素的同时也是一个嵌套的段所以也有一个独有的boundary参数,和上面的multipart参数的关系一样,可是是一层层的嵌套关系。

5.包含所有的东西

Received: from 15616104472$163.com ( [122.207.54.20] ) by
 ajax-webmail-wmsvr14 (Coremail) ; Fri, 19 May 2017 20:37:12 +0800 (CST)
X-Originating-IP: [122.207.54.20]
Date: Fri, 19 May 2017 20:37:12 +0800 (CST)
From: 15572483149 <[email protected]>
To: [email protected]
Subject: ss
X-Priority: 3
X-Mailer: Coremail Webmail Server Version SP_ntes V3.5 build
 20160729(86883.8884) Copyright (c) 2002-2017 www.mailtech.cn 163com
X-CM-CTRLDATA: WqpW62Zvb3Rlcl9odG09MjUzOjM5Mg==
Content-Type: multipart/mixed; 
    boundary="----=_Part_218429_202270086.1495197432753"
MIME-Version: 1.0
Message-ID: <[email protected]>
X-Coremail-Locale: zh_CN

------=_Part_218429_202270086.1495197432753
Content-Type: multipart/related; 
    boundary="----=_Part_218430_777936326.1495197432753"

------=_Part_218430_777936326.1495197432753
Content-Type: multipart/alternative; 
    boundary="----=_Part_218431_95247708.1495197432753"

------=_Part_218431_95247708.1495197432753
Content-Type: text/plain; charset=GBK
Content-Transfer-Encoding: base64

c2Rm
------=_Part_218431_95247708.1495197432753
Content-Type: text/html; charset=GBK
Content-Transfer-Encoding: base64

PGRpdiBzdHlsZT0ibGluZS1oZWlnaHQ6MS43O2NvbG9yOiMwMDAwMDA7Zm9udC1zaXplOjE0cHg7
Zm9udC1mYW1pbHk6QXJpYWwiPjxkaXY+c2RmPC9kaXY+PGRpdj48aW1nIHNyYz0iY2lkOjQyZWE3
NDczJDIkMTVjMjBiNjNiYjEkQ29yZW1haWwkMTU2MTYxMDQ0NzIkMTYzLmNvbSIgb3Jnd2lkdGg9
IjQ4IiBvcmdoZWlnaHQ9IjQ4IiBkYXRhLWltYWdlPSIxIiBzdHlsZT0id2lkdGg6IDQ4cHg7IGhl
aWdodDogNDhweDsiPjwvZGl2PjwvZGl2Pjxicj48YnI+PHNwYW4gdGl0bGU9Im5ldGVhc2Vmb290
ZXIiPjxkaXYgaWQ9Im5ldGVhc2VfbWFpbF9mb290ZXIiPjxkaXYgc3R5bGU9ImJvcmRlci10b3A6
I0NDQyAxcHggc29saWQ7cGFkZGluZzoxMHB4IDVweDtmb250LXNpemU6MTZweDtjb2xvcjojNzc3
O2xpbmUtaGVpZ2h0OjIycHgiPjxhIGhyZWY9Imh0dHA6Ly95b3UuMTYzLmNvbS9pdGVtL21hbnVm
YWN0dXJlcj90YWdJZD0xMDAxMDAwJmZyb209d2ViX2FkX2ppYW9iaWFvMSIgdGFyZ2V0PSJfYmxh
bmsiIHN0eWxlPSJjb2xvcjojMzM2NkZGO3RleHQtZGVjb3JhdGlvbjpub25lIj6hvs340tfX1NOq
fDMwzOzO3tPHzcu79aG/zt7TocG8xrfWxtTsyczWsbmpu/m0obTytddU0PS1yLrDzu+jrM/eyrEy
OdSqxvAmZ3Q7Jmd0OzwvYT4KICZuYnNwOyAmbmJzcDs8L2Rpdj48L2Rpdj48L3NwYW4+
------=_Part_218431_95247708.1495197432753--

------=_Part_218430_777936326.1495197432753
Content-Type: image/png; name="circle.png"
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename="circle.png"
Content-ID: <42ea7473$2$15c20b63bb1$Coremail$15616104472$163.com>

iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAQAAAD9CzEMAAAABGdBTUEAALGPC/xhBQAAACBjSFJN
AAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QA/4ePzL8AAAAHdElN
RQfaBBoAAAC1VYTSAAAEGElEQVRYw63Ye4hUZRjH8c/Mjpu6XtbcSjTZki1dK2VBCtPRIJSU2oyi
gsrAzL/CEC9kaPiHVBJBBaYUSYgRlRGZFV2MaPKKmhfU1Kxlt7y73lZXXXe2P86c2XGd3XXd8/wz
c2be5/d9n987c97nPTFtRvLKyy7iYtIuS+d+nGpDIXYN4l0MMNhQtytRqFC9Ov/aZ5cDzrYHibUj
fptxJiiXcNxBh51DQol++uuuxhrf2qGhdUSsDfE7PW+SAmutsdURZ13ODuruRkOM8aB+1lpqQ2Ba
qn1ARr7YFNPUWWGVqlzHU1euS7EHvKjcSu84mA8Ryys/zELDfGiZQ615nIMp8ohZzptr7dUjY3mS
JnjLIfNtaHv5WqzVa0ZZ4DPpKzMKrhr8hPf86iV7A/FqbUW1aqVwyk96mOOsPyjNySpoIf+Qd31h
rlPtzT0XUgoN1rnsFcfsyEUUtPB+qV+86vy1y+fUkbZFkRl2qmpGxHIAfSxXYLLjHRFvYXF37xvs
STWhRjxnxFSDzXP8OrRlKz5vgS5mSoSuxLPsoaZabGvHzMkTVRZ5zNjwMqwgZoojVnROPpO52ibT
dc8CkjBEpWVOdGbqWUS9JSqMDpTDCiqd8V2n7Qljve2eDn6hAaC3ib53NAr5TA1fut9tJMWTUG6g
H6KYejZ+w8jmCu5V68+I7AlUauw2KgTEVNijNtIKGmx0lx4BoEiZXVfushHEHiVuDgDFequKWJ5q
hUoCQE9dr/f+kz9SUKshBHSVaO4OIosLzukdLnKji5EDaBILAGkJPSKXT7hBfQCo16DXVV1cZ6On
bk4EgDPq9YtSOwn9pR0LALUOuyNyi8qcCQEX7TZMYcSAEf5xMrwXbTDIrVGtQhL6qrBRYwjYJO2+
SOdf4abg/xZPQbVNHtUlMvmYSf6ym7CCRp8bYXgUJiWhzDgr1ZESz9w5UvaboqCziEz2c85bHbwN
9+Q6i403JhKDKjxruf+CqTc3Xj9KmatvZ2rI9HZzHPRJ+Fk88AeXLHKLGddvUyZrqrHeaG4gMs1v
KRx3zGxnWjbgHZJ/2Js+8JEmGYUMINOC75Uw21E7O4pIhi+L/W6+C83bV/Z8UK2UJlsUm+m0HZpK
rxmSkR9viX1ediJ3d8w54VQrpdE63czWyzYXrqWOZFB7oSnettn04CjYnJXvjJYw2Tz7LbQ27DVS
eaWzUWaWSsstcrLl6NaOsSMtcLeVltmZD5IjPsBTXlDvdatcbvcYm5PcxzOm6e1nX9nsaJ6+qady
E1Xq6lMfq8lfa95HCdn5DVTpcWVO2mmb/Y6pk9ZVsYGGu8cAB33ja3+3bmSrD0OykB6GGq3CIMXS
LkmLizvrgO3W2x02PB18GHKV0wlFSvRSqMklp9Wq0xh+2VbL9j9IHjTiA2DrdAAAACV0RVh0ZGF0
ZTpjcmVhdGUAMjAxNi0wOS0xN1QxNToyMjo1NiswODowMJ6pg4wAAAAldEVYdGRhdGU6bW9kaWZ5
ADIwMTAtMDQtMjZUMDA6MDA6MDArMDg6MDCgVTtdAAAATXRFWHRzb2Z0d2FyZQBJbWFnZU1hZ2lj
ayA3LjAuMS02IFExNiB4ODZfNjQgMjAxNi0wOS0xNyBodHRwOi8vd3d3LmltYWdlbWFnaWNrLm9y
Z93ZpU4AAAAYdEVYdFRodW1iOjpEb2N1bWVudDo6UGFnZXMAMaf/uy8AAAAYdEVYdFRodW1iOjpJ
bWFnZTo6SGVpZ2h0ADEyOEN8QYAAAAAXdEVYdFRodW1iOjpJbWFnZTo6V2lkdGgAMTI40I0R3QAA
ABl0RVh0VGh1bWI6Ok1pbWV0eXBlAGltYWdlL3BuZz+yVk4AAAAXdEVYdFRodW1iOjpNVGltZQAx
MjcyMjExMjAwCSkN7wAAABJ0RVh0VGh1bWI6OlNpemUAMi4zMktCSJ1SyQAAAFt0RVh0VGh1bWI6
OlVSSQBmaWxlOi8vL2hvbWUvd3d3cm9vdC9zaXRlL3d3dy5lYXN5aWNvbi5uZXQvY2RuLWltZy5l
YXN5aWNvbi5jbi9zcmMvMjk3LzI5NzEyLnBuZ5u0pR4AAAAASUVORK5CYII=
------=_Part_218430_777936326.1495197432753--

------=_Part_218429_202270086.1495197432753
Content-Type: text/plain; name="first.txt"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="first.txt"

MTIzNA==
------=_Part_218429_202270086.1495197432753--

猜你喜欢

转载自blog.csdn.net/m0_37556444/article/details/83097500
今日推荐