MIME郵件格式分析及信息提取

論文類別:計算機論文 > 計算機理論論文
論文作者:
上傳時間:2008/5/5 11:03:00

摘 要 MIME是目前互联網郵件普遍采用的格式標準,本文通過對MIME郵件格式规範的分析和說明,給出了從郵件中提取其所含各種信息的基本方法。
  關鍵詞 MIME、邮件、格式、信息提取

  MIME,英文全稱為“Multipurpose Internet Mail Extensions”,即多用途互聯網郵件扩展,是目前互聯網電子郵件普遍遵循的郵件技術規範。在MIME出現之前,互聯網電子郵件主要遵循由RFC 822所制定的标準,電子郵件一般只用來傳递基本的ASCII碼文本信息,MIME在 RFC 822的基礎上對電子郵件規範做了大量的擴展,引入了新的格式规範和編碼方式,在MIME的支持下,圖像、聲音、動畫等二進制文件都可方便的通過电子郵件來進行傳遞,極大地豐富了電子郵件的功能。目前互聯網上使用的基本都是遵循MIME規範的電子邮件。
  電子郵件的分析和讀取一般都通過專用的郵件軟件來實現,比如Outlook、Foxmail,但這種第三方軟件無法和開發者自己的系統整合,通過對MIME郵件格式的分析,我們可以在自己的應用程序中實現對MIME郵件所含信息的讀取。

1 MIME郵件格式分析

  MIME技術規範的完整內容由RFC 2045-2049定義,包括了信息格式、媒體類型、编碼方式等各方面的內容,這裏我們只介紹其中的一些關键的格式和規範,通過了解这些格式規範,我們就可以實現以編程的方式从MIME郵件中提取基本的郵件信息。

1.1 域

  MIME郵件的基本信息、格式信息、編碼方式等重要內容都記錄在郵件內的各種域中,域的基本格式:{域名}:{內容},域由域名後面跟“:”再加上域的信息內容構成,一條域在郵件中占一行或者多行,域的首行左側不能有空白字符,比如空格或者制表符,占用多行的域其後續行則必须以空白字符開頭。域的信息內容中還可以包含属性,屬性之間以“;”分隔,属性的格式如下:{屬性名称}=”{屬性值}”。
  表1是一封示例郵件的內容,其中行1-5、行8都是單行的域,行6-7則是一個多行的域,並帶有一個名為charset的屬性,屬性值為us-ascii。
表1 示例電子郵件
行1 From: ”suntao” <suntao@fimmu.com>
行2 To: <yxj@fimmu.com>
行3 Subject: hello world
行4 Date: Mon, 9 Oct 2006 16:51:34 +0800
行5 MIME-Version: 1.0
行6 Content-Type: text/plain;
行7      charset="us-ascii"
行8 Date: Mon, 9 Oct 2006 16:48:25 +0800
行9
行10 Hello world
行11
  郵件規範中定義了大量域,分别用來存儲同郵件相关的各種信息,比如发件人的名字和郵件地址信息存储在From域中,收件人的邮件地址信息存儲在To域中,開發人員可通過查詢RFC文檔得到完整的郵件域定義列表。

1.2 Content-Type域

  Content-Type域定義了郵件中所含各種內容的類型以及相關屬性。郵件所含的文本、超文本、附件等信息都按照對應Content-Type域所指定的媒體類型、存儲位置、編碼方式等信息存儲在郵件中。Content-Type域基本格式:Content-Type:{主類型}/{子類型}。
示例郵件中的行6-7就是一個Content-Type域,主類型為text,子类型為plain,字符集屬性為us-ascii。
表2:MIME郵件中常見的主類型
主类型
常見属性
參數含义
text
charset
文本信息所使用的字符集
image
name
圖像的名稱
application
name
應用程序的名稱
multipart
boundary
郵件分段邊界標識

1.3 multipart類型

  MIME郵件中各種不同類型的內容是分段存儲的,各個段的排列方式、位置信息都通過Content-Type域的multipart類型來定義。multipart類型主要有三種子類型:mixed、alternative、related。
1.3.1 multipart類型基本格式
  ● multipart/mixed類型
  如果一封郵件中含有附件,那郵件的Content-Type域中必須定義multipart/mixed類型,郵件通過multipart/mixed類型中定義的boundary標識將附件内容同郵件其它內容分成不同的段。基本格式如下:
Content-Type: multipart/mixed;
         boundary="{分段標識}"
  ● multipart/alternative類型
  MIME郵件可以傳送超文本內容,但出於兼容性的考慮,一般在發送超文本格式內容的同時會同時發送一個純文本內容的副本,如果郵件中同時存在純文本和超文本內容,則郵件需要在Content-Type域中定義multipart/alternative類型,郵件通过其boundary中的分段標識將純文本、超文本和郵件的其它內容分成不同的段。基本格式如下:
