郵件服務器基礎:郵件服務相關協議二
我們簡單地比較一下SMTP和HTTP。這兩個協議都是用于從一臺主機向另一臺主機傳送文件;HTTP用于從web服務器向Web用戶代理(即瀏覽器)傳送文件(或對象),SMTP用于從一個郵件服務器向另一個郵件服務器傳送文件(也就是電子郵件消息)。在傳送文件時,SMTP和持久HTTP都使用持久連接。可見,這兩個協議具有一些共同的特征,不過它們之間的差別也是顯著的。首先,HTTP基本上是一個內拉式協議(pull protocol)——有人把信息上傳到web服務器中,用戶則在方便的時候使用HTTP把這些信息從服務器上拉過來。更確切地說,TCP連接是由想要接收文件的主機發起的。SMIP則基本上是一個外推式協議(pushProtoco1)——發送端郵件服務器把文件推送給接收端郵件服務器。更確切地說,TCP連接是由想要發送文件的主機發起的。
SMTP和HTTP的第二個重要差別是,SMTP要求包括信體部分在內的每個郵件消息都是7位ASCII文本格式。另外,SMTP RFC還要求每個郵件消息的信體以僅由單個點號構成的一行結束,改用ASCII字符名稱來說就是每個郵件消息的信體必須以“CRLF.CRLF“結尾,其中CR和LF分別代表回車符和換行符。這種方式下,當從同一個SMTP客戶接收一系列郵件消息時,SMTP服務器可以通過在字節流中搜索“CRLF.CRLF”來分割每個消息。要是信體不是ASCII文本,而是二進制數據(譬如說一幅JPEG圖像),那么這些二進制數據字節流中偶爾出現“CRLF.CRLF”這一模式是有可能的。這將導致SMTP服務器不正確地認定當前郵件消息已結束。為避免這樣的問題,二進制數據應以一定的方式先編碼成ASCII文本,保證其中不使用特定的ASCH字符(包括點號)。HTTP無論是持久的還是非持久的都不需要預先把二進制數據轉換成ASCII本。對于持久的HTTP,每個TCP連接只傳送一個對象:服務器關閉連接后,客戶就知道己接收到一個完整的響應消息。對于非持久的HTTP,每個響應消息中包含一個Content-length:頭部,使得客戶能夠確定每個響應消息的邊界。
SMTP和HTTP的第三個重要差別涉及如何處理包含文本和圖像或其他媒體類型的文檔。HTTP是把每個對象封裝在各自的HTTP響應消息中。SMTP(正如接下去要詳細討論的那樣)是把同一個郵件內的各個對象置于同一個郵件消息中。
郵件消息格式和MIME
當Alice給Bob發一封普通的郵政信件時,她把這封信裝入一個信封里,在信封上寫明Bob的地址和自己的回信地址,然后投入郵箱;郵政業務在遞送這封信的過程中,也會把表明時間和地點的郵戳蓋在信封上。類似地,當電子郵件消息從一個人傳送到另——個人時,在信體之前會有一個含有這些外圍信息的信頭。這些信息實際上由一系列在RFC 822中定義的郵件消息頭部及其值構成。郵件消息中構成信頭的各個頭部和信體之間以一個空行(也就是CRLF)分割。RFC 822詳細說明了各個郵件消息頭部的格式和含義。與HTTP一樣,郵件消息的每個頭部都是直觀可讀的文本,由一個后跟冒號的關鍵字和相應的值構成。郵件消息的頭部有些是必須的,有些則是司選的。每個信頭必須有一個From:頭部和一個To:頭部.還可以有一個Subject:頭部和其他頭部。需注意的是,這些頭部和先前討論的SMTP命令不是一回事:SMTP命令是SMTP握手協議的一部分,郵件消息頭部則屬于郵件消息的一部分。
下面是一個典型的電子郵件信頭:
From:alice@crepes.fr
To:bob@hamburger.edu
Subject:this is a test
信頭之后空一行就是信體。整個消息以只含有一個點號的單獨行結束。
非ASCII數據的MlME擴展
RFC 822中說明的郵件消息頭部盡管足以滿足發送普通ASCII文本郵件的要求,但是在多媒體消息(例如,包含圖像、音頻或視頻數據的消息)的描述和非ASCII文本格式(例如,非英語國家使用的文字)的承載上,卻顯然不夠。要發送非ASCII文本的郵件消息,必須由發送者的用戶代理在其中增添額外的頭部RFC 2045和RFC 2046定義了這些額外的頭部,它們是對RFC 822的多用途因特網郵件擴展(Multipurpose Internet Mail Extensions,簡稱MIME)。
支持多媒體的兩個關鍵MIME頭部是Content-Type:和Content-Tansfer-Encoding:。Content-Type:頭部允許接收用戶代理對郵件消息采取合適的行動。例如,通過指出信體內容為一個JPG圖像,接收用戶代理可以把信仲定向到某個JNG解壓縮例程。我們已經知道,為確保SMTP正常工作,非ASCII文本消息必須預先編碼成ASCH文本格式。
Content-Tansfer-Encoding:頭部用于告知接收用戶代理信體已被編碼咸ASCII格式,并指出具體編碼方式。這樣,當某個用戶代理收到一個包含這兩個頭部的郵件消息時,它首先使用Content-Tansfer-Encoding:頭部的值把信體轉換成原始的非AscH文本形式,再使用Content-Type:頭部的值確定自己應該對信體采取什么行動。
下面看一個具體的例子。假設Alice想給Bob發送一個JPEG圖像,她為此調用自己的用戶代理,給出Bob的電子郵件地址和郵件消息的主題,并把這個JPG圖像插入這個郵件消息的信體中(這個圖像有可能是作為該郵件消息的“附件”插入的,具體取決于Alice所用的用戶代理)。Alice填寫完郵件消息后讓用戶代理把它發送出去。Alice的用戶代理生成一個大體如下的MIME消息:
From:alice@crepes.fr
To:bob@hamburger.edu
Subject:picture of mine
MIME-Version:1.0
Content-Transfer-Encoding:base64
Content-Type:image/jpeg
{...base64編碼數據...)
{...base64編碼數據...)
從中我們可以看到,alice的用戶代理采用base64編碼格式對這個JPEG圖像進行編碼i而base64是在MIME中標準化的用于轉換成某種可接受的7位ASCII格式的編碼技術之一[RFC 2045]。另一種流行的內容傳送編碼技術稱為帶轉義的可打印(叫quoted-printable)編碼格式,一般用于把普通的ASCII郵件消息轉換成不帶非期望字符串(例如由單個點號構成的行)的ASCII文本。
Bob閱讀郵件時,其用戶代理所操作的是同一個MIME消息。該用戶代理看到值為base64的Content-Transfer-Encoding:頭部后,知道該郵件消息中還有一個值為image/jpeg的Content-Type:頭部,它告知Bob的用戶代理應該對信體進行JPEG解壓縮。該郵件消息中的MIME-Version:頭部自然是在指示本消息所用的MIME版本。需注意的是,郵件消息的其余部分仍然遵循標準的RFC 922/SMTP格式。具體地說,在信頭之后有一個空行,接著是信體:在信體結束處是一個僅由單個點號構成的行。
我們接下去深入討論一下Content-Type;頭部。該頭部按照MIME規范[RFC 2046]有如下的格式;
Content-Type: type/subtype; parameters
其中parameters(以及其前面的分號)是可選的。通過在Content-Type:頭部給出媒體類型名和子類型名,MIME消息信體中數據的性質得以說明。類型名和子類型名之后的其余部分是一組參數。總的說來,頂級類型名用于聲明數據的一般類型,子類型名用于指明這類數據中的某種具體格式。參數是對于類型的修飾說明,具體取決于類型和子類型本身,基本上不影響內容性質的指定。MIME是按照可擴展這一目標仔細地設計的,并預期媒體類型/子類型以及它們的相關參數會隨時間顯著增長。為確保以有秩序的文檔完備公開的方式開發這些類型/子類型,MIME建立了一套注冊程式,把因特網已分配數值權威(Internet Asigned Numbers Authority,簡稱IANA)作為MIME各個可擴展域的中心注冊處。BFC 2048具體說明了這些可擴展域的注冊程式。
當前已定義的MIME頂級類型共有7個,每個類型關聯一組子類型,其數量在逐年增長。下面是其中的5個類型;
●text;text類型用于向接收者的用戶代理指出消息體為文本。該類型極為普遍的一個類型/子類型對為text/plain。子類型plain指定不含任何格式定義信息的普通文本。plain文本應該不加任何解釋地按照原樣顯示,不需要特殊的軟件,能支持給定的字符集就行。在實際的郵件消息中經常能看到值為比text/plain;charset=gb2312或text/plain;charset="ISO—8859—1"的Content-Type:頭部,其中的參數指出用于產生相應消息的字符集。另一個變得越來越普遍的類型/子類型對是text/html。子類型html指示接收用戶代理解釋嵌埋在消息體中的html標記,從而像Web頁面那樣顯示信件內容,其中有可能包含各種字體的文本、超鏈接、Java小應用程序,等等。
●image:image類型用于向接收用戶代理指出消息體為圖像。該類型較為流行的兩個類型/子類型對為iamge/gif和image/jpeg,接收用戶代理碰到這樣的類型時,就知道該把消息體作為GIF圖像或JPEG圖像解碼并顯示。
●audio:audio類型需要音頻輸出設備(例如揚聲器或電話)來表達內容。這類型中常見的已標準化子類型包括basic(基本8位u-law編碼)和32kadpcm(RFC 1911中定義的一種32Kbps格式)。
●video:video類型的子類型包括mpeg和quicktime。
●application:application類型適用于不適合歸為其他類別的數據,通常用在必須由某個應用程序預先處理才能為用戶所見或所用的數據上。例如.當用戶在某個電子郵件消息中附帶一個微軟word文檔時,其用戶代理一般把它的類型子類型對指定為application/msword;這將導致接收用戶代理啟動微軟word應用程序,并把該MIME消息的信體傳遞給它處理。這類型極為重要的一個子類型是octet-stream,它用于指示信體含有任意的二進制數據。收到內容類型為application/octet-stream的郵件消息后,接收用戶代理會提示用戶是否把信體保存到硬盤中,以便稍后處理。
【編輯推薦】