郵件協議之MIME

哎呀嚇死我了發表於2019-03-04

一、MIME: Multipurpose Internet Mail Extensions


  英國帝國大學計算機線上字典FOLDOC對MIME的解釋為:“多部分(multi-part)、多媒體電子郵件和WWW超文字的一種編碼標準,用於傳送諸如圖形、聲音和傳真等非文字資料。MIME定義於RFC1341,用MIMENCODE的方法將二進位制資料轉換成為一種被稱為BASE64的ASCII子集的字元的組合。”


  Internet上有專門討論MIME的新聞組: comp.mail.mime。該新聞組的FAQ可以從下面的網點獲得:

       


  MIMENCODE最早稱為MMENCODE,提出用MIMENCODE代替UUENCODE,是因為UUENCODE使用了一些字元在一些郵件閘道器(特別是那些轉換ASCII和EBCDIC碼的閘道器)中造成傳輸障礙,(還有一些軟體不能對所有 UUENCODE 的演算法進行正確解碼而導致郵件的閱讀困難),因此 MIME 被設計用於替代UUENCODE,但是結果是這些協議共存。

在MIME出來之前,使用RFC 822只能傳送基本的ASCII碼文字資訊,郵件內容如果要包括二進位制檔案、聲音和動畫等,實現起來非常困難。

MIME提供了一種可以在郵件中附加多種不同編碼檔案的方法,彌補了原來的資訊格式的不足。實際上不僅僅是郵件編碼,現在MIME經成為HTTP協議標準的一個部分。


二、MIME編碼方式簡介


  對郵件進行編碼最初的原因是因為 Internet 上的很多閘道器不能正確傳輸8bit內碼的字元,比如漢字等。編碼的原理就是把8bit的內容轉換成7bit的形式以能正確傳輸,在接收方收到之後,再將其還原成8bit的內容。

  在MIME協議之前,郵件的編碼曾經有過UUENCODE等編碼方式 ,但是由於MIME協議演算法簡單,並且易於擴充套件,現在已經成為郵件編碼方式的主流,不僅是用來傳輸8bit的字元,也可以用來傳送二進位制的檔案,如郵件附件中的影像、音訊等資訊,而且擴充套件了很多基於MIME 的應用。從編碼方式來說,MIME定義了兩種編碼方法Base64與QP(Quote-Printable)。


1.Base64編碼

  Base64是一種通用的方法,其原理很簡單,就是把三個Byte的資料用4個Byte表示。在這四個Byte中,實際用到的都只有前面6bit,這樣就不存在只能傳輸7bit的字元的問題了。Base64的縮寫一般是“B”。

Base64將輸入的字串或一段資料編碼成只含有{‘A’-‘Z’, ‘a’-‘z’, ‘0’-‘9’, ‘+’, ‘/’}這64個字元的串,’=’用於填充。

其編碼的方法是,將輸入資料流每次取6bit,用此6bit的值(0-63)作為索引去查表,輸出相應字元。

這樣,每3個位元組將編碼為4個字元(3×8 → 4×6);不滿4個字元的以’=’填充。

有的場合,以“=?charset?B?xxxxxxxx?=”表示xxxxxxxx是Base64編碼,且原文的字符集是charset。在段體內則直接編碼,適當時機換行,MIME建議每行最多76個字元。

Base64的演算法很簡單,它將字元流順序放入一個24位的緩衝區,缺字元的地方補零。

然後將緩衝區截斷成為4個部分,高位在先,每個部分6位,用64個字元重新表示。如果輸入只有一個或兩個位元組,那麼輸出將用等號“=”補足。這可以隔斷附加的資訊造成編碼的混亂。


2.QP編碼

  另一種方法是QP(Quote-Printable) 方法,通常縮寫為“Q”方法,其原理是把一個8bit的字元用兩個16進位制數值表示,然後在前面加“=”。所以我們看到經過QP編碼後的檔案通常是這個樣子:=B3=C2=BF=A1=C7=E5=A3= AC=C4=FA=BA=C3=A3=A1。

