標籤:積极參与 程式 武漢話 簡訊 生態
發起的.NET Core開源組織號召,進展的速度是我自己也沒有想到的,很多園友都積极參与(雖然有些人誠心砸場子,要是以我以前的寶脾氣,這會應該被我打住院了吧,不過幸好是少數,做一件事總有人說好,也有人說是用武漢話說“鬧眼子”),.NET社區不是沒有樂於共用知識的人,只是沒有一個完整和良好的生態環境,總之希望國內的.NET發展越來越強大。我在這裡想到一句話“我們希望自己可以做巨浪,但我們也甘願做巨浪來襲前的小浪”。
上面扯淡完畢(我這人幹正事前,都要將一些扯淡的話,這個習慣改不掉了...)
項目中為了及時的通訊,有直接發資料到頁面,也有利用簡訊通知,也有我門今天介紹的郵件組件。我們今天的主要任務就是講解一下有一個.NET的免費開源的郵件組件MailKit。本文將一如既往的結合執行個體和組件底層代碼講解一下相關組件的知識。(項目招人的時候,我都會問一下.NET的底層原理,有一個大神問我這樣有什麼意義嗎?我們也寫不出.NET底層那樣的優秀處理方式,為何取瞭解這些,其實我個人覺得,問底層的原理,只是向為了跟好的處理一些程式出現的問題,以及對程式編碼的時候,選擇最合適的方式提升效能,任何一種方式都有優勢和劣勢,.NET的類庫代碼也是如此,如果我們知道.NET的底層實現,我們在項目的需求實現時,可以根據.NET底層實現,選擇合適的方式,以求效能最優)。
一.Mailkit組件概述
項目中使用Email的操作機會比較多,一般稍微大一點的項目,都會使用到郵件操作這一個操作。對於.NET郵件操作的組件和方式比較多,今天我們就介紹一款郵件操作的組件MailKit,這個郵件組件是一個開源免費的,我們現在就來瞭解一下這一個組件的特點。MimeKit旨在通過儘可能接近地遵循MIME規範來解決這個問題,同時還為程式員提供了一個非常容易使用的進階API。
組件的支援的用戶端類型比較多,例如SMTP用戶端、POP3用戶端、IMAP用戶端。該組件是一個跨平台的Email組件,該組件支援.NET 4.0,.NET 4.5,Xamarin.Android,Xamarin.iOS,Windows Phone 8.1等等平台。該組件提供了一個MIME解析器,組件具備的解析特性靈活、效能高、很好的處理各種各樣的破碎的MIME格式化。MimeKit的效能實際上與GMime相當。
該組件在安全性的還是比較高的,處理安全的方式較多,SASL認證、支援S / MIME v3.2、支援OpenPGP、支援DKIM簽名等等方式。Mailkit組件可以通過CancellationToken取消對應的操作,CancellationToken傳播應取消操作的通知,一個的CancellationToken使線程,線程池工作項目之間,或取消合作任務的對象。過執行個體化CancellationTokenSource對象來建立取消令牌,該對象管理從其CancellationTokenSource.Token屬性檢索的取消令牌。然後,將取消令牌傳遞到應該收到取消通知的任意數量的線程,任務或操作。令牌不能用於啟動取消。
MailKit組件支援非同步作業,在內部編寫的有關I/O非同步作業的類。
二.MailKit執行個體:
上面介紹了MailKit組件的背景和特點,這裡就介紹一下Email組件的簡單應用。
1.建立郵件方式:
public void SentEmail(string path) { var message = new MimeMessage(); //擷取From標題中的地址清單,添加指定的地址 message.From.Add(new MailboxAddress("Joey", "[email protected]")); //擷取To頭中的地址清單,添加指定的地址 message.To.Add(new MailboxAddress("Alice", "[email protected]")); //擷取或設定訊息的主題 message.Subject = "How you doin?"; // 建立我們的訊息文本,就像以前一樣(除了不設定為message.Body) var body = new TextPart("plain") { Text = @"Hey Alice-- Joey" }; // 為位於路徑的檔案建立映像附件 var attachment = new MimePart("image", "gif") { ContentObject = new ContentObject(File.OpenRead(path), ContentEncoding.Default), ContentDisposition = new ContentDisposition(ContentDisposition.Attachment), ContentTransferEncoding = ContentEncoding.Base64, FileName = Path.GetFileName(path) }; // 現在建立multipart / mixed容器來儲存訊息文本和映像附件 var multipart = new Multipart("mixed") { body, attachment }; // 現在將multipart / mixed設定為訊息本文 message.Body = multipart; }
調用該組件發送郵件和為郵件添加附件是比較簡單的,第一步是執行個體化MimeMessage對象,對於該對象的解析將在下面進行,得到MimeMessage對象後,指定郵件的地址和主題等等相關資訊。第二步執行個體化TextPart對象,為對象設定文本資訊。若需要問郵件建立檔案的附件,可以使用MimePart對象,包含內容(如訊息本文或)的分葉節點MIME部分一個附件。第四步為建立的郵件主體和文本以及附件資訊後,可以建立Multipart對象,建立郵件容器,用來裝載文本資訊和附件。最後調用MimeMessage.body屬性擷取或設定訊息的本文。
2.郵件資訊的解析:
var message = MimeMessage.Load(stream);
郵件的資訊我們需要進行對應的解析,這裡我們使用MimeMessage的Load方法,該方法從指定的流載入MimeKit.MimeMessage。另一個載入資料的方式,可以使用MimeParser類,這裡就不再解析了。
3.郵件的接收:
public static void HandleMimeEntity(MimeEntity entity) { //MimeEntity轉化為Multipart實體 var multipart = entity as Multipart; if (multipart != null) { for (int i = 0; i < multipart.Count; i++) HandleMimeEntity(multipart[i]); return; } var rfc822 = entity as MessagePart; if (rfc822 != null) { var message = rfc822.Message; HandleMimeEntity(message.Body); return; } var part = (MimePart)entity; }
以上是對接收到的訊息的一個遍曆,採用遞迴遍曆MIME結構。MIME是內容的樹結構,很像一個檔案系統。MIME確實定義了一組通用規則,用於郵件用戶端如何解釋MIME部分的樹結構。的 內容處置頭是為了給接收用戶端提供提示以哪些部分是為了顯示作為訊息體的一部分,並且意在被解釋為附件。另外兩種方式這離就不做介紹了。
三.MailKit核心對象解析
上面介紹了Email的基本操作就不做過多的介紹,在使用該組件時,較為的簡單。這裡就來看看該組件的類型結構和一些核心對象。類庫結構有如:
650) this.width=650;" src="http://images2015.cnblogs.com/blog/831875/201703/831875-20170317002859135-1588383177.png" style="margin:0px;padding:0px;border:0px;" />
1.MimeMessage.Load():
MimeMessage Load (ParserOptions options, Stream stream, persistent, CancellationToken cancellationToken = (options == (stream == parser =
該方法從指定的流載入MimeMessage,具有6個方法重載。該方法返回一個MimeMessage對象,有源碼可以看出,在該方法內部建立了一個MimeParser對象,MimeParser包含內容(例如郵件內文文本或附件)的分葉節點MIME部分。調用ParseMessage方法,解析來自流的訊息。
2.TextPart.Text:
public string Text { get { if (ContentObject == null) return string.Empty; var charset = ContentType.Parameters["charset"]; using (var memory = new MemoryStream ()) { ContentObject.DecodeTo (memory); var content = memory.ToArray (); Encoding encoding = null; if (charset != null) { try { encoding = CharsetUtils.GetEncoding (charset); } catch (NotSupportedException) { } } if (encoding == null) { try { return CharsetUtils.UTF8.GetString (content, 0, (int) memory.Length); } catch (DecoderFallbackException) { encoding = CharsetUtils.Latin1; } } return encoding.GetString (content, 0, (int) memory.Length); } } set { SetText (Encoding.UTF8, value); } }
該屬性擷取解碼的常值內容。該屬性是一個可讀可寫的屬性。ContentType.Parameters["charset"]用於擷取charset參數的值。該方法用來將參數的值設定為資料流並設定對應的編碼。看到這裡的異常處理結構,就想簡單的談幾句,.NET的異常比較的薄弱,很多時候在寫.NET的異常時就更加的簡單,以上是對異常知識捕獲,有些地方並沒有做處理,有些地方是對異常的地方進行恢複。
3.MimeEntity.WriteTo():
WriteTo (FormatOptions options, Stream stream, contentOnly, CancellationToken cancellationToken = (options == (stream == (!
該方法將MimeEntity寫入到指定的資料流中,該方法接受參數options格式選項。stream輸出資料流,contentOnly判斷是否可寫。該方法定義為虛方法,在繼承此方法後,可以在子類種對該方法進行重寫。
四.總結
本人覺得在項目開發中,如果引入了第三方組件,我們盡量引入組件的源碼,這樣我們對整個組件的結構有一個認識,組件的實現方式我們也可以進行細緻瞭解,尤其是我們在進行調試的事後更加有用,我們可以逐一的進行斷點調試。以上是對該組件的一個簡單介紹,有興趣的可以去深入的瞭解和學習。
跨平台的.NET郵件協議MailKit組件解析