基于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邮件接收和删除操作的详细内容...