Content-Type: multipart/alternative;
         boundary="{分段標識}"
  ● multipart/related類型
  MIME郵件中除了可以攜带各種附件外,還可以將其它內容以内嵌資源的方式存儲在郵件中。比如我們在發送html格式的郵件內容時,可能使用圖像作為html的背景,html文本會被存儲在alternative段中,而作為背景的图像則會存儲在multipart/related類型定義的段中。基本格式如下:
Content-Type: multipart/related;
         type="multipart/alternative";
         boundary="{分段標識}"
1.3.2 multipart類型的boundary屬性
  multipart的子類型中都定義了各自的boundary屬性,郵件使用這些boundary中定义的字符串作為標識,將郵件內容分成不同的段,段體內的每個子段以“--”+boundary行開始,父段則以“--”+boundary+“--”行结束,不同段之間用空行分隔。
1.3.3 multipart類型的層次关系
表3:multipart子類型之間的層次關系
Multipart/mixed
Multipart/related
Multipart/alternative
純文本正文
超文本正文
內嵌資源
附件
  MIME郵件通過多個Content-Type域的multipart類型將内容分成不同的段,这些段在郵件中不是線形順序排列的,而是存在一個互相包含的層次關系,multipart子類型之間的層次關系結構如表3。

1.4 Content-Transfer-Encoding域

  MIME郵件可以傳送圖像、聲音、視頻以及附件,這些非ASCII碼的數據都是通過一定的編碼規則进行轉換後附著在郵件中進行傳遞的。編碼方式存儲在邮件的Content-Transfer-Encoding域中,一封郵件中可能有多個Content-Transfer-Encoding域,分別對應郵件不同部分内容的編碼方式。目前MIME郵件中的數據編碼普遍采用Base64編碼或Quoted-printable編码來實現。
1.4.1 Base64編码
  Base64編碼的目的是將輸入的數據全部轉换成由64個指定ASCII字符組成的字符序列, 這64個字符由{'A'-'Z', 'a'-'z', '0'-'9', '+', '/'}构成。編碼時將需要轉換的數據每次取出6bit,然後將其轉換成十進制數字,這個數字的範圍最小為0,最大為63,然後查询{'A'-'Z', 'a'-'z', '0'-'9', '+', '/'}構成的字典表,輸出對應位置的ASCII碼字符,這樣每3個字节的數據內容會被轉換成4個字典中的ASCII碼字符,當轉換到數據末尾不足3個字節時,則用“=”來填充。
1.4.2 Quoted-printable編碼
  Quoted-printable編码的目的也是將輸入的信息轉換成可打印的ASCII碼字符,但它是根據信息的內容来決定是否進行編碼,如果讀入的字節處於33-60、62-126範圍內的,這些都是可直接打印的ASCII字符,則直接輸出,如果不是,則將該字節分為兩個4bit,每個用一個16進制數字來表示,然後在前面加“=”,这樣每個需要編碼的字節會被轉換成三個字符來表示。

免費論文下載中心 http://www.hi138.com

2 MIME郵件信息提取

  從上面的分析可以看出,MIME郵件傳遞的實際是一個經過特殊編碼並以約定格式排列的字符序列,我們只需要提取存儲在郵件各種域中的格式、位置和編碼信息,按照根據這些信息從字符序列中提取出對應的字符內容並对其進行反向解碼,就可以得到我們需要的有關內容。
下面給出.Net環境下,利用C#结合正則表達式從郵件中提取相关信息的基本思路和部分代码。

2.1 收件人/发件人/郵件主題的提取

  收件人、發件人、郵件主題是一封郵件的基本組成信息,分別存郵件的From域、To域、Subject域中。開發中只需要通過正則表達式來匹配這些指定的域,然後從匹配結果中取出相關信息即可。
  示例代碼:提取郵件主題
string emailContent = “……”;//emailContent中存儲的是郵件內容
pat = @"^Subject:\s*(?<title>.*)\s*\r\n";
myMatches = Regex.Matches(emailContent,pat,RegexOptions.Multiline);
foreach(Match nextMatch in myMatches)
{
     GroupCollection myGroup = nextMatch.Groups;
     string title = myGroup["title"].ToString();//title變量存儲From域的內容
     ……
}
  需要註意的是上面的代碼提取的是跟隨在Subject:後面的字符串,如果郵件的主題內容是中文或者其它需要編碼的地區文字,則還需要對其進行解码。比如,如果郵件的Subject域中的信息是“你好”,那麽提取出來的字符串会是這種形式:=?gb2312?B?xOO6ww==?=,第一個?同第二個?之間的gb2312代表标題內容所使用的字符集,第二個?和第三個?之間的B代表這部分内容采用的是base64编碼方式,如果采用Quoted-printabel編碼方式則顯示Q,第三個?和第四個?之间則是“你好”經過base64編码後的字符串。

