邮件发送需考虑很多因素,包括发送邮件客户端(一般编码实现),发送和接收邮件服务器设置等。如果使用第三方邮件服务器作为发送服务器,就需要考虑该服务器的发送限制,(如发送邮件时间间隔,单位时间内发送邮件数量,是否使用安全连接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
新闻热点
疑难解答