基于Lumisoft.NET组件的POP3邮件接收和删除操作
基于Lumisoft.NET组件的POP3邮件接收和删除操作
Lumisoft.NET组件是一个非常强大的邮件发送、邮件接收等功能的开源组件,一般用它来处理邮件的相关操作,是非常合适的。之前也写过一些该组件的随笔文章,不过主要是利用来发送邮件居多,最近由于项目需要,需要利用该组件来接收邮件,邮件通过POP3协议进行接收到本地,故对该组件进行了全面的了解和使用。本文主要是在此背景上,介绍该组件的POP3协议处理类的使用。Lumisoft.NET组件2013年作者有做了一定的更新,修复了一些问题,本文是基于该组件的最新版本进行开发使用。
1、POP3登录及头部信息获取
首先使用POP3,必须创建一个POP3_Client的对象,然后通过Connect和Login进行连接和登录处理,相关的代码如下所示。
using (POP3_Client popClient = new POP3_Client()) { popClient.Logger = new Logger(); popClient.Logger.WriteLog += new EventHandler<WriteLogEventArgs> (WriteLog); popClient.Connect(pop3Server, pop3Port, pop3UseSsl); popClient.Login(username, password);
POP3的的邮件下载通过 POP3_Client 对象的属性 Messages对象进行,每个POP3_ClientMessage代表一份完整的邮件信息,一开始应该是只是获取一些简单的邮件信息(其中包括邮件的唯一标识UID),这样才能提高POP3协议的处理速度,如下代码所示。
foreach (POP3_ClientMessage message in popClient.Messages)
为了进一步获取邮件头部信息,那么需要进行下面的转换
Mail_Message mime_header = Mail_Message.ParseFromByte(message.HeaderToByte());
转换后Mail_Message承载了邮件头部文件的很多必备信息,如发送人,发送人名称,接收地址,抄送人地址,邮件标题,邮件日期等等信息。
这些邮件地址的信息,都是通过Mail_t_Mailbox对象来记录,一般包含邮件地址的Address和显示名称DisplayName,这样非常方便用来显示,如我们可以进行转义,记录到数据库里面。
if (mime_header.From != null ) { // 伍华聪(wuhuacong@163测试数据) string displayname = mime_header.From[ 0 ].DisplayName; string from = mime_header.From[ 0 ].Address; // DecodeString(mime_header.From[0].Address); if (! string .IsNullOrEmpty(displayname)) { info.From = string .Format( " {0}({1}) " , displayname, from ); } else { info.From = string .Format( " {0} " , from ); } }
if (mime_header.To != null ) { StringBuilder sb = new StringBuilder(); foreach (Mail_t_Mailbox recipient in mime_header.To.Mailboxes) { string displayname = recipient.DisplayName; string address = recipient.Address; if (! string .IsNullOrEmpty(displayname)) { sb.AppendFormat( " {0}({1}); " , displayname, address); } else { sb.AppendFormat( " {0}; " , address); } } info.Senders = sb.ToString().Trim( ' ; ' ); } if (mime_header.Cc != null ) { StringBuilder sb = new StringBuilder(); foreach (Mail_t_Mailbox recipient in mime_header.Cc.Mailboxes) { string displayname = recipient.DisplayName; string address = recipient.Address; if (! string .IsNullOrEmpty(displayname)) { sb.AppendFormat( " {0}({1}); " , displayname, address); } else { sb.AppendFormat( " {0}; " , address); } } info.Carboncopy = sb.ToString().Trim( ' ; ' ); }
每封Email会有一个在Pop3服务器范围内唯一的Id,检查这个Id是否存在就可以知道以前有没有接收过这封邮件
info.MailUid = message.UID;
每份邮件的头部信息,都会包含一个日期的,如下可以获取到该日期
info.Date = mime_header.Date;
标题信息可以通过下面代码获取
info.Title = mime_header.Subject;/
2、邮件正文信息和附件信息的获取
如果需要进一步获取邮件的正文内容,则需要对信息进行进一步的转换,把message对象进行MessageToByte操作,然后利用函数Mail_Message.ParseFromByte进行转换。
byte [] messageBytes = message.MessageToByte(); Mail_Message mime_message = Mail_Message.ParseFromByte(messageBytes); if (mime_message == null ) continue ;
info.Body = mime_message.BodyText; try { if (! string .IsNullOrEmpty(mime_message.BodyHtmlText)) { info.Body = mime_message.BodyHtmlText; } } catch { // 屏蔽编码出现错误的问题,错误在BodyText存在而BodyHtmlText不存在的时候,访问BodyHtmlText会出现 }
邮件的附件是通过MIME_Entity来承载信息的,所以我们需要把对象通过mime_message.GetAttachments(true, true)进行获取,转换为附件信息。
#region 邮件附件内容 foreach (MIME_Entity entity in mime_message.GetAttachments( true , true )) { if (entity.ContentDisposition != null && entity.ContentDisposition.Param_FileName != null ) { // Console.WriteLine("Attachment: " + entity.ContentDisposition.Param_FileName); string fileName = entity.ContentDisposition.Param_FileName;
如果需要进一步获取附件里面的文件字节流,那么还需要进行进一步的转换为MIME_b_SinglepartBase对象。
MIME_b_SinglepartBase byteObj = (MIME_b_SinglepartBase)entity.Body; if (byteObj != null ) { FileUtil.CreateFile(filePath, byteObj.Data); fileSize = byteObj.Data.Length;
如果要区分邮件里面的附件是内嵌图片附件还是真正的附件,那么可以通过下面代码进行判断,如果是MIME_DispositionTypes.Attachment的就是普通附件,MIME_DispositionTypes.Inline的就是内嵌正文的附件。
entity.ContentDisposition.DispositionType == MIME_DispositionTypes.Attachment
3、邮件的删除操作
服务器上的邮件,可以通过POP3的协议方式进行删除,删除操作很简单,主要是通过mail.MarkForDeletion进行标识即可,实例操作代码如下所示
using (POP3_Client c = new POP3_Client()) { c.Connect(pop3Server, pop3Port, pop3UseSsl); c.Login(username, password); if (c.Messages.Count > 0 ) { foreach (POP3_ClientMessage mail in c.Messages) { try { if (toDeleteMailUidList.Contains(mail.UID)) { mail.MarkForDeletion(); deletedList.Add(mail.UID); } } catch (Exception ex) { LogTextHelper.Error(ex); } } } }
主要研究技术:代码生成工具、Visio二次开发、送水管理软件等共享软件开发
专注于 Winform开发框架 、WCF开发框架的研究及应用。
转载请注明出处:
撰写人:伍华聪 http://HdhCmsTestiqidi测试数据
标签: 开发辅助
基于Lumisoft.NET组件和.NET API实现邮件发送功能的对比
我在较早时期的一篇文章《 基于Lumisoft.NET实现的邮件发送功能 》有大致对这个Lumisoft.NET组件的使用进行了介绍,在《 DevExpress控件使用之RichEditControl的使用 》则对使用.NET API进行邮件发送进行了说明,其实,实现邮件发送,这两种方式是比较常见的,当然Lumisoft.NET组件除了提供邮件发送功能外,还提供了邮件接收等功能的处理(包括基于POP3协议和IMAP协议),而.NET则除了提供SMTP协议功能外,则没有提供POP3协议处理的相关类库,因此收取邮件这需要自己进行封装(需要也可以参考codeproject测试数据上的相关文章)。
1、.NET的邮件发送功能实现
.NET本身封装了一个SmtpClient类以及相关的邮件对象类,这样利用这些类库,也可以方便实现邮件的发送功能的了。
如添加发送人地址,抄送地址,以及暗送地址(多个地址用逗号分开)代码如下。
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); }
.NET的附件和嵌入式资源由对象Attachment和LinkedResource进行管理,他们的利用代码如下所示:
// 附件 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; }
上面利用.net的SmtpClient发送邮件操作的完整代码如下:
/// <summary> /// 发送外部邮件(系统配置,系统邮件) /// </summary> /// <param name="mailInfo"> 发送邮件信息 </param> /// <returns></returns> public CommonResult Send(MailInfo mailInfo) { CommonResult result = new CommonResult(); try { AppConfig config = new AppConfig(); string MailDomain = config.AppConfigGet( " MailDomain " ); string MailUsername = config.AppConfigGet( " MailUsername " ); string MailPassword = config.AppConfigGet( " MailPassword " ); string MailPort = config.AppConfigGet( " MailPort " ); string MailFrom = config.AppConfigGet( " MailFrom " ); int port = 25 ; int .TryParse(MailPort, out port); 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; }
2、基于Lumisoft.NET组件的邮件发送功能实现
基于Lumisoft.NET组件的邮件发送,也是一种很常用的,因为这个开源组件非常强大,经常可以在一些程序中被使用。
这个发送邮件的功能主要是利用SMTP_Client类来实现的,如下代码所示。注意其中的Authenticate函数已经被舍弃,可以使用Auth方法进行验证。但是函数参数有所不同,根据验证对象,使用不同的验证方式,一般选择AUTH_SASL_Client_Plain对象即可。
public bool Send() { bool sended = false ; using (SMTP_Client client = new SMTP_Client()) { 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 ); foreach ( string address in toList.Keys) { client.RcptTo(address); } // 采用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; }
构造用于SMTP发送的数据,可以使用Mail_Message 对象,也可以使用Mime对象,虽然读都可以实现发送功能,不过Mime对象是舍弃的对象了。
构造Mail_Message对象后,创建用于发送的格式要转换为Stream对象。转换为发送的Stream操作如下所示。
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 ; }
构造Mail_Message格式的邮件操作如下所示。
private Mail_Message Create_PlainText_Html_Attachment_Image(Dictionary< string , string > tomails, Dictionary< string , string > ccmails, string mailFrom, string mailFromDisplay, string subject, string body, Dictionary< string , string > attachments, string notifyEmail = "" , string plaintTextTips = "" ) { Mail_Message msg = new Mail_Message(); msg.MimeVersion = " 1.0 " ; msg.MessageID = MIME_Utils.CreateMessageID(); msg.Date = DateTime.Now; msg.Subject = subject; msg.From = new Mail_t_MailboxList(); msg.From.Add( new Mail_t_Mailbox(mailFromDisplay, mailFrom)); msg.To = new Mail_t_AddressList(); foreach ( string address in tomails.Keys) { string displayName = tomails[address]; msg.To.Add( new Mail_t_Mailbox(displayName, address)); } msg.Cc = new Mail_t_AddressList(); foreach ( string address in ccmails.Keys) { string displayName = ccmails[address]; msg.Cc.Add( new Mail_t_Mailbox(displayName, address)); } // 设置回执通知 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; }
而构造Mime格式的操作如下所示。
private Mime Create_Html_Attachment_Image( string mailTo, string mailFrom, string mailFromDisplay, string subject, string body, List< string > attachments, Dictionary< string , string > embedImages, string notifyEmail = "" , string plaintTextTips = "" , string replyEmail = "" ) { Mime m = new Mime(); MimeEntity mainEntity = m.MainEntity; 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文件的相关操作如下所示。
private void btnCreateFile_Click( object sender, EventArgs e) { string attachFile = Path.Combine(Application.StartupPath, " Attachment/Hotel2.png " ); List < string > attachments = new List< string > (); attachments.Add(attachFile); string subject = " 测试邮件 " ; string body = " <html>这是一份测试邮件,来自<font color=red><b>LumiSoft.Net</b></font></html> " ; string bodyEmbedy = " <html>这是一份测试邮件<img src=\"cid:test.jpg\">,来自<font color=red><b>LumiSoft.Net</b></font></html> " ; Dictionary < string , string > embedList = new Dictionary< string , string > (); embedList.Add( " test.jpg " , " C:\\test.jpg " ); // 存储为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 " ); }
发送EML文件操作如下所示。
private void btnSendFile_Click( object sender, EventArgs e) { using (SMTP_Client client = new SMTP_Client()) { int smtpPort = smtpUseSsl ? WellKnownPorts.SMTP_SSL : WellKnownPorts.SMTP; 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 " ); }
主要研究技术:代码生成工具、Visio二次开发、送水管理软件等共享软件开发
专注于 Winform开发框架 、WCF开发框架的研究及应用。
转载请注明出处:
撰写人:伍华聪 http://HdhCmsTestiqidi测试数据
标签: 开发辅助
基于Lumisoft.NET组件开发碰到乱码等一些问题的解决
在Lumisoft.NET组件获取POP3邮件的时候,发现大多数邮件都能正常获取,不过对于一些特殊的邮件,好像总是会出现转换错误,或者出现乱码及部分乱码现象,有些在标题里面或者邮件接收人地址,而有些则在内容里面,为了更好整理相关的问题,写了本文,希望对大家使用该组件有一定的帮助作用。
1、 日期转换出错问题。
错误信息: [2013-05-04 10:49:03] 转换邮件的Date出错:账号wuhuacong@163测试数据 邮件标题:ICP???????????????????????wuhuacong)
LumiSoft.Net.ParseException: Header field 'Date' parsing failed.
在 LumiSoft.Net.Mail.Mail_Message.get_Date()
错误原因: 由于邮件格式的日期内容格式不同,导致无法正常解析。如一般的格式为下面
Message-ID: <d74841c5887b4df692ebdb7ec7802054@4782e72954a24cc89535840ea2e5da5b> Date: Fri, 26 Apr 2013 08 : 56 : 52 GMT Mime -Version: 1.0 From: " wuhuacong2013@163测试数据 " <wuhuacong2013@ 163 测试数据> To: " wuhuacong@96900测试数据.cn " <wuhuacong@ 96900 测试数据.cn>
有些邮件日期格式是2013-05-06 19:01:44,则Lumisoft组件无法解析,需要跟踪到他的邮件日期处理的代码,然后进行修改才可以实现正常的邮件日期解析了。
官方的代码如下所示。
public DateTime Date { get { if ( this .IsDisposed){ throw new ObjectDisposedException( this .GetType().Name); } MIME_h h = this .Header.GetFirst( " Date " ); if (h != null ){ try { return MIME_Utils.ParseRfc2822DateTime(((MIME_h_Unstructured)h).Value); } catch { throw new ParseException( " Header field 'Date' parsing failed. " ); } } else { return DateTime.MinValue; } } set { if ( this .IsDisposed){ throw new ObjectDisposedException( this .GetType().Name); } if (value == DateTime.MinValue){ this .Header.RemoveAll( " Date " ); } else { MIME_h h = this .Header.GetFirst( " Date " ); if (h == null ){ this .Header.Add( new MIME_h_Unstructured( " Date " ,MIME_Utils.DateTimeToRfc2822(value))); } else { this .Header.ReplaceFirst( new MIME_h_Unstructured( " Date " ,MIME_Utils.DateTimeToRfc2822(value))); } } } }
需要增加对普通日期格式的修改,修改后的代码如下所示
public DateTime Date { get { if ( this .IsDisposed){ throw new ObjectDisposedException( this .GetType().Name); } MIME_h h = this .Header.GetFirst( " Date " ); if (h != null ){ try { return MIME_Utils.ParseRfc2822DateTime(((MIME_h_Unstructured)h).Value); } catch { // 尝试转换正常的日期 DateTime dt; string dateString = ((MIME_h_Unstructured)h).Value; bool success = DateTime.TryParse(dateString, out dt); if (success) { return dt; } else { throw new ParseException( " Header field 'Date' parsing failed. " ); } } } else { return DateTime.MinValue; } } set { if ( this .IsDisposed){ throw new ObjectDisposedException( this .GetType().Name); } if (value == DateTime.MinValue){ this .Header.RemoveAll( " Date " ); } else { MIME_h h = this .Header.GetFirst( " Date " ); if (h == null ){ this .Header.Add( new MIME_h_Unstructured( " Date " ,MIME_Utils.DateTimeToRfc2822(value))); } else { this .Header.ReplaceFirst( new MIME_h_Unstructured( " Date " ,MIME_Utils.DateTimeToRfc2822(value))); } } } }
2、由于意外的数据包格式,握手失败
错误信息 :[2013-05-04 10:13:54] System.IO.IOException: 由于意外的数据包格式,握手失败。
在 LumiSoft.Net.TCP.TCP_Client.Connect(String host, Int32 port, Boolean ssl)
错误原因 :由于POP3的配置端口不正确导致,一般的端口必须严格按照正常的来填写。
邮件SMTP 和POP3 常用配置说明:
邮箱
Smtp服务器
Smtp端口
POP3服务器
POP3端口
使用SSL
Gmail测试数据
smtp.gmail测试数据
pop.gmail测试数据
true
QQ测试数据
smtp.qq测试数据
pop.qq测试数据
true
163测试数据
smtp.163测试数据
pop.163测试数据
false
Sina测试数据
smtp.sina测试数据
pop.sina测试数据
false
其他
smtp.test测试数据
pop.test测试数据
false
3、邮件标题乱码问题
错误信息 : 标题出现类似 =?utf-8?B?5rWL6K+V6YKu5Lu2?=
错误原因 :这个是因为编码的问题,其中=?utf-8?B是表示该段字符为UTF-8的格式,后面的是base64格式的内容。除了utf-8,还可以出现gb2312或者ibm-euccn等格式。为了转换上面的编码问题,我写了一个转码函数,如下所示。
private string DecodeString( string input) { string regex = @" =\?(?<encode>.*?)\?B\?(?<body>.*?)\?= " ; Regex re = new Regex(regex, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline); MatchCollection mcs = re.Matches(input); foreach (Match mc in mcs) { string encode = mc.Groups[ " encode " ].Value; if (! string .IsNullOrEmpty(encode)) { if (encode.ToLower().Contains( " euccn " ) || encode.ToLower().Contains( " euc-cn " ) || encode.ToLower().Contains( " gbk " )) { encode = " gb2312 " ; } else if (encode.ToLower().Contains( " utf8 " )) { encode = " utf-8 " ; } string body = mc.Groups[ " body " ].Value; byte [] bytes = Convert.FromBase64String(body); string result = Encoding.GetEncoding(encode).GetString(bytes); input = input.Replace(mc.Value, result); } } return input; }
如可以通过代码吧标题进行转码解析
info.Title = DecodeString(mime_header.Subject);
转码后,标题和相关的内容都可以正常显示了。
除了上面的转码操作,还有一种更好的方法,能够使得邮件相关信息正常显示。
因为通过分析了解到,由于Lumisoft的Mail_Message.ParseFromByte函数默认只是以UTF8转换字节,一旦字节为GB2312格式,就会发生转换乱码问题,因此先经过Default编码转换,然后再以UTF8获取字节,即可正常转换邮件头部。
byte [] utf8Bytes = Encoding.UTF8.GetBytes(message.HeaderToString()); Mail_Message mime_header = Mail_Message.ParseFromByte(utf8Bytes);
这样获取到的标题,以及邮件头部等信息,都是正常的了。
主要研究技术:代码生成工具、Visio二次开发、送水管理软件等共享软件开发
专注于 Winform开发框架 、WCF开发框架的研究及应用。
转载请注明出处:
撰写人:伍华聪 http://HdhCmsTestiqidi测试数据
标签: 开发辅助
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于基于Lumisoft.NET组件的POP3邮件接收和删除操作的详细内容...