MIME協議及源郵件格式分析

轉載鏈接:http://wenku.baidu.com/view/7246de671ed9ad51f01df277.html


電子郵件也許是一個Internet上的流行最廣泛的應用。也是我們現在的大多數網絡辦公流程的基礎。各種郵件服務器很多,但都大都遵循以1982年出版的RFC822--《ARPA網絡文本信息格式標準(STANDARD?FOR?THE?FORMAT?OF?ARPA?INTERNET?TEXT?MESSAGES)》為基礎的一系列郵件格式的規定。?
?
RFC(The?Requests?for?Comments)是用來規定互聯網工作標準的文檔。我們使用的時候并沒有注意到這些協議在我們的郵件通信過程中默默的發揮著的作用,這絲毫也不能減低這些作用的重要性。郵件內部還有很多不為人知的秘密。
?
在RFC822中規定一封信包括一個必須的多個頭部域(header?fields)和一個可選的體部(body)組成。從一封信頭開始至第一個空行都是頭部。頭部定義了一個郵件的各項基本要素,路由信息等內容。
?
在Outlook?Express中選定一封信看它的屬性。在詳細資料選項卡中顯示的就是這封郵件的頭部內容。也可以選定一封信,另存為一個.eml文件。由于文件是一個純文本文件,用一般的編輯器打開就可以看到郵件的內容。?
頭部有各個頭部域組成,每一個頭部域都包括域名(field-name)和域體(field-body),它們之間以":"分隔。每一個頭部域都可以看作由ASCII碼字符組成的獨立的文本。常見的頭部域包括:"Return-Path",?"Received",?"Date",?"From",?"Subject",?"Sender","To",?"cc","MIME-Version"等。各頭部域之間沒有規定順序。??就像各個域的名字一樣。他們表示的具體意義也不同。?Return-Path域表示退信的地址。?Received域表示路由信息。
?
Internet上的信件可能是由多個服務器依靠協議傳遞到達最終的目的郵箱的。每一個服務器都會把自己的一段
Received域信息添加近信件。所以可能有多段Received域,依傳遞次序排列。這個域的內容很有意思,我們可以根據每一段的內容來跟蹤一封信在internet上的傳遞過程。網管人員也可以根據這些信息做出很有價值的判斷。
??例如一段代碼中???Received:?from?unknown?(unknown?[202.108.44.208])?by?mx7.163.com?(Postfix)?with?SMTP?id?74E0E8?for;?Fri,?28?Feb?2003?18:10:25?+0800?(CST)中,from?表示發送主機,by表示接受主機,via物理路徑(本例沒有),with表示使用的協議,id表示接受消息號,for表示目的郵件地址,分號后面表示時間。
??Date域表示建立信件的時間。???From域表示郵件作者。
??Subject域就是郵件的主題。
??Sender域表示郵件的實際發送者。???To,cc域都表示接受的郵件地址。
??MIME-Version域表示MIME的版本(以后擴充的域)
??還有一個域—Content-Type。標識了一個重要的概念:郵件內容的格式。這個域的內容根據互聯網的發展產生,使郵件可以用來傳輸非文本內容,在RFC822中并沒有定義,而是在后續的RFC2045,RFC2046等文檔中有定義。
??還有一些不太常見的頭部域,如"References","Message-ID"域。以及一些由不同廠家定義的自己的域(域名以"X-"開頭)。
??知道了這些知識,就可以看懂郵件頭部。了解到那些郵件的秘密。???比如這是一封郵件的頭部。
Return-Path:?"sea"?
Received:?from?unknown?(unknown?[202.108.44.208])?by?mx7.163.com?(Postfix)?with?SMTP?id?74E0E8?for??Fri,?28?Feb?2003?18:10:25?+0800?(CST)
Received:?from?smtp.netcs.com?(unknown?[211.150.100.6])
by?192.168.1.208?(Coremail:www.163.com)?with?SMTP?id?cAsAAJY1Xz7kAmQG.1?for??Fri,?28?Feb?2003?18:10:30?+0800?(CST)?Received:?from?sea?(unknown?[192.168.18.160])
by?smtp.netcs.com?(Postfix)?with?ESMTP?id?E55D02675F
for??Fri,?28?Feb?2003?18:09:58?+0800?(CST)
Message-ID:?<000901c2df11$2fcac090$a012a8c0@sea>?From:?"sea"?
To:?"=?gb2312?B?usK6vQ==?="?
Message-ID:?<000901c2df11$2fcac090$a012a8c0@sea>?References:?<000c01c2decb$9c7b7860$a012a8c0@sea>??<004601c2dee2$28a348c0$2400a8c0@haostation>??<001501c2deeb$352b34a0$a012a8c0@sea>?Subject:?Re:?hello
Date:?Fri,?28?Feb?2003?18:07:22?+0800?MIME-Version:?1.0
Content-Type:?multipart/alternative;
boundary="----=_NextPart_000_0006_01C2DF54.3DDEBE50"?X-Priority:?3
X-MSMail-Priority:?Normal
X-Mailer:?Microsoft?Outlook?Express?6.00.2600.0000
X-MimeOLE:?Produced?By?Microsoft?MimeOLE?V6.00.2600.0000??
??通過辨認就可以知道這是一封從(From域)"sea"?寫給(To域)"=?gb2312?B?usK6vQ==?="?的Id(Message-ID域)為<000901c2df11$2fcac090$a012a8c0@sea>的回信。退信的地址(Return-Path域)是haibo.yang@netcscom可以看出(References域)這封信已經經過了連續三次回復。主題(Subject域)是Re:?hello。時間(Date域)是2003年的3月28日。郵件優先級(X-Priority域)是普通。郵件的傳遞依次經過了三個服務器(Received域):smtp.netcs.com;unknown;和mx7.163.com。還可以看到各服務器的協議和到達各服務器的時間。其中Postfix和Coremail都是常見的郵件系統。其中郵件接收地址中的內容由于包含漢字進行了編碼。?
??一封郵件首先建立的是核心的幾個域:From,To,Message-Id,Subject,Date等,在傳輸過程中每通過一個服務器再由此服務器在郵件頭部添加一行Received信息,最后一個服務器添加退信地址(Return-Path)。
??郵件頭的格式制定的細節是根據信息交流和網絡傳輸的特點制定的。閱讀它們不僅可以知道郵件傳輸的秘密,還可以讓我們體會到協議制定與實現間的互相關聯的緊密關系。可以通過http://www.rfc.net/?查詢到RFC822,同時可以查詢到其它重要的RFC文檔。?
?
MX記錄的應用
在DNS服務器上除了可以建立主機名與IP地址的映射外,還可以建立其他多種映射,例如,建立某個主機名與其別名的映射;建立某個域名與其SMTP服務器的映射。在DNS服務器上創建的各項映射關系稱為記錄,一項映射關系就是一條記錄,在DNS服務器上創建的主機名與IP地址的映射關系稱為A記錄,主機名與別名的映射關系稱為CNAME記錄,域名與其SMTP服務器的映射關系稱為MX記錄。
在DNS服務器上為什么要建立MX記錄呢?即為什么要建立域名與其SMTP服務器的映射關系呢?這與電子郵件地址的表示形式和工作原理有關。郵件地址后綴部分表示的通常都是一個域名,而不是接收郵件的服務器的主機名,例如,郵件地址“zxx@it315.org”中的“it315.org”對應的就是一個域名。域只是一個邏輯組合概念,它并不代表真正的計算機,對于使用某個域名作為后綴的郵件地址,外界發送給它的電子郵件必須由一臺專門的SMTP服務器來進行接收和處理,接收和處理某個域的電子郵件的SMTP服務器即為該域的SMTP服務器,外界發送給某個域的電子郵件實際上都是發送給該域的SMTP服務器。外界如何知道一個域的SMTP服務器的地址呢?這就是通過管理該域的DNS服務器上的MX記錄來獲得的,這也就是在DNS服務器上為什么要建立域名與其SMTP服務器的映射關系的原因。
當某臺SMTP服務器要給“zxx@it315.org”發送一封電子郵件時,該SMTP服務器將根據郵件地址的后綴部分而去查詢“it315.org”這個域的MX記錄,得到這個域的SMTP服務器的主機名為“mail.it315.org”,然后將郵件發送給“mail.it315.org”這個SMTP服務器。
動手實踐??根據域名查詢SMTP服務器?