Quoted -printable根據輸入的字串或位元組範圍進行編碼,若是不需編碼的字元,直接輸出。若需要編碼,則先輸出’=’,後面跟著以2個字元表示的十六進位制位元組值。有的場合,以“=?charset?Q?xxxxxxxx?=”表示xxxxxxxx是Quoted-printable編碼,且原文的字符集是charset。在段體內則直接編碼,適當時機換行,換行前額外輸出一個’=’。

 

三、MIME的頭資訊

郵件頭

在郵件頭中,有很多從RFC 822沿用的域名,MIME也增加了一些。常見的標準域名和含義如下:

域名 含義 新增者

Received 傳輸路徑 各級郵件伺服器

Return-Path 回覆地址 目標郵件伺服器

Delivered-To 傳送地址 目標郵件伺服器

Reply-To 回覆地址 郵件的建立者

From 發件人地址 郵件的建立者

To 收件人地址 郵件的建立者

Cc 抄送地址 郵件的建立者

Bcc 暗送地址 郵件的建立者

Date 日期和時間 郵件的建立者

Subject 主題 郵件的建立者

Message-ID 訊息ID 郵件的建立者

MIME-Version MIME版本 郵件的建立者

Content-Type 內容的型別 郵件的建立者

Content-Transfer-Encoding 內容的傳輸編碼方式 郵件的建立者

非標準的、自定義域名都以X-開頭,例如X-Mailer, X-MSMail-Priority等,通常在接收和傳送郵件的是同一程式時才能理解它們的意義。

段頭

在段頭中,大致有如下一些域:

域名 含義

Content-Type 段體的型別

Content-Transfer-Encoding 段體的傳輸編碼方式

Content-Disposition 段體的安排方式

Content-ID 段體的ID

Content-Location 段體的位置(路徑)

Content-Base 段體的基位置

有的域除了值之外,還帶有引數。值與引數、引數與引數之間以“;”分隔。引數名與引數值之間以“=”分隔。


1.MIME-Version

  表示使用的MIME的版本號,一般是1.0;

如:

MIME-Version: 1.0


2.Content-Type

Content-Type定義了正文的型別,我們實際上是透過這個標識來知道正文內是什麼型別的檔案。比如:text/plain 表示的是無格式的文字正文,text/html 表示的 Html 文件,image/gif 表示的是 gif 格式的圖片等等。Content-Type都是“主型別/子型別”的形式。主型別有text, image, audio, video, application, multipart, message等,分別表示文字、圖片、音訊、影片、應用、分段、訊息等。每個主型別都可能有多個子型別,如text型別就包含plain, html, xml, css等子型別。以X-開頭的主型別和子型別,同樣表示自定義的型別,未向IANA正式註冊,但大多已經約定成俗了。如application/x-zip-compressed是ZIP檔案型別。在Windows中,登錄檔的“HKEY_CLASSES_ROOT/MIME/Database/Content Type”內列舉了除multipart之外大部分已知的Content-Type。

關於引數的形式,RFC裡有很多補充規定,有的允許帶幾個引數,較為常見的有:

主型別 引數名 含義

text charset 字符集

image name 名稱

application name 名稱

multipart boundary 邊界

multipart型別

郵件中常用到的複合型別:multipart。

multipart型別表示正文是由多個部分組成的,後面的子型別說明的是這些部分之間的關係。

 

郵件中用到的三個型別有:

(1).multipart/alternative:表示正文由兩個部分組成,可以選擇其中的任意一個。主要作用是在徵文同時有text格式和html格式時,可以在兩個正文中選擇一個來顯示,支援 html 格式的郵件客戶端軟體一般會顯示其 HTML 正文,而不支援的則會顯示其Text正文;

(2).multipart/mixed:表示文件的多個部分是混合的,指正文與附件的關係。如果郵件的MIME型別是multipart/mixed,即表示郵件帶有附件。

(3).multipart/related:表示文件的多個部分是相關的,一般用來描述 Html 正文與其相關的圖片。

 

multipart型別,是MIME郵件的精髓。郵件體被分為多個段,每個段又包含段頭和段體兩部分,這兩部分之間也以空行分隔。它們之間的層次關係可歸納為下圖所示:

+————————- multipart/mixed —————————-+

| |

| +—————– multipart/related ——————+ |

| | | |

| | +—– multipart/alternative ——+ +———-+ | +——+ |

| | | | | 內嵌資源 | | | 附件 | |

| | | +————+ +————+ | +———-+ | +——+ |

| | | | 純文字正文 | | 超文字正文 | | | |

| | | +————+ +————+ | +———-+ | +——+ |

| | | | | 內嵌資源 | | | 附件 | |

| | +———————————-+ +———-+ | +——+ |

| | | |

| +——————————————————+ |

| |

+———————————————————————-+

 

可以看出,如果在郵件中要新增附件,必須定義multipart/mixed段;如果存在內嵌資源,至少要定義multipart/related段;如果純文字與超文字共存,至少要定義multipart/alternative段。什麼是“至少”?舉個例子說,如果只有純文字與超文字正文,那麼在郵件頭中將型別擴大化,定義為multipart/related,甚至multipart/mixed,都是允許的。

multipart諸型別的共同特徵是,在段頭指定“boundary”引數字串,段體內的每個子段以此串定界。所有的子段都以“--”+boundary行開始,父段則以“--”+boundary+“--”行結束。段與段之間也以空行分隔。在郵件體是multipart型別的情況下,郵件體的開始部分(第一個“--” +boundary行之前)可以有一些附加的文字行,相當於註釋,解碼時應忽略。段間也可以有一些附加的文字行,不會顯示出來。


  這些複合型別又是可以巢狀使用的,比如說一個帶有附件的郵件,同時有html與text兩種格式的正文,則郵件的結構是:

  Content-Type: multipart/mixed

  部分一:

  Content Type : multipart/alternative:

  Text 正文;

  Html 格式的正文 

  部分二:

  附件

  郵件結束符;

  由於複合型別由多個部分組成,因此,需要一個分隔符來分隔這多個部分,這就是上面的郵件原始檔中的boundary所描述的,對於每一個Contect type :multipart/* 的內容,都會有這麼一個說明,表示多個部分之間的分隔。

  含有 MIME/BASE64編碼的郵件,你檢視它的原始碼時一般都含有:“This is a multi-part message in MIME format.”這樣的句子。也可以被絕大多數的email程式進行解碼,包括Netscape、MS Mail、Eudora等。這些程式可以正確識別郵件的正文,恢 MIME/BASE64 編碼的部分為正確的文字或夾帶的二進位制檔案。


3.Content-Transfer-Encoding

它表示了這個部分文件的編碼方式。只有識別了這個說明,才能用正確的解碼方式實現對其解碼。

Content-Transfer-Encoding共有Base64, Quoted-printable, 7bit, 8bit, Binary等幾種。

其中7bit是預設的編碼方式。電子郵件原始碼最初設計為全部是可列印的ASCII碼的形式。

非ASCII碼的文字或資料要編碼成要求的格式。

Base64, Quoted-Printable是在非英語國家使用最廣使的編碼方式。

Binary方式只具有象徵意義,而沒有任何實用價值。


4.boundary

這個分隔符是正文中不可能出現的一串古字元的組合,在文件中,以”–”加上這個boundary 來表示一個部分的開始,在文件的結束,以”–”加boundary再在最後加上”–”來表示文件的結束。由於複合型別是可以巢狀使用的,因此,郵件中可能會多個boundary。

 

以上是對MIME的簡單介紹,最近在關注“ 郵件內容安全” ,在找一些公開的“ 郵件加密軟體” ,PGP用起來太麻煩了,不過找到了另外一個“ ,這是一個免費公開的" 郵件內容加密 "平臺,無論是個人還是企業規模化都可以試用,目前還沒有本地版本的,不過從官網上檢視資料其是以" 郵件加密閘道器" 形式存在的,也不用自己管理金鑰,所以還是挺方便安全的。大家如果有更好的可以推薦給我。

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69910739/viewspace-2637453/,如需轉載,請註明出處,否則將追究法律責任。

相關文章