我在另一篇文章《深入Lumisoft.NET实现邮件发送功能的方法详解》有大致对这个Lumisoft.NET组件的使用进行了介绍,当然Lumisoft.NET组件除了提供邮件发送功能外,还提供了邮件接收等功能的处理(包括基于POP3协议和IMAP协议),而.NET则除了提供SMTP协议功能外,则没有提供POP3协议处理的相关类库,因此收取邮件这需要自己进行封装(需要也可以参考codeproject.com上的相关文章)。
1、.NET的邮件发送功能实现
.NET本身封装了一个SmtpClient类以及相关的邮件对象类,这样利用这些类库,也可以方便实现邮件的发送功能的了。
如添加发送人地址,抄送地址,以及暗送地址(多个地址用逗号分开)代码如下。
string cc = "";
mailInfo.RecipientCC.ForEach(obj => cc += string.Format("{0},", obj));
cc = cc.Trim(',');
MailMessage mail = new MailMessage(settingInfo.MailFrom, toEmails);
if (!string.IsNullOrEmpty(bcc))
{
mail.Bcc.Add(bcc);
}
if (!string.IsNullOrEmpty(cc))
{
mail.CC.Add(cc);
}
//嵌入资源
AlternateView view = AlternateView.CreateAlternateViewFromString(mailInfo.Body, Encoding.UTF8, MediaTypeNames.Text.Html);
foreach (LinkedAttachementInfo link in mailInfo.EmbedObjects)
{
LinkedResource resource = new LinkedResource(link.Stream, link.MimeType);
resource.ContentId = link.ContentId;
view.LinkedResources.Add(resource);
}
mail.AlternateViews.Add(view);
//发送账户设置信息
SmtpClient client = new SmtpClient();
client.Host = settingInfo.SmtpServer;
client.Port = settingInfo.SmptPort;
client.UseDefaultCredentials = false;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Credentials = new NetworkCredential(settingInfo.SmtpUser, settingInfo.SmtpPass);
bool success = false;
try
{
client.Send(mail);
success = true;
}
catch (Exception ex)
{
LogTextHelper.Error(ex);
//throw;
}
SmtpSettingInfo settingInfo = new SmtpSettingInfo(MailDomain, port,
MailUsername, MailPassword, MailFrom);
result.Success = PrivateSendEmail(mailInfo, settingInfo);
}
catch (Exception ex)
{
result.ErrorMessage = ex.Message;
throw;
}
return result;
}
/// <summary>
/// 通用发送邮件操作
/// </summary>
private static bool PrivateSendEmail(MailInfo mailInfo, SmtpSettingInfo settingInfo)
{
string toEmails = mailInfo.ToEmail;
string bcc = "";
mailInfo.RecipientBCC.ForEach(obj => bcc += string.Format("{0},", obj));
bcc = bcc.Trim(',');
string cc = "";
mailInfo.RecipientCC.ForEach(obj => cc += string.Format("{0},", obj));
cc = cc.Trim(',');
MailMessage mail = new MailMessage(settingInfo.MailFrom, toEmails);
if (!string.IsNullOrEmpty(bcc))
{
mail.Bcc.Add(bcc);
}
if (!string.IsNullOrEmpty(cc))
{
mail.CC.Add(cc);
}
//附件
foreach (string fileName in mailInfo.Attachments)
{
mail.Attachments.Add(new Attachment(fileName));
}
//嵌入资源
AlternateView view = AlternateView.CreateAlternateViewFromString(mailInfo.Body, Encoding.UTF8, MediaTypeNames.Text.Html);
foreach (LinkedAttachementInfo link in mailInfo.EmbedObjects)
{
LinkedResource resource = new LinkedResource(link.Stream, link.MimeType);
resource.ContentId = link.ContentId;
view.LinkedResources.Add(resource);
}
mail.AlternateViews.Add(view);
mail.IsBodyHtml = mailInfo.IsBodyHtml;
mail.BodyEncoding = Encoding.UTF8;
mail.Subject = mailInfo.Subject;
mail.SubjectEncoding = Encoding.UTF8;
//发送账户设置信息
SmtpClient client = new SmtpClient();
client.Host = settingInfo.SmtpServer;
client.Port = settingInfo.SmptPort;
client.UseDefaultCredentials = false;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Credentials = new NetworkCredential(settingInfo.SmtpUser, settingInfo.SmtpPass);
bool success = false;
try
{
client.Send(mail);
success = true;
}
catch (Exception ex)
{
LogTextHelper.Error(ex);
//throw;
}
string message = string.Format("发送给【{0}】的邮件“{1}”,{2},时间:{3}",
mailInfo.ToEmail[0], mailInfo.Subject, success ? "发送成功" : "发送失败", DateTime.Now);
LogTextHelper.Info(message);
return success;
}
这个发送邮件的功能主要是利用SMTP_Client类来实现的,如下代码所示。注意其中的Authenticate函数已经被舍弃,可以使用Auth方法进行验证。但是函数参数有所不同,根据验证对象,使用不同的验证方式,一般选择AUTH_SASL_Client_Plain对象即可。
//采用Mail_Message类型的Stream
Mail_Message m = Create_PlainText_Html_Attachment_Image(toList, ccList, from, fromDisplay, subject, body, attachments);
using (MemoryStream stream = new MemoryStream())
{
m.ToStream(stream, new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.Q, Encoding.UTF8), Encoding.UTF8);
stream.Position = 0;
client.SendMessage(stream);
sended = true;
}
if (m != null)
{
m.Dispose();
}
client.Disconnect();
}
return sended;
}
构造Mail_Message对象后,创建用于发送的格式要转换为Stream对象。转换为发送的Stream操作如下所示。
sended = true;
}
//设置回执通知
if (!string.IsNullOrEmpty(notifyEmail) && ValidateUtil.IsEmail(notifyEmail))
{
msg.DispositionNotificationTo.Add(new Mail_t_Mailbox(notifyEmail, notifyEmail));
}
#region MyRegion
//--- multipart/mixed -----------------------------------
MIME_h_ContentType contentType_multipartMixed = new MIME_h_ContentType(MIME_MediaTypes.Multipart.mixed);
contentType_multipartMixed.Param_Boundary = Guid.NewGuid().ToString().Replace('-', '.');
MIME_b_MultipartMixed multipartMixed = new MIME_b_MultipartMixed(contentType_multipartMixed);
msg.Body = multipartMixed;
//--- multipart/alternative -----------------------------
MIME_Entity entity_multipartAlternative = new MIME_Entity();
MIME_h_ContentType contentType_multipartAlternative = new MIME_h_ContentType(MIME_MediaTypes.Multipart.alternative);
contentType_multipartAlternative.Param_Boundary = Guid.NewGuid().ToString().Replace('-', '.');
MIME_b_MultipartAlternative multipartAlternative = new MIME_b_MultipartAlternative(contentType_multipartAlternative);
entity_multipartAlternative.Body = multipartAlternative;
multipartMixed.BodyParts.Add(entity_multipartAlternative);
//--- text/plain ----------------------------------------
MIME_Entity entity_text_plain = new MIME_Entity();
MIME_b_Text text_plain = new MIME_b_Text(MIME_MediaTypes.Text.plain);
entity_text_plain.Body = text_plain;
//普通文本邮件内容,如果对方的收件客户端不支持HTML,这是必需的
string plainTextBody = "如果你邮件客户端不支持HTML格式,或者你切换到“普通文本”视图,将看到此内容";
if (!string.IsNullOrEmpty(plaintTextTips))
{
plainTextBody = plaintTextTips;
}
text_plain.SetText(MIME_TransferEncodings.QuotedPrintable, Encoding.UTF8, plainTextBody);
multipartAlternative.BodyParts.Add(entity_text_plain);
//--- text/html -----------------------------------------
string htmlText = body;//"<html>这是一份测试邮件,<img src=\"cid:test.jpg\">来自<font color=red><b>LumiSoft.Net</b></font></html>";
MIME_Entity entity_text_html = new MIME_Entity();
MIME_b_Text text_html = new MIME_b_Text(MIME_MediaTypes.Text.html);
entity_text_html.Body = text_html;
text_html.SetText(MIME_TransferEncodings.QuotedPrintable, Encoding.UTF8, htmlText);
multipartAlternative.BodyParts.Add(entity_text_html);
//--- application/octet-stream -------------------------
WebClient client = new WebClient();
foreach (string attach in attachments.Keys)
{
try
{
byte[] bytes = client.DownloadData(attach);
using (MemoryStream stream = new MemoryStream(bytes))
{
multipartMixed.BodyParts.Add(Mail_Message.CreateAttachment(stream, attachments[attach]));
}
}
catch (Exception ex)
{
LogTextHelper.Error(ex);
}
}
#endregion
return msg;
}
mainEntity.From = new AddressList();
mainEntity.From.Add(new MailboxAddress(mailFromDisplay, mailFrom));
mainEntity.To = new AddressList();
mainEntity.To.Add(new MailboxAddress(mailTo, mailTo));
mainEntity.Subject = subject;
mainEntity.ContentType = MediaType_enum.Multipart_mixed;
//设置回执通知
if (!string.IsNullOrEmpty(notifyEmail) && ValidateUtil.IsEmail(notifyEmail))
{
mainEntity.DSN = notifyEmail;
}
//设置统一回复地址
if (!string.IsNullOrEmpty(replyEmail) && ValidateUtil.IsEmail(replyEmail))
{
mainEntity.ReplyTo = new AddressList();
mainEntity.ReplyTo.Add(new MailboxAddress(replyEmail, replyEmail));
}
MimeEntity textEntity = mainEntity.ChildEntities.Add();
textEntity.ContentType = MediaType_enum.Text_html;
textEntity.ContentTransferEncoding = ContentTransferEncoding_enum.QuotedPrintable;
textEntity.DataText = body;
//附件
foreach (string attach in attachments)
{
MimeEntity attachmentEntity = mainEntity.ChildEntities.Add();
attachmentEntity.ContentType = MediaType_enum.Application_octet_stream;
attachmentEntity.ContentDisposition = ContentDisposition_enum.Attachment;
attachmentEntity.ContentTransferEncoding = ContentTransferEncoding_enum.Base64;
FileInfo file = new FileInfo(attach);
attachmentEntity.ContentDisposition_FileName = file.Name;
attachmentEntity.DataFromFile(attach);
}
//嵌入图片
foreach (string key in embedImages.Keys)
{
MimeEntity attachmentEntity = mainEntity.ChildEntities.Add();
attachmentEntity.ContentType = MediaType_enum.Application_octet_stream;
attachmentEntity.ContentDisposition = ContentDisposition_enum.Inline;
attachmentEntity.ContentTransferEncoding = ContentTransferEncoding_enum.Base64;
string imageFile = embedImages[key];
FileInfo file = new FileInfo(imageFile);
attachmentEntity.ContentDisposition_FileName = file.Name;
//string displayName = Path.GetFileNameWithoutExtension(fileName);
attachmentEntity.ContentID = key;//BytesTools.BytesToHex(Encoding.Default.GetBytes(fileName));
attachmentEntity.DataFromFile(imageFile);
}
return m;
}
3、LumiSoft.NET存储eml邮件文件以及发送eml文件操作
除了上面的发送普通邮件,Lumisoft还支持吧邮件序列号存储到文件(.eml邮件文件)里面,然后也可以通过把文件读取到流里面,进行发送,对于某种场合,可以把邮件存储到eml文件是一个很好的操作。
存储EML文件的相关操作如下所示。
//存储为Eml文件
string path = Path.Combine(Application.StartupPath, "Eml");
DirectoryUtil.AssertDirExist(path);
string emlFile = string.Format("{0}/{1}.eml", path, DateTime.Now.ToFileTime());
Mime m = Create_Html_Attachment_Image(to, from, from, subject, bodyEmbedy, attachments, embedList);
m.ToFile(emlFile);
MessageUtil.ShowTips("OK");
}
client.Connect(smtpServer, smtpPort, smtpUseSsl);
client.EhloHelo(smtpServer);
//var authhh = new AUTH_SASL_Client_Plain(username, password);
//client.Auth(authhh);
client.Authenticate(username, password);
//string text = client.GreetingText;
client.MailFrom(from, -1);
client.RcptTo(to);
string path = Path.Combine(Application.StartupPath, "Eml");
string emlFile = Directory.GetFiles(path)[0];
var msg = Mail_Message.ParseFromFile(emlFile);
MemoryStream stream = new MemoryStream();
msg.ToStream(stream, new MIME_Encoding_EncodedWord(MIME_EncodedWordEncoding.Q, Encoding.UTF8), Encoding.UTF8);
stream.Position = 0;
client.SendMessage(stream);
client.Disconnect();
}
MessageUtil.ShowTips("OK");
}