Windows操作系統自帶的nslookup命令可以查詢一個域的MX記錄。要想知道負責接收某個電子郵箱的郵件的SMTP服務器,可以先根據該郵件地址的后綴部分推斷出其域名,然后使用nslookup命令進行查詢即可。下面以查找負責接收“zxx@sina.com”這個郵件地址的SMTP服務器的信息為例進行講解。
?
啟動Windows下的DOS命令行窗口,執行nslookup命令,結果如圖1.16所示。
?
圖1.16中“ns2.bjgwbn.net.cn”表示執行nslookup命令的這臺計算機當前所使用的DNS查詢服務器的主機名,“211.161.46.84”則表示該DNS服務器的IP地址。
?
在圖1.16中的“>”提示符后面先輸入“set?type=mx”命令,設置所要查詢的記錄類型為MX,然后輸入域名
“sina.com”,結果如圖1.17所示。
?
圖1.16??????????????????????????????????圖1.17
圖1.17中顯示了“sina.com”這個域的SMTP服務器的主機名和IP地址,其中“sinamx.sina.com.cn”為SMTP服務器的主機名,并且該主機名對應了3個IP地址。這說明“sina.com”為了擴充其郵件處理能力,使用了3臺SMTP服務器來接收外界發送給該域的郵件,這3臺服務器的主機名都為“sinamx.sina.com.cn”,外界的SMTP服務器可以選擇其中任何一臺進行連接,然后將郵件發送給該服務器。
?
在圖1.17中的“>”提示符后面再次輸入“sina.com”,nslookup命令將再次查詢該域的MX記錄,結果如圖
1.18所示。
比較圖1.18中的用方框標識的部分,可以看到這兩次查詢出的“sinamx.sina.com.cn”所對應的3個IP地址的排列順序并不相同,第一次查詢時“202.108.3.187”排列在最前面,而第二次查詢時卻變成了“202.108.3.188”排列在最前面。如果繼續查詢“sina.com”域的MX記錄,可以看到“sinamx.sina.com.cn”所對應的3個IP地址的排列順序總是在改變。這是由于sina在管理“sina.com.cn”域的DNS服務器上進行了專門的設置,當外界每次查詢“sinamx.sina.com.cn”這個主機名的IP地址時,管理“sina.com.cn”域的DNS服務器都將對該主機名所對應的3個IP地址進行輪循排列后再返回。
?
圖1.18
對于查詢到一個主機名對應多個IP地址的情況,外界的計算機通常都是選擇其中的第一個IP地址來進行通信,只要管理“sina.com.cn”域的DNS服務器每次都將“sinamx.sina.com.cn”所對應的3個IP地址進行輪循排列后再返回給外界,外界的SMTP服務器將會分別選擇到不同的IP地址來進行通信,sina通過這種簡單的方式就在“sinamx.sina.com.cn”所對應的3臺SMTP服務器之間實現了負載均衡。
提示:使用nslookup查詢“sina.com”域的MX記錄時,讀者可能會遇到DNS服務器只返回SMTP服務器的主機名,而不返回該主機名所對應的IP地址的情況,這時候可以在原來的nslookup命令窗口中輸入“set?type=a”命令,即

