SmtpClient的文檔現(xiàn)已改成:“廢棄(“SmtpClient及其相關(guān)類型設(shè)計很差,我們強烈建議使用https://github.com/jstedfast/MailKit和https://github.com/jstedfast/MimeKit替代。”)”。這是Microsoft有史以來第二次將一個.NET類正式標(biāo)為被開源軟件庫替代。
MailKit和MimeKit的創(chuàng)建者是Jeffrey Stedfast,InfoQ曾在2014年采訪過他。在當(dāng)時,它們已被認為是.NET上最全面的MIME和電子郵件庫。
Newtonsoft的JSON.NET是被Microsoft接受的首個重要開源庫。JSON.NET已在ASP.NET Web API中廣泛使用,并被正式推薦為Web API使用的序列化類,通??商娲鶭avaScriptSerializer類。但是不同于SmtpClient的是,沒有任何一個序列化類因此被標(biāo)記為廢棄。
SmtpClient的主要問題在于連接生命周期管理混亂。由于連接SMTP服務(wù)器是一個非常耗時的操作,尤其是需要做認證時,因此每個SmtpClient對象都維護了一個內(nèi)部連接池。
這是一個非常奇葩的設(shè)計。以典型的數(shù)據(jù)庫連接為例,當(dāng)在SqlClient命名空間中調(diào)用Dispose方法時,底層的連接會返回到連接池中。當(dāng)新建一個SqlClient時,需要檢查連接池中是否已具有連接串相同的活躍連接。
使用SmtpClient時,調(diào)用Dispose方法會關(guān)閉所有連接并清空對象的連接池。這意味著不能通過常規(guī)的“using”語句調(diào)用該方法。
你可能會想到,“那么我可以持續(xù)維護一個類似于HttpClient的共享實例”。但這也行不通。因為不同于在HttpClient中,Send和SendAsync方法并非是線程安全的。除非你引入了自定義的同步模式,否則不能以這種方式使用SmtpClient。事實上,SmtpClient的文檔中已給出了警告:
SmtpClient無法判定一個應(yīng)用何時能完成,何時應(yīng)被清除。
相比之下,MailKit的SMTP客戶端表示的是一個到單個服務(wù)器的簡單連接。它消除了由內(nèi)部連接池所導(dǎo)致的復(fù)雜性。如果使用MailKit連接對象只需創(chuàng)建應(yīng)用特定的連接池,這的確簡化了操作。
雖然活躍的MailKit軟件缺陷數(shù)非常少,但在對異步操作的真正支持上,它的確還存在著問題。要對已有軟件庫中添加異步操作,一般方法是拷貝全部方法并稍作修改以支持異步操作。在一些簡單的應(yīng)用中,這并非難事。但是對于郵件客戶端這樣的復(fù)雜應(yīng)用,這會導(dǎo)致一場噩夢。當(dāng)前MailKit只是簡單地調(diào)用了同步代碼路徑和阻塞線程,模擬了對異步操作的支持。
解決異步問題的方案現(xiàn)在仍未確定,一個正在考慮的方案是使用AsyncRewriter工具。它是一個基于Roslyn的工具,已被PostgreSQL團隊用于將其同步代碼轉(zhuǎn)換為等價的異步代碼。
查看英文原文: MailKit Officially Replaces .NET’s SmtpClient