2.2 multipart分段信息的提取

  郵件通過multipart類型将內容分隔成不同的段,各段之間的邊界標識由對應multipart類型的boundary屬性定義。要從郵件中提取出需要的內容,首先需要提取出郵件中的分段信息。下面的代码從一封郵件中提取出所有的multipart類型的名稱和boundary屬性。
示例代碼:提取multipart信息
string emailContent = “……”;//emailContent中存儲的是郵件內容
string pat = @"\bContent-Type:\s*(?<type>\w+/\w+);\s+(type=\S(?<subtype>\S+)\S)?\s+boundary=""(?<flag>\S+)""";
MatchCollection myMatches = Regex.Matches(emailContent,pat);
foreach(Match nextMatch in myMatches)
{
     GroupCollection myGroup = nextMatch.Groups;
     string type = myGroup["type"].ToString();//type變量存储multipart類型的名稱
     string flag = myGroup["flag"].ToString();//flag變量存儲multipart類型的boundary屬性
     ……
}

2.3 郵件附件的提取

  郵件中的附件信息由對應的Content-Type域、Content-Transfer-Encoding域、Content-Disposition域和multipart/mixed類型定義,前三個域定義附件的類型、名稱和編碼方式,multipart/mixed則定義附件同郵件其它內容的分段標識。基本格式如下:
--boundary分段標識
Content-Type: application/msword;
     name="readme.doc"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
     filename=" readme.doc "
……
文件內容的Base64编碼
……
--boundary分段標識
  示例代碼:提取郵件附件
//boundaryMixed代表已經提取出的multipart/mixed類型的boundary標識
//DecodeBase64為自定義的base64解碼函數
//DecodeQuotedPrintable為自定義的quoted-printable解码函數
string emailContent = “……”;//emailContent中存儲的是郵件內容
string pat = @"\r\nContent-Type:\s*(?<filetype>\S*);\s*name=""(?<name>\S*)""\s*Content-Transfer-Encoding:\s*(?<encoding>\S*)\s*Content-Disposition:\s*attachment;\s*filename=""(?<filename>\S+)""\s+(?<content>[\S|\r\n]+)" + "--" + boundaryMixed;
MatchCollection myMatches = Regex.Matches(emailContent,pat,RegexOptions.Singleline);  
foreach(Match nextMatch in myMatches)
{
     //提取附件的類型、编碼方式、文件名、內容信息
     GroupCollection myGroup = nextMatch.Groups;
     string fileType = myGroup["filetype"].ToString();
     string encoding = myGroup["encoding"].ToString();
     string fileName = myGroup["filename"].ToString();
     string content = myGroup["content"].ToString().Trim();
     byte[] attachFile;
     //根據附件的編碼方式對提取出的附件內容進行解碼
     if(encoding == “base64”)
     {
         attachFile = DecodeBase64 (content);
}
if(encoding == “quoted-printable”)
{
         attachFile = DecodeQuotedPrintable (content);
}
//將解碼後的內容寫入磁盘
     FileStream fs = new FileStream("c:\\" + fileName,
FileMode.CreateNew);
     BinaryWriter bw = new BinaryWriter(fs);
     bw.Write(attachFile);
     bw.Close();
     fs.Close();
}
  上面的程序從郵件原文中提取出附件信息,並根據附件采用的編碼類型進行解碼,然後將解碼後的內容按照原文件名存儲到C盤根目錄。同樣,如果附件的文件名是中文或者其它需要編碼的文字,則首先需要對文件名進行解碼。

3 總結

  本文對MIME郵件的基本格式做了分析和闡述,介紹了MIME中幾個重要的規范和定義,並給出了利用正則表達式从郵件內容中提取相關信息的基本思路和方法。在開發中需要註意的是,郵件中所含的內容決定了郵件的具體格式,multipart類型以及對應的分段標识只有在有相關內容的時候才會在郵件中出現,在開發時需要具體分析。MIME的詳細技術规範可以查詢RFC的相關文檔。

參考文獻

[1]   Francois Liger,C# Text Manipulation [M], Wrox Press Inc, 2002.
[2]   Internet RFC/STD/FYI/BCP Archives [EB/OL]., http://www.faqs.org/rfcs/
免費論文下載中心 http://www.hi138.com
下载论文

論文《MIME郵件格式分析及信息提取》其它版本

計算機理論論文

計算機理論論文服務

代寫計算機理論論文 計算機理論論文翻譯服務 如何寫計算機理論論文? 計算機理論英文論文計算機理論中英文對照論文 政府事業單位、機關論文 如怎樣寫好計算機理論畢業論文?
網站聲明 | 聯系我們 | 網站地圖 | 論文下載地址 | 代寫論文 | 作者搜索 | 英文版 | 手機版 CopyRight@2008 - 2017 免費論文下載中心 京ICP备17062730号