將要查詢的記錄類型設置為A,然后輸入前面查詢到的SMTP服務器的主機名就可以得到其IP地址

電子郵件的工作原理
下面以sina和sohu這兩個電子郵局為例來講解電子郵件的傳輸過程和工作原理。假設sina郵箱的賬戶為lisi@sina.com,sohu郵箱的賬戶為wangwu@sohu.com,它們之間的郵件收發過程如圖1.20所示。
?
圖1.20
圖1.20中實線部分表示lisi@sina.com賬戶向wangwu@sohu.com賬戶發送郵件的過程,虛線部分表示wangwu@sohu.com賬戶向lisi@sina.com賬戶發送郵件的過程。下面通過分析lisi@sina.com賬戶向wangwu@sohu.com賬戶發送郵件的過程,來具體講解一封郵件從發送到接收所涉及的環節。
?
lisi@sina.com的郵件客戶端程序(這里假設為Outlook?Express)與sina的SMTP服務器建立網絡連接,并
以lisi的用戶名和密碼進行登錄后,使用SMTP協議把郵件發送給sina的SMTP服務器。
?
sina的SMTP服務器收到lisi@sina.com提交的電子郵件后,首先根據收件人的地址后綴判斷接收者的郵件地
址是否屬于該SMTP服務器的管轄范圍,如果是的話就直接把郵件存儲到收件人的郵箱中,否則,sina的SMTP服務器向DNS服務器查詢收件人的郵件地址后綴(sohu.com)所表示的域名的MX記錄,從而得到sohu的SMTP服務器信息,然后與sohu的SMTP服務器建立連接并采用SMTP協議把郵件發送給sohu的SMTP服務器。
?
sohu的SMTP服務器收到sina的SMTP服務器發來的電子郵件后,也將根據收件人的地址判斷該郵件是否屬于
該SMTP服務器的管轄范圍,如果是的話就直接把郵件存儲到收件人的郵箱中,否則(一般不會出現這種情況),sohu的SMTP服務器可能繼續轉發這封電子郵件,也可能丟棄這封電子郵件。
?
擁有wangwu@sohu.com賬戶的用戶通過郵件客戶端程序(這里假設也為Outlook?Express)與sohu的POP3/IMAP
服務器建立網絡連接,并以wangwu的用戶名和密碼進行登錄后,就可以通過POP3或IMAP協議查看wangwu@sohu.com郵箱中是否有新郵件,如果有的話,則使用POP3或IMAP協議讀取郵箱中的郵件。
圖1.20中的虛線部分表示wangwu@sohu.com賬戶向lisi@sina.?com賬戶發送郵件的過程,此過程與lisi@sina.com賬戶向wangwu@?sohu.com賬戶發送郵件的過程類似,這里不再復述。
多想一想??郵件客戶端程序和SMTP服務器
分別如何發送郵件
郵件客戶端軟件與SMTP服務器之間,以及兩臺SMTP服務器之間都采用SMTP協議進行通信。郵件客戶端軟件只采用SMTP協議發送郵件,即郵件客戶端軟件只作為SMTP協議的發送方。SMTP服務器既要采用SMTP協議向其他SMTP服務器發送郵件,又要采用SMTP協議接收其他SMTP服務器或郵件客戶端軟件發送來的郵件,即SMTP服務器既作為SMTP協議的發送方,又作為SMTP協議的接收方。郵件客戶端軟件與SMTP服務器都可以使用SMTP協議發送郵件,僅發送郵件這一功能而言,它們在技術實現上有何差異呢?它們的差異主要體現在以下兩個方面:
(1)SMTP服務器接收到郵件客戶端軟件發送來的郵件后,需要根據收件人地址的域名將郵件轉發給目標域的SMTP服務器,而大量的收件人地址中肯定會出現各種可能的域名,因此,SMTP服務器涉及到要與其他多臺不能事先確定的SMTP服務器進行通信,它需要具有根據收件人地址的域名查詢出該域的SMTP服務器的功能,即需要具有查詢域名的MX記錄的功能。郵件客戶端軟件被設置為與固定的SMTP服務器通信,它可以直接與指定的SMTP服務器建立網絡連接,因此它不需要具有根據收件人地址的域名來查詢該域的SMTP服務器的功能。??

