郵件發送需考慮很多因素,包括發送郵件客戶端(一般編碼實現),發送和接收郵件服務器設置等。如果使用第三方郵件服務器作為發送服務器,就需要考慮該服務器的發送限制,(如發送郵件時間間隔,單位時間內發送郵件數量,是否使用安全連接SSL),同時無論使用第三方還是自己的郵件服務器都還需要考慮接收郵件服務器的限制。為理清思路,下面我們簡單回顧電子郵件系統的基本網絡結構和郵件發送接收流程。
一、電子郵件系統的基本網絡結構
如下圖:

郵件發送接收一般經過以下幾個節點:
發送過程中客戶端與服務器及服務器之間使用SMTP協議,在接收過程中客戶端與服務端之間使用POP3或IMAP(POP3的替代協議,支持郵件摘要顯示和脫機操作)。郵件發送可簡單認為是一種文件傳輸,但與FTP實時文件傳輸不同,各郵件服務器會保存郵件文件本身,直至被下一個郵件服務器或客戶端接收,類似異步與同步的差別。
由上可知,為順利發送和接受郵件,客戶端設置或編碼需要嚴格適應郵件服務器的要求。對于發送郵件需明確:SMTP服務器地址和端口(默認端口25),是否使用安全連接(SSL),驗證憑據(用戶和密碼),及更加細節的郵件格式,郵件編碼方式等;對于接收郵件需明確:POP3或IMAP服務器地址和端口(POP3默認端口110,IMAP默認端口143),是否使用安全連接(SSL),驗證憑據(用戶和密碼)
二、C#下發送郵件組件及測試
C#下發送郵件的組件使用較為普遍的有以下三個:System.Net.Mail, OpenSmtp, LumiSoft.Net。下面我們就分別對他們進行測試。
發送郵件至少需要發送郵件服務器信息和郵件信息,因此我們建立Host和Mail兩個配置類。
public class ConfiGhost { public string Server { get; set; } public int Port { get; set; } public string Username { get; set; } public string PassWord { get; set; } public bool EnableSsl { get; set; } } public class ConfiGmail { public string From { get; set; } public string[] To { get; set; } public string Subject { get; set; } public string Body { get; set; } public string[] Attachments { get; set; } public string[] Resources { get; set; } }
同時定義一個統一的接口ISendMail,以方便測試和比較。
public interface ISendMail { void CreateHost(ConfigHost host); void CreateMail(ConfigMail mail); void CreateMultiMail(ConfigMail mail); void SendMail(); }
1、使用System.Net.Mail
System.Net.Mail屬于.Net Framework 的一部分,.Net2.0以后可以使用這個組件。
using System.Net.Mail; public class UseNetMail : ISendMail { PRivate MailMessage Mail { get; set; } private SmtpClient Host { get; set; } public void CreateHost(ConfigHost host) { Host = new SmtpClient(host.Server, host.Port); Host.Credentials = new System.Net.NetworkCredential(host.Username, host.Password); Host.EnableSsl = host.EnableSsl; } public void CreateMail(ConfigMail mail) { Mail = new MailMessage(); Mail.From = new MailAddress(mail.From); foreach (var t in mail.To) Mail.To.Add(t); Mail.Subject = mail.Subject; Mail.Body = mail.Body; Mail.IsBodyHtml = true; Mail.BodyEncoding = System.Text.Encoding.UTF8; } public void CreateMultiMail(ConfigMail mail) { CreateMail(mail); Mail.AlternateViews.Add(AlternateView.CreateAlternateViewFromString("If you see this message, it means that your mail client does not support html.", Encoding.UTF8, "text/plain")); var html = AlternateView.CreateAlternateViewFromString(mail.Body, Encoding.UTF8, "text/html"); foreach (string resource in mail.Resources) { var image = new LinkedResource(resource, "image/jpeg"); image.ContentId = Convert.ToBase64String(Encoding.Default.GetBytes(Path.GetFileName(resource))); html.LinkedResources.Add(image); } Mail.AlternateViews.Add(html); foreach (var attachment in mail.Attachments) { Mail.Attachments.Add(new Attachment(attachment)); } } public void SendMail() { if (Host != null && Mail != null) Host.Send(Mail); else throw new Exception("These is not a host to send mail or there is not a mail need to be sent."); } }2、使用OpenSmtp開源的發送郵件組件,可以在這里獲得源碼。但是OpenSmtp目前不支持SSL。 using OpenSmtp.Mail; public class USEOpenSmtp : ISendMail { private MailMessage Mail { get; set; } private Smtp Host { get; set; } public void CreateHost(ConfigHost host) { Host = new Smtp(host.Server, host.Username, host.Password, host.Port); } public void CreateMail(ConfigMail mail) { Mail = new MailMessage(); Mail.From = new EmailAddress(mail.From); foreach (var t in mail.To) Mail.AddRecipient(t, AddressType.To); Mail.HtmlBody = mail.Body; Mail.Subject = mail.Subject; Mail.Charset = "UTF-8"; } public void CreateMultiMail(ConfigMail mail) { CreateMail(mail); foreach (var attachment in mail.Attachments) { Mail.AddAttachment(attachment); } foreach (var resource in mail.Resources) { Mail.AddImage(resource, Convert.ToBase64String(Encoding.Default.GetBytes(Path.GetFileName(resource)))); } } public void SendMail() { if (Host != null && Mail != null) Host.SendMail(Mail); else throw new Exception("These is not a host to send mail or there is not a mail need to be sent."); }
3、使用LumiSoft.Net
LumiSoft.Net是非常強大的開源組件,不僅僅發送郵件,同樣也可用于接收郵件,是個人認為最好的開源組件了。在這里可以詳細了解LumiSoft.Net組件的命名空間,也可以在這里下載其源碼和樣例。
using LumiSoft.Net.SMTP.Client; using LumiSoft.Net.AUTH; using LumiSoft.Net.Mail; using LumiSoft.Net.MIME; public class UseLumiSoft : ISendMail { private SMTP_Client Host { get; set; } private Mail_Message Mail { get; set; } public void CreateHost(ConfigHost host) { Host = new SMTP_Client(); Host.Connect(host.Server, host.Port, host.EnableSsl); Host.EhloHelo(host.Server); Host.Auth(Host.AuthGetStrongestMethod(host.Username, host.Password)); } public void CreateMail(ConfigMail mail) { Mail = new Mail_Message(); Mail.Subject = mail.Subject; Mail.From = new Mail_t_MailboxList(); Mail.From.Add(new Mail_t_Mailbox(mail.From, mail.From)); Mail.To = new Mail_t_AddressList(); foreach (var to in mail.To) { Mail.To.Add(new Mail_t_Mailbox(to, to)); } var body = new MIME_b_Text(MIME_MediaTypes.Text.html); Mail.Body = body; //Need to be assigned first or will throw "Body must be bounded to some entity first" exception. body.SetText(MIME_TransferEncodings.Base64, Encoding.UTF8, mail.Body); } public void CreateMultiMail(ConfigMail mail) { CreateMail(mail); var contentTypeMixed = new MIME_h_ContentType(MIME_MediaTypes.Multipart.mixed); contentTypeMixed.Param_Boundary = Guid.NewGuid().ToString().Replace("-", "_"); var multipartMixed = new MIME_b_MultipartMixed(contentTypeMixed); Mail.Body = multipartMixed; //Create a entity to hold multipart/alternative body var entityAlternative = new MIME_Entity(); var contentTypeAlternative = new MIME_h_ContentType(MIME_MediaTypes.Multipart.alternative); contentTypeAlternative.Param_Boun
新聞熱點
疑難解答