SMTP協議分析html
SMTP,即簡單郵件傳送協議,所相應RFC文檔爲RFC821。同http等多數應用層協議同樣,它工做在C/S模式下,用來實現因特網上的郵件傳送。SMTP在整個電子郵件通訊中所處的位置如圖 1所看到的。編程
圖 1電子郵件的通訊過程瀏覽器
可以看出,SMTP是用來將客戶機上的郵件傳送到server上。這裏的客戶機是指某次鏈接中的發送方,server是指對應的接收方。在解說發送郵件的整個通訊過程前,先解釋一如下幾個術語。安全
郵件是一種消息的格式,由信封、首部和正文組成。dom
信封上最重要的是收信人的地址。郵件server用這個地址將郵件發送到收信人所在的郵件server上。socket
首部是由用戶代理或郵件server加入的一些信息。包含Received、Message-ID、From、Data、Reply-To、X-Phone、X-Mailer、To和Subject等字段。
正文是是發送用戶發給接收用戶報文的內容。RFC 822 規定正文爲NVT ASCII文字行。編碼
更爲具體的說明,請參考RFC821和RFC822等協議。加密
用戶代理UA(User Agent)是用戶與電子郵件系統的交互接口,通常來講它就是咱們PC機上的一個程序。Windows上常見的用戶代理是Foxmail和Outlook Express。spa
用戶代理提供一個好的用戶界面,它提取用戶在其界面填寫的各項信息,生成一封符合SMTP等郵件標準的郵件,而後採用SMTP協議將郵件發送到發送端郵件server。
郵件server是電子郵件系統的核心,它用來發送和接收郵件。郵件server不一樣於普通PC的是它差點兒是全天工做的,因此它可以在不論何時爲用戶提供服務,後面將提到這正是爲何需要郵件server的一個重要緣由。很是多ISP都提供免費的郵件server,如126提供smtp.126.com郵件server。
郵件server向其餘郵件server轉發郵件也是採用SMTP協議。
普通狀況下,一封郵件的發送和接收步驟例如如下。
1) 發信人在用戶代理裏編輯郵件,包含填寫發信人郵箱、收信人郵箱和郵件標題等等。
2) 用戶代理提取發信人編輯的信息,生成一封符合郵件格式標準(RFC822)的郵件。
3) 用戶代理用SMTP將郵件發送到發送端郵件server(即發信人郵箱所相應的郵件server)。
4) 發送端郵件server用SMTP將郵件發送到接收端郵件server(即收信人郵箱所相應的郵件server)。
5) 收信人調用用戶代理。用戶代理用POP3協議從接收端郵件server取回郵件。
6) 用戶代理解析收到的郵件,以適當的形式呈現在收信人面前。
一個詳細的SMTP通訊(如發送端郵件server與接收端server的通訊)的步驟例如如下。
1) 發送端郵件server(下面簡稱client)與接收端郵件server(下面簡稱server)的25號port創建TCP鏈接。
2) client向server發送各類命令,來請求各類服務(如認證、指定發送人和接收人)。
3) server解析用戶的命令,作出對應動做並返回給client一個響應。
4) 2)和3)交替進行,直到所有郵件都發送完或二者的鏈接被意外中斷。
從這個過程看出,命令和響應是SMTP協議的重點,如下將予以重點講述。
SMTP的命令很少(14個),它的通常形式是:COMMAND [Parameter] <CRLF>。當中COMMAND是ASCII形式的命令名,Parameter是對應的命令參數,<CRLF>是回車換行符(0DH, 0AH)。
SMTP的響應也不復雜,它的通常形式是:XXX Readable Illustration。XXX是三位十進制數;Readable Illustration是可讀的解釋說明,用來代表命令是否成功等。XXX具備例如如下的規律:以2開頭的表示成功,以4和5開頭的表示失敗,以3開頭的表示未完畢(進行中)。
命令和響應的格式是語法,各命令和響應的意思則是語義,各命令和各響應在時間上的關係則是同步。如下將經過一個簡單的SMTP通訊過程來講明協議的這三個要素。
C:telnet smtp.126.com 25 /* 以telnet方式鏈接126郵件server */
S:220 126.com Anti-spam GT for Coremail System (126com[071018]) /* 220爲響應數字,其後的爲歡迎信息,會應server不一樣而不一樣*/
C:HELO smtp.126.com /* HELO 後用來填寫返回域名(詳細含義請參閱RFC821),但該命令並不檢查後面的參數 */
S:250 OK
C: MAIL FROM: bripengandre@126.com /* 發送者郵箱 */
S:250 … ./* 「…」表明省略了一些可讀信息 */
C:RCPT TO: bripengandre@smail.hust.edu.cn /* 接收者郵箱 */
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
分析上面的過程可參考凝視進行,這裏要補充例如如下幾點。
1) 「C:」開頭的行(不包含"C:")是client的輸入,而以「S:」開頭的行(不包含"S:")則是server的輸出。
2) 上述的命令並不必定會一次性成功,server會返回錯誤響應,client應該依照協議規定的時序,來輸入興許的命令(或反覆運行失敗的命令,或重置會話,或退出會話等等)。
SMTP命令不區分大寫和小寫,但參數區分大寫和小寫,有關這方面的具體說明請參考RFC821。常用的命令例如如下。
HELO <domain> <CRLF>。向server標識用戶身份發送者能欺騙,說謊,但普通狀況下server都能檢測到。
MAIL FROM: <reverse-path> <CRLF>。<reverse-path>爲發送者地址,此命令用來初始化郵件傳輸,即用來對所有的狀態和緩衝區進行初始化。
RCPT TO:<forward-path> <CRLF>。 <forward-path>用來標誌郵件接收者的地址,常用在MAIL FROM後,可以有多個RCPT TO。
DATA <CRLF>。將以後的數據做爲數據發送,以<CRLF>.<CRLF>標誌數據的結尾。
REST <CRLF>。重置會話,當前傳輸被取消。
NOOP <CRLF>。要求server返回OK應答,通常用做測試。
QUIT <CRLF>。結束會話。
VRFY <string> <CRLF>。驗證指定的郵箱是否存在,由於安全方面的緣由,server大多禁止此命令。
EXPN <string> <CRLF>。驗證給定的郵箱列表是否存在,由於安全方面的緣由,server大多禁止此命令。
HELP <CRLF>。查詢server支持什麼命令。
常用的響應例如如下所看到的,數字後的說明是從英文譯過來的。更具體的說明請參考RFC821。
501參數格式錯誤
502命令不可實現
503錯誤的命令序列
504命令參數不可實現
211系統狀態或系統幫助響應
214幫助信息
220<domain>服務就緒
221<domain>服務關閉
421<domain>服務未就緒,關閉傳輸信道
250要求的郵件操做完畢
251用戶非本地,將轉發向<forward-path>
450要求的郵件操做未完畢,郵箱不可用
550要求的郵件操做未完畢,郵箱不可用
451放棄要求的操做;處理過程當中出錯
551用戶非本地,請嘗試<forward-path>
452系統存儲不足,要求的操做未運行
552過量的存儲分配,要求的操做未運行
553郵箱名不可用,要求的操做未運行
354開始郵件輸入,以"."結束
554操做失敗
從
1) 命令過於簡單,沒提供認證等功能。
2) 僅僅傳送7位的ASCII碼,不能傳送二進制文件。
針對缺點1),標準化組織制定了擴充的SMTP(即ESMTP),相應的RFC文檔爲RFC1425。針對缺點2),標準化組織在兼容SMTP的前提下,提出了傳送非7位ASCII碼的方法,相應的RFC文檔有兩個:郵件首部的擴充相應於RFC1522,郵件正文的擴充相應與RFC1521(即MIME)。
ESMTP最顯著的地方是加入了用戶認證功能。假設用戶想使用ESMTP提供的新命令,則在初次與server交互時,發送的命令應該是EHLO而不是HELO。先來看一個樣例。
C:telnet smtp.126.com 25 /* 以telnet方式鏈接126郵件server */
S:220 126.com Anti-spam GT for Coremail System (126com[071018]) /* 220爲響應數字,其後的爲歡迎信息,會應server不一樣而不一樣*/
C:EHLO smtp.126.com /* 除了HELO所具備的功能外,EHLO主要用來查詢server支持的擴充功能 */
S:250-mail
S:250-AUTH LOGIN PLAIN
S:250-AUTH=LOGIN PLAIN
S:250 8BITMIME /* 最後一個響應數字應答碼以後跟的是一個空格,而不是'-' */
C:AUTH LOGIN /* 請求認證 */
S:334 dxNlcm5hbWU6 /* server的響應——通過base64編碼了的「Username」 */
C:Y29zdGFAYW1heGl0Lm5ldA== /* 發送通過BASE64編碼了的username */
S:334 UGFzc3dvcmQ6 /* 通過BASE64編碼了的"Password:" */
C:MTk4MjIxNA== /* client發送的通過BASE64編碼了的password */
S:235 auth successfully /* 認證成功 */
C: MAIL FROM: bripengandre@126.com /* 發送者郵箱 */
S:250 … ./* 「…」表明省略了一些可讀信息 */
C:RCPT TO: bripengandre@smail.hust.edu.cn /* 接收者郵箱 */
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
對於這個樣例有例如如下幾點說明。
1) 僅僅是一個示意性的過程,再輸入username、password時需採用base64編碼,這需要專門的計算,因此在telnet終端上模擬比較麻煩。
2) 認證過程有很是多種,有基於明文的認證,也有基於MD5加密的認證,這裏給出的僅僅是一個示意性的過程。
3) EHLO對於詳細server,響應會不一樣,keyword「8BITMIME」用來講明server是否支持正文中傳送8位ASCII碼,而以「X」開頭的keyword都是指server本身定義的擴充(還沒歸入RFC標準)
更具體的說明,請參看RFC1425。
首部經過兩種編碼方式來支持傳送非7位ASCII碼。它首先經過一個例如如下格式的編碼字來代表所用的編碼方式。
=?charset?encoding?encoded-text?text
charset是字符集規範。有效值是兩個字符串us-ascii和iso-8859-x,當中x 是一個單個數字,好比iso-8859-1中的數字爲「
encoding是一個單個字符用來指定編碼方法,支持兩個值。
Q表明quoted-printable(可打印)編碼。不論什麼要發送的字符若其第8比特置1則被做爲3個字符發送:第1個是字符是「=」,後面的兩個字符相應於字符的十六進制表示。好比對於二進制碼11111111,其相應的十六進制表示爲「FF」,因此相應的編碼位「=FF」。爲了能夠傳輸「=」,「=」的編碼方式與第8比特置1的字符一樣,因爲其二進制代碼爲00111101,因此相應的編碼爲「=3D」。能夠看出這樣的編碼方式的開銷達200%,因此僅僅適合傳送僅僅含有少許非7位ASCII碼的文本。
B表明base64編碼。它的編碼方法是先將二進制代碼劃分爲一個24bit長的單元,而後將這24 bit單元劃分爲4個6 bit組。每個組按圖 2所看到的的方法轉換成ASCII碼。
圖 2 base64映射表
可以看出這種映射方法是這種:0-25依次映射成A-Z,26-51依次映射成a-z,52-61依次映射成數字0-9,而後62映射成+,63映射成/。
對於二進制代碼01001001 00110001 01111001,先將其劃分紅4個6 bit組,即010010 0100011 000101 111001。接着按圖 2所看到的的映射表,可獲得base64編碼爲:STF5。可以看出,這樣的編碼方式的開銷是25%,相對quoted-printable編碼來講,它更適合用來傳送含大量非7位ASCII碼的二進制文件。
正文的擴充主要是使正文不只可以傳輸NVT ASCII字符,而且可以傳輸隨意字符,相應的文檔爲RFC1511(即MIME)。
MIME全稱爲「Multiple Internet Mail Extensions」, 比較確切的中文名稱爲「多用途互聯網郵件擴展」。它經過新增一些郵件首部字段、郵件內容格式和傳送編碼,使得其成爲一種應用很是普遍的可以傳輸多媒體的電子郵件規範。
更具體的說明請參看還有一篇文章《MIME協議分析》和RFC1511。
通常的PC資源不夠,處理能力不夠,不可能全天候地鏈接在因特網上來收發郵件。因此使用SMTPserver,可以讓多個用戶共用server,有效地減小了成本。
如前所述,SMTP是客戶機向server發送郵件時所使用的協議,其核心是2.2中所述的命令和響應,至於它命令和響應中所帶的參數採用什麼格式,則是依賴於其它標準的。好比DATA後所帶的參數,則應遵循郵件格式標準RFC822.
SMTP和郵件格式的關係可用這麼一個樣例來講明。甲與乙書信往來,甲經過郵局向乙發信,郵局間轉交郵件可當作使用了SMTP協議,至於書信的格式則會因爲地區習慣等的不一樣而不一樣(中國人的書信格式和美國人的書信格式不一樣),這個書信格式則可當作是郵件格式標準。
應當認識到不能孤立地看待協議,各個協議之間每每存在着耦合關係,但爲了分析方便,咱們在詳細敘述某個協議時,僅僅能抓住主要矛盾——主要闡述單個協議。
瀏覽器如IE、Maxthon可經過登錄用戶郵箱,來收發郵件,這是如何實現的?好比bripengandre@126.com可經過登錄www.126.com來收發郵件。
這個過程是這種:bripengandre@126.com在www.126.com提供的郵件頁面上填寫的對應信息(如發信人郵箱、收信人郵箱等),經過http協議被提交給126server;126server依據這些信息組裝一封符合郵件規範的郵件(就像用戶代理同樣);而後smtp.126.com經過SMTP協議將這封郵件發送到接收端郵件server。
可以看出,瀏覽器發送郵件僅僅是用戶代理的功能直接放到郵件server上去作了,至於郵件server間發送郵件仍是採用的SMTP協議。咱們看問題,假設有必要仍是要適當地透過現象看本質。
1) 可以經過ethereal等協議分析軟件來抓包分析協議。
2) 可以利用socket編程實現SMTP的通訊過程。
3) 可以利用用戶代理來查看一封郵件的原始編碼。好比在Foxmail中,可以選擇郵件列表右鍵菜單的「原始信息」進行查看。
ID |
Protocol |
Captured contents |
||||||
user name |
password |
sender |
receiver |
subject |
contents |
attachments |
||
4 |
smtp |
√ |
√ |
√ |
√ |
√ |
√ |
|
表 1 協議分析要求
表 1給出了協議分析要求。easy看出,獲取各個字段是比較easy的。咱們能夠抓取client與server端的交互信息,而後依據各命令字或響應字來提取出咱們想要的字段。好比,要獲取user name,咱們僅僅需檢測到server端要求client發送username這個時候,而後提取這以後client的發送信息就能夠。需要說明的是,儘管client與服務端交互的信息可能通過了編碼或加密,但咱們仍能夠經過解碼或解密來得到所需要的信息。
[1] RFC文檔:RFC821相應SMTP協議,RFC822相應郵件標準,RFC1425相應ESMTP,RFC1522相應郵件首部的擴充,RFC1521相應郵件正文的擴充,RFC1939相應POP3協議。
[2] http://www.faqs.org/rfcs/,上面有全面的英文RFC文檔
[3] http://www.cnpaf.net/,上面有很多實用的協議分析文檔,也有中文RFC文檔,但質量不是特別高
[4] Stevens, W.R., TCP/IP Illustrated, Vol1. Addision-Wesley, 機械工業出版社,2002