(2)對于來自某個郵件客戶端軟件的郵件傳輸請求,SMTP服務器可能需要對發件人的用戶賬號信息進行驗證,因此,郵件客戶端軟件需要具有向SMTP服務器傳送用戶賬號信息的功能。SMTP服務器能夠直接接受來自其他SMTP服務器的郵件傳輸請求,因此,SMTP服務器在發送郵件時根本不需要傳送用戶賬號信息的功能。
?
RFC822郵件格式
郵件內容的格式在RFC822文檔中定義,它包括兩個主要的組成部分:郵件頭和郵件體。在第2章的SMTP協議的實驗中,it315_test?@sohu.com郵箱中接收到的it315_test@sina.com發送來的郵件的最終內容如例程3-1所示,其中的行號不屬于郵件內容,是作者為了便于講解而加上的。
例程3-1??test.eml
1.Return-Path:?<it315_test@sina.com>
2.Delivered-To:?it315_test@mx72.mail.sohu.com
3.Received:?from?smtp.sina.com.cn?(unknown?[202.108.3.177])?4.?by?sohumx139.sohu.com?(Postfix)?with?SMTP?id?E4F9802C1249
5.?for?<it315_test@sohu.com>;?Thu,?10?Nov?2005?16:39:50?+0800?(CST)
6.Received:?(qmail?49221?invoked?from?network);?10?Nov?2005?08:39:?33?-0000?7.Received:?from?unknown?(HELO?it315?test)?(218.246.5.151)?8.???by?smtp.sina.com.cn?with?SMTP;?10?Nov?2005?08:39:33?-0000?9.?From:?it315_test@sina.com?10.To:?it315_test@sohu.com?11.subject:test
12.Message-Id:?<20051110083950.E4F9802C1249@sohumx139.sohu.com>?13.Date:?Thu,?10?Nov?2005?16:39:50?+0800?(CST)?14.Status:?RO
15.X-UIDL:?1131611863.21509_77.mx72?16.
17.test!!!
例程3-1中的第1~15行是郵件的郵件頭,第17行是郵件的郵件體,郵件頭和郵件體之間以一個空行進行分隔。這封郵件的郵件體內容非常少,只有一行“test!!!”文本。郵件頭部分由多個頭字段和字段內容組成,各種頭字段分別用于表示郵件的發件人、收件人、發件時間和主題等信息。細心的讀者可能已經看到,例程3-1中的郵件頭部分比在第2章的SMTP協議的實驗中實際發送的郵件頭多出了一些頭字段,這些頭字段是各個SMTP服務器在傳遞郵件的過程加上的。SMTP服務器在傳遞郵件時,會把一些相關信息增加到郵件的郵件頭中,這種情況有點類似于現實生活中的郵局在處理郵件時,通常都會在信封上加蓋郵戳一樣,表示這封郵件在什么時候經過了哪個郵局和由哪個工作人員經手處理。SMTP服務器按從下往上的方式添加各個字段,即先添加的字段位于后添加的字段的下面,例如,例程3-1中的郵件是由sina發送給sohu的,它首先經過sina的SMTP服務器,然后經過sohu的SMTP服務器,所以,sohu的SMTP服務器添加的頭字段(1~5行)位于sina的SMTP服務器添加的頭字段(6~8行)的上面。另外,POP3服務器也會在郵件頭中增加一些頭字段,例如,例程3-1中的12~15行。
每一個郵件頭以“字段名:字段值”的格式出現,即每一行郵件頭的內容依次由字段名、冒號、空格、字段值、回車換行符組成。RFC822文檔中定義了多個標準的郵件頭字段,每一個郵件頭字段表示一種特定的信息。郵件頭中也可以包含自定義的頭字段,這種自定義的頭字段通常是某個組織或機構內部專用的。下面是對例程3-1中出現的一些主要的郵件頭字段的解釋:
—??Return-Path??該字段代表郵件的回復地址,該字段內容由接收郵件的SMTP服務器填寫,接收郵件的SMTP服務器從郵件發送程序發出的mail?form命令中獲得該字段內容。
—??Received??該字段的基本格式為Received?from?A?by?B?for?C,其中A為發送方,B為接收方,C為收件人的郵箱地址。該字段的內容由接收郵件的SMTP服務器填寫,常常被用來追蹤郵件傳輸的路線和分析郵件的來源,例如,從例程3-1中的各個Received字段中,可以知道這封郵件的傳輸路徑:從IP地址為【218.246.5.151】的機器上發出→【smtp.sina.com.cn】→【sohumx139.sohu.com】→【it315_test@sohu.com】。例程3-1中的第6行的“Received:?(qmail?49221?invoked?from?network)”是sina的SMTP服務器內部調用的一個郵件發送模塊添加的,它說明sina的SMTP服務器接收到郵件后再通過這個郵件發送模塊將郵件轉發出去。顯然,通過分析一封郵件的源內容,是可以知道發件人的IP地址的。?


圖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消息之間的分隔符
?
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語句來引用該圖片資源:
<img?src="cid: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語句來引用該圖片資源:
<img?src="http://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語句來引用該圖片資源:
<img?src="http://www.it315.org/images/it315logo.gif">??
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!
在第一行末尾的“=”字符和換行,都是由于編碼后生成的。?MIME實例分析
了解MIME協議的基本組織結構后,下面用Outlook?Express撰寫出一封顯示效果如圖3.4所示的電子郵件,然后分析該郵件的源文件,以便讀者更加深入地了解MIME協議。
?
啟動Outlook?Express,單擊工具欄中的“創建郵件”按鈕,在打開的“新郵件”對話框中輸入收件人地址、
主題和郵件正文,然后選中郵件正文,單擊編輯窗口的工具欄上的“》”按鈕,在彈出的菜單欄中單擊表示超鏈接的圖標,如圖3.7所示。
?
圖3.7
?
在打開的“超級鏈接”對話框中輸入如圖3.8所示的內容,然后單擊“OK”按紐。
?
圖3.8
?再次單擊編輯窗口的工具欄上的“》”按鈕,在打開的如圖3.7所示的菜單欄中單擊表示圖片的圖標,在打開
的“圖片”對話框中單擊“瀏覽”按鈕,然后通過打開的對話框選擇一個圖片文件,結果如圖3.9所示。
?
單擊圖3.9中的“OK”按鈕,結果如圖3.10所示。
?
單擊圖3.10所示窗口中的“插入”à“文件附件”菜單項,在打開的“插入附件”對話框窗口中選擇需要發送的附件
單擊“附件”按鈕,插入所選中的附件。
?
單擊圖3.10所示窗口中的“文件”à“保存”菜單項,在Outlook?Express主窗口的“草稿”目錄中就可以看到這封郵件
?
將這封郵件從“草稿”目錄中移動到“發件箱”目錄中,接著按照3.1節中講解的查看郵件源文件步驟,打開
剛才撰寫的這封郵件的源文件。或者在“草稿”目錄中選中這封郵件,將它另存為一個eml文件,再用任意一種文本編輯程序打開這個eml文件,這樣也可以查看到剛才撰寫的這封郵件的源文件。為了便于讀者看清郵件內容的組織結構關系,筆者專門為此畫了一個描述郵件中的各個MIME消息分隔符的層次關系的示意圖,如圖3.13所示。
從圖3.13中可以看出,在MIME組合消息的消息體中的每個消息單元都要以一個分割符開始,在組合消息的消息體結束時還需要用一個結束分割符。MIME消息中的分隔符的層次關系與一篇文章中的標題之間的層次關系非常相似,只是在每個組合消息結束時還要增加一個結束“標題”。為了便于講解,筆者對剛才撰寫的郵件源文件內容進行了適當修改,并添加了相應的注釋,如下所示:
?
圖3.13
1:From:?"it315"?<it315_test@sohu.com>?
2:To:?<it315_test@sohu.com>

3:Subject:?=?gb2312?B?TUlNRdCt0unLtcP308q8/g==?=

4:Date:?Thu,?1?Dec?2005?20: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:?Microsoft?Outlook?Express?6.00.2900.2670

11:X-MimeOLE:?Produced?By?Microsoft?MimeOLE?V6.00.2900.2670

12:

13:This?is?a?multi-part?message?in?MIME?format.//郵件注釋

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:------=_NextPart_002_0052_01C?

25:Content-Type:?text/plain;

26:?charset="gb2312"

27:Content-Transfer-Encoding:?base64

28:

29:u7bTrbTzvNK3w87KztLDx7XEzfjVvg0KDQog

????????????????????//經BASE64編碼后的文本格式的郵件正文

30:

????????//郵件正文內部的第一部分的第二部分的開始標記

31:------=_NextPart_002_0052_01C?

32:Content-Type:?text/html;

33:?charset="gb2312"

34:Content-Transfer-Encoding:?base64

35:

36:PCFET0NUWVBFIEhUTUwgUFVC......//經BASE64編碼后的HTML格式的郵件正文?

37:

????????//郵件正文內部的第一部分的的結束標記

38:------=_NextPart_002_0052_01C--?

39:

????//郵件正文內部的第二部分(HTML中的內嵌資源)的開始標記

40:------=_NextPart_001_0051_01C?

41:Content-Type:?image/gif;

42:?name="logo.gif"

43:Content-Transfer-Encoding:?base64

44:Content-ID:?<004f01c5f675$4e210300$b501a8c0@zxx>

45:

46:R0lGODlh/ABGAOYAADdhmaekZjxsq0N4vHik

47:xK27z9CtCJWpxCZEa3aczejr7......

????????????????????//?HTML中內嵌的經BASE64編碼后的圖片數據

48:

????//郵件正文的結束標記

49:------=_NextPart_001_0051_01C—

50:

//整個郵件內容的第二部分(第一個附件)的開始標記

51:------=_NextPart_000_0050_01C?

52:Content-Type:?application/x-msdownload;

53:?name="daemon.exe"

54:Content-Transfer-Encoding:?base64

55:Content-Disposition:?attachment;//聲明內容類型為附件

56:?filename="daemon.exe"

57:

58:TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA

?59:AAAA0AAAAA4fug4AtAnNAAAAAA......//?第一個郵件附件內容

60:

//整個郵件內容的第三部分(第二個附件)的開始標記

61:------=_NextPart_000_0050_01C?

62:Content-Type:?audio/wav;

63:?name="sndrec.wav"

64:Content-Transfer-Encoding:?base64

65:Content-Disposition:?attachment;//聲明內容類型為附件

66:?filename="sndrec.wav"

67:

68:UklGRjIAAABXQVZFZm10IBIAAAABAAEAIlYAACJWAAABAAgAKABmYWN0

69:AA==AAAAAAAAAAAAAAAAAACCC......//第二個郵件附件內容

70:

//整個郵件內容的結束標記

71:------=_NextPart_000_0050_01C5F6B8.5C492500--


源文件中第1~11行為郵件的郵件頭,第15~71行為郵件體。郵件體中的15~49行為郵件正文,第51-59行為郵件的第一個附件,第61~71行為第二個附件。讀者只要對照圖3.13來閱讀,就很容易看出這個郵件源文件內容的組織結構。關于上述的郵件源文件內容,還需要做出如下三點補充解釋:
(1)每個MIME組合消息的Content-type頭字段中的boundary屬性用于定義其中嵌套的各個MIME消息之間的分隔符,如源文件中的第7行、第18行和第22行等。在各個MIME組合消息內部的起始分隔符是在該MIME組合消息的Content-type頭字段中的boundary屬性值前面增加了兩個減號(-)字符而形成的,如源文件中的第15行、第20行和第24行等;而每個MIME組合消息的結束分隔符則是在其起始分隔符的后面又添加兩個減號(-)字符而形成的,如源文件中的第38行、第49行和第71行。
(2)在每個MIME組合消息的消息體之前(即第一個開始分隔符之前),可以有一些附加的文本行,這些文本行相當于MIME消息的注釋,在解碼時將被忽略,如源文件的13行。
(3)源文件中的第44行使用Content-ID頭字段為內嵌的圖片資源指定了一個唯一標識號,在HTML格式的正文中需要使用這個唯一標識號來引用相應的內嵌資源,其引用語句為<img?src=?"cid:
004f01c5f675$4e210300$b501a8c0@zxx">,但是由于整個HTML正文部分采用了Base64編碼,所以在源文件的HTML正文部分無法看到原始的引用語句。
多學兩招??郵件傳播病毒的原理

MIME協議其實就是一種郵件內容的組織協議,支持MIME協議的郵件閱讀程序將根據MIME消息頭中定義的MIME類型,調用相應的解析程序來處理消息體中的數據。例如MIME消息頭中定義為郵件附件時,郵件閱讀程序會提示用戶保存消息體中的數據,如果定義為圖像文件時,郵件閱讀程序則把消息體中的數據作為一個圖像文件自動打開。
由于郵件數據通常是經過BASE64編碼后的ASCII碼數據,郵件閱讀程序只能通過分析數據的MIME消息頭來獲知數據類型,無法通過分析數據本身來獲知數據的類型,因此,一些病毒制造者就可以把病毒程序進行BASE64編碼后,再附加在郵件的MIME消息體中,然后在MIME消息頭中將其MIME類型定義為圖片或聲音等類型,而文件名的擴展名卻為.exe。這樣,當郵件閱讀程序解碼帶有病毒程序的MIME消息體后,將執行解碼后得到的病毒程序。前些年曾經在全球范圍內流行的Nimda病毒,就是通過這種方式進行傳播的,其示意源代碼如下:
MIME-Version:?1.0
Content-Type:?multipart/related;//聲明所包含內容為內嵌資源??type="multipart/alternative";
?boundary="====_ABC1234567890DEF_===="?--====_ABC1234567890DEF_====?Content-Type:?multipart/alternative;
?boundary="====_ABC0987654321DEF_===="?--====_ABC0987654321DEF_====?Content-Type:?text/html;???charset="iso-8859-1"
Content-Transfer-Encoding:?7bit
<HTML><HEAD></HEAD><BODY?bgColor=#ffffff>?<iframe?src=cid:EA4DMGBP9p?height=0?width=0>?</iframe></BODY></HTML>
--====_ABC0987654321DEF_====--?--====_ABC1234567890DEF_====
Content-Type:?audio/x-wav;?name="readme.exe"?????????????????????//把exe文件定義成一個wav文件
Content-Transfer-Encoding:?base64?Content-ID:?<EA4DMGBP9p>
TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAA……//經BASE64編碼后的病毒源代碼
--====_ABC1234567890DEF_====
這封郵件傳播病毒的運行原理非常簡單,如上面的源文件中的黑體字部分及相應注釋所示,它就是將一個可執行文件(readme.exe)作為一個audio/x-wav類型的聲音文件嵌入到HTML頁面中。由于最初的Outlook?Express程序沒有檢查MIME消息的Content-Type頭字段定義的MIME類型與其中的name屬性指定的文件擴展名是否匹配,于是導致用戶打開郵件時將執行解碼后的readme.exe程序,從而感染上了病毒。這個病毒程序又利用Outlook?Express中的地址簿向別人發送帶毒的郵件,這樣一傳十,十傳百,Nimda蠕蟲就大行其道了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/276317.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/276317.shtml
英文地址,請注明出處:http://en.pswp.cn/news/276317.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

溝通:用故事產生共鳴

《溝通:用故事產生共鳴》(全彩) 基本信息作者&#xff1a; Nancy Duarte(南希.杜瓦特)譯者&#xff1a; 馮海洋出版社&#xff1a;電子工業出版社ISBN&#xff1a;9787121195914上架時間&#xff1a;2013-4-1出版日期&#xff1a;2013 年3月開本&#xff1a;12開頁碼&#xff1…

合工大五套卷_2020合工大超越數一五套卷第一套感想

合工大的卷子確實不錯&#xff0c;題目給我的感覺是題干包裝的看起來就很難&#xff0c;但是寫起來還是一樣的套路。計算上要難一些&#xff0c;需要細心點選擇題:1.可去間斷點的定義和泰勒公式2.這個題我用排除法寫的&#xff0c;可微的話連續和偏導存在都成立了&#xff0c;然…

DotNet關鍵知識點——WPF篇(一)(范德成編輯批注版)

1. Journal 的使用 Journal 用于在 XAML 瀏覽器應用程序&#xff08;XBAP&#xff09;中維護歷史訪問頁。刪除前一訪問頁只需調當前 NavigationService 對象的 RemoveBackEntry() 即可&#xff1b;而增加一個訪問頁則復雜得多&#xff1a; 1) 實現一個 CustomContentState 的派…

若川的2018年度總結,平淡無奇

可以點擊上方的標簽若川的故事、年度總結&#xff0c;查看往期文章偷偷告訴你&#xff0c;公眾號內回復【報告】&#xff0c;可以獲取你自己的github 2020 年度報告昨晚在我的6個微信群里都發了紅包&#xff0c;以這樣的方式跨過了2020年。運營公眾號真的挺難的&#xff0c;比如…

Simple TCP Server Client Socket C

轉載鏈接&#xff1a;http://blog.163.com/caipeipei_love126/blog/static/2596603220101118433940/ tcpserver.c #include<stdlib.h> #include<stdio.h> #include<errno.h> #include<string.h> #include<netdb.h> #include<sys/types.h>…

基于dnn的車牌識別_自然場景中文文字識別,身份證火車票都能識別

圖像處理中OCR(Optical Character Recognition光學字符識別)場景非常多&#xff0c;也給大家的工作生活帶來了很多便利&#xff0c;比如車牌識別就能管理停車場車輛的出入&#xff0c;快遞時只需給一個帶有快遞信息的圖就能自動解析上傳發件信息和收件信息&#xff0c;再比如我…

年末的大廠前端面試總結(20屆雙非二本)-終入字節

關注若川視野, 回復"pdf" 領取資料&#xff0c;回復"1"&#xff0c;可加群長期交流學習自我介紹雙非二本,軟件工程,自學前端,今年畢業。喜歡編程,古風,日語和英語。常以冷月心之名混跡前端江湖,也曾在混跡網文圈時用冷月心做筆名簽約掌閱,作品《清起風云》…

面試題(轉的)

第一組   1.燒一根不均勻的繩&#xff0c;從頭燒到尾總共需要1個小時。現在有若干條材質相同的繩子&#xff0c;問如何用燒繩的方法來計時一個小時十五分鐘呢?  2.你有一桶果凍&#xff0c;其中有黃色、綠色、紅色三種&#xff0c;閉上眼睛抓取同種顏色的兩個。抓取多少個…

python三酷貓_洛克王國三代酷貓登場 冰水酷貓解析

洛克王國三代酷貓登場 冰水酷貓解析 洛克王國三代武斗酷貓解析三代水靈&#xff0c;在哥斯拉的傾情推薦下&#xff0c;小洛克們都已經很熟悉了吧&#xff01;那和水靈同一期出現的帥哥——武斗酷貓&#xff0c;如果三代遺傳了&#xff0c;會怎么樣呢&#xff1f;小洛克們一起來…

Linux禁止用戶登錄

轉載鏈接&#xff1a;http://blog.sina.com.cn/s/blog_4cebadd10100a9bl.html 我們在做系統維護的時候&#xff0c;希望個別用戶或者所有用戶不能登錄系統&#xff0c;保證系統在維護期間正常運行。這個時候我們就要禁止用戶登錄。 1、禁止個別用戶登錄。比如禁止lynn用戶登錄…

.NET常用功能和代碼[總結與收藏]

1. 打開新的窗口并傳送參數&#xff1a; 傳送參數&#xff1a;response.write("<script>window.open(*.aspx?id"this.DropDownList1.SelectIndex"&id1"...")</script>") 接收參數&#xff1a;string a Request.QueryString(&q…

topcoder srm 305 div1

problem1 link 直接按照題意模擬即可。 import java.util.*; import java.math.*; import static java.lang.Math.*;public class UnfairDivision {public int albertsShare(int[] assets) {final int nassets.length;for(int i1;i<n;i) {assets[i]assets[i-1];}int result0…

動圖演示23個鮮為人知的VSCode快捷鍵

原文地址&#xff1a;https://dev.to/devmount/23-lesser-known-vs-code-shortcuts-as-gif-80盡管我在VS Code中經常使用許多快捷方式&#xff0c;以下快捷方式可能會派上用場&#xff0c;但我經常忘記它們的存在。我制作了一些GIF&#xff0c;以便更好地記住它們。也許這里面也…

使用C語言進行面向對象的開發--GObject入門[5]

轉載請注明出處 blog.csdn.net/pingf0 或www.cnblogs.com/pingf 接上文這一部分簡要介紹下類的析構&#xff0c;或者成為終結。還是多說幾句&#xff0c;也算是對前文的補充1.生成一個類是由父到子&#xff0c;析構的時候自然與之相對是由子到父。2.GObject的內存管理并沒有采用…

python結課報告_Python數據分析課程到底是學什么內容的?

2020年12月4日&#xff0c;博為峰旗下學掌門召開了《Python 商業(大)數據分析師》新課程發布會。據悉&#xff0c;此次發布會上發布的《Python 商業(大)數據分析師》課程是在原《數據分析師》課程上進行了全面升級。在發布會上博為峰副總經理王琰表示&#xff0c;在未來學掌門作…

linux禁止root用戶直接登錄sshd并修改默認端口

轉載鏈接&#xff1a;http://jingyan.baidu.com/article/a681b0de3a657c3b184346d9.html linux最高權限用戶root&#xff0c;默認可以直接登錄sshd。為了提高服務器的安全度&#xff0c;需要對它進行禁止&#xff0c;使得攻擊者無法通過暴力破解來獲取root權限。 1,新建一個用…

面試官問:能否模擬實現JS的bind方法(高頻考點)

可以點擊上方的話題JS基礎系列&#xff0c;查看往期文章寫于2018年11月21日&#xff0c;發布在掘金閱讀量1.3w前言這是面試官問系列的第二篇&#xff0c;旨在幫助讀者提升JS基礎知識&#xff0c;包含new、call、apply、this、繼承相關知識。面試官問系列文章如下&#xff1a;感…

推薦一個ASP.NET的資源網站

推薦一個ASP.NET的資源網站&#xff1a;ASP.NET屋-專業的ASP.NET學習,ASP.NET源碼,ASP.NET演示,MVC,Silverlight,JQuery,EXTJS,軟件設計網站 http://www.aspx58.com.cn/ 轉載于:https://www.cnblogs.com/yuyichen/archive/2009/11/26/1611682.html

連續投影算法_中航國畫榮獲“2020 IAV國際視聽嘉年華” 大屏幕投影顯示行業三大獎項!...

近日&#xff0c;“2020IAV國際視聽嘉年華”在深圳灣創新生態園隆重舉行&#xff0c;航空工業上電下屬子公司中航國畫作為2020年迪拜世博會中國館官方合作伙伴應邀參加此次高峰論壇&#xff0c;并在展會期間憑借4K系列雙色激光工程投影機、LP160UL系列超高亮度雙色激光工程投影…