在早期一直使用Lumisoft.NET组件来进行邮件的处理查找,对于邮件的处理非常方便,之前在随笔《基于Lumisoft.NET组件的POP3邮件接收和删除操作》中也介绍过基于POP3和SMPT进行邮件的收发处理,一般邮件服务器对于Pop3都是支持很好的,常规使用测试多个服务器都没问题,所以就没怎么研究IMAP协议的处理,本篇随笔基于原来POP3 的需求扩展了IMAP协议的处理。

1、创建IMAP收件辅助类

为了方便进行收取IMAP邮件的处理,我们创建一个ImapHelper,并传入相关用到的一些参数,用来封装收件的处理操作。

如下辅助类所示,传入服务器域名地址,端口,是否SSL,用户名和密码等信息。

接下来,我们需要连接服务器,并尝试获取授权信息,如果通过,则可以进行下一步获取邮件信息的操作,如下代码所示。

        /// <summary>
/// 收取邮件操作
/// </summary>
public void Receive()
{
using (var client = new IMAP_Client())
{
//创建日志处理
client.Logger = new Logger();
client.Logger.WriteLog += new EventHandler<WriteLogEventArgs>(WriteLog);//响应记录显示 //使用账号密码,连接服务器
client.Connect(server, port, useSsl);
//登录获取授权操作
client.Login(username, password);
//var identity = client.AuthenticatedUserIdentity; //获取各个邮箱目录的概要信息
client.GetFolders(null).ToList().ForEach(f =>
{ Console.WriteLine(f.FolderName);
var s = client.FolderStatus(f.FolderName);
s.ToList().ForEach(sIt =>
{
Console.WriteLine("总数:{0},未读:{1},最近{2}", sIt.MessagesCount, sIt.MessagesCount, sIt.UnseenCount);
}); });

我们登录获得授权后,测试获取各个目录的概要邮件信息,如总邮件数量,以及未读数量等等。

然后通过选择具体的邮箱目录,并设置返回信息包含的内容格式,以及从服务器返回那些序号的邮件等等,如下代码所示。

    //选择邮箱
client.SelectFolder("INBOX");
//首先确定取第x到第n封邮件,"1:*"表示第1封到最后一封
var seqSet = IMAP_t_SeqSet.Parse("1:*");
var items = new IMAP_t_Fetch_i[]
{
new IMAP_t_Fetch_i_Envelope(), //邮件的标题、正文等信息
new IMAP_t_Fetch_i_Uid(), //返回邮件的UID号,UID号是唯一标识邮件的一个号码
new IMAP_t_Fetch_i_Flags(), //此邮件的标志,应该是已读未读标志
new IMAP_t_Fetch_i_InternalDate(),//貌似是收到的日期
new IMAP_t_Fetch_i_Rfc822() //Rfc822是标准的邮件数据流,可以通过Lumisoft.Net.Mail.Mail_Message对象解析出邮件的所有信息
};

接着我们通过传入条件,并给他一个回调匿名函数处理相关的邮件信息,如下所示。

    //Fetch 第一个参数false时seqSet有效
client.Fetch(false, seqSet, items, (s, e) =>
{
//处理邮件的匿名函数内容
});

接着我们处理邮件信息的转换,吧邮件信息转换为Mail_Message对象的信息,这个包含邮件相关的头部信息,正文,以及附件信息等全部内容。

   var email = e.Value as IMAP_r_u_Fetch;
if (email.Rfc822 != null)
{
email.Rfc822.Stream.Position = 0;
var mime_message = Mail_Message.ParseFromStream(email.Rfc822.Stream);
email.Rfc822.Stream.Close();

然后我们把邮件的信息进一步转换为我们需要存储在数据库的对象信息,最后写入数据库即可。

    receiveInfo.ReceivedDate = DateTime.Now;//接收本地时间
receiveInfo.Company_ID = this.companyId;
receiveInfo.User_ID = this.userId;
receiveInfo.Email = this.email;//接收Email账号
receiveInfo.MailConfig_ID = this.mailConfig_ID;//接收Email账号的配置记录ID //每封Email会有一个在Pop3服务器范围内唯一的Id,检查这个Id是否存在就可以知道以前有没有接收过这封邮件
receiveInfo.MailUid = email.UID.UID.ToString(); try
{
//可能会出现【LumiSoft.Net.ParseException: Header field 'Date' parsing failed】异常错误。
receiveInfo.SendDate = mime_message.Date;
}
catch (Exception ex)
{
receiveInfo.SendDate = Convert.ToDateTime("1900-1-1");//错误赋值一个日期
error = string.Format("转换邮件的Date出错:账号{0} 邮件标题:{1}", username, mime_message.Subject);
LogTextHelper.Error(error, ex);
} //可能出现乱码问题,通过函数进行转换
receiveInfo.Title = mime_message.Subject;//DecodeString(mime_header.Subject); receiveInfo.MailBody = mime_message.BodyText;
try
{
if (!string.IsNullOrEmpty(mime_message.BodyHtmlText))
{
receiveInfo.MailBody = mime_message.BodyHtmlText;
}
}
catch
{
//屏蔽编码出现错误的问题,错误在BodyText存在而BodyHtmlText不存在的时候,访问BodyHtmlText会出现
}

写入数据库处理,调用我们通用处理类处理数据信息的存储即可。

    #region 写入邮件信息到数据库
int mailId = -1;
try
{
mailId = BLLFactory<MailReceive>.Instance.Insert2(receiveInfo);
}
catch (Exception ex)
{
error = string.Format("写入邮件信息到数据库出错:账号{0} 邮件标题:{1}", username, mime_message.Subject);
LogTextHelper.Error(error, ex);
} if (mailId <= 0) return; //如果邮件没有保存,不要保存附件
#endregion

2、邮件的附件处理

邮件的附件,包含常规的邮件附件,以及嵌入正文的附件图片,因此需要进行不同类型的判断,并一起把附件获取下来存储,这样在显示的时候,才能正常显示相关的附件。

其中Mail_Message 对象有一个函数,可以获取全部这两类附件的信息到列表中。

public MIME_Entity[] GetAttachments(bool includeInline, bool includeEmbbedMessage)

这样我们来调用这个函数,然后进行附件的提取存储处理即可。

    #region 邮件附件内容
foreach (var entity in mime_message.GetAttachments(true, true))
{
string fileName = ""; #region 判断是普通附件还是嵌入的内容附件
if (entity.ContentDisposition != null &&
entity.ContentDisposition.DispositionType == MIME_DispositionTypes.Attachment)
{
Console.WriteLine("Attachment: " + entity.ContentDisposition.Param_FileName);
fileName = entity.ContentDisposition.Param_FileName;
}
else
{
string cid = entity.ContentID.Substring(1, entity.ContentID.Length - 2);
if (entity.ContentType.Param_Name != null &&
mime_message.BodyHtmlText.Contains(string.Format("cid:{0}", cid)))
{
Console.WriteLine("Embeded image: " + cid);
fileName = cid;
}
else
{
Console.WriteLine("Unknown attachment.");
}
}

邮件的附件信息,entity对象需要转换为MIME_b_SinglepartBase进行处理的。

 var byteObj = entity.Body as MIME_b_SinglepartBase;

因此我们可以通过文件方式存储它的字节数据,如下所示。

File.WriteAllBytes(filename, byteObj.Data);

或者调用附件信息进行存储处理(可以是本地存储、或者FTP上传等方式)

如对于测试带有嵌入图片,附件信息的邮件,这样处理能够顺利获取所有的附件信息。

因此可以使用邮件管理模块中的定时收发邮件的处理,实现邮件的接收和发送。

3、163邮箱对于IMAP协议不支持

在测试IMAP协议收取邮件的时候,对于POP3发现大多数邮箱都是支持的。

但虽然163邮箱对POP3的支持不错,对IMAP协议却不支持,都是使用授权码进行登录,也确实登录成功了,但是IMAP协议切换邮箱进行邮件收取的时候,就会提示

提示错误信息。

00023 NO SELECT Unsafe Login. Please contact kefu@188.com for help

如有兴趣,了解Lumisoft.NET组件的相关使用内容,请参考我相关随笔,谢谢。

《 基于Lumisoft.NET组件和.NET API实现邮件发送功能的对比

基于Lumisoft.NET实现的邮件发送功能

基于Lumisoft.NET组件开发碰到乱码等一些问题的解决

基于Lumisoft.NET组件的SMTP账号登陆检测

邮件代收代发软件操作说明

邮件代收代发功能模块的操作界面设计和阶段性总结

基于Lumisoft.NET组件,使用IMAP协议收取邮件的更多相关文章

  1. 基于Lumisoft.NET组件的SMTP账号登陆检测

    在邮件处理的方面,Lumisoft.NET可以说是非常不错的一个选择,我在前面几篇文章中都介绍过这个组件. 基于Lumisoft.NET组件开发碰到乱码等一些问题的解决 基于Lumisoft.NET组 ...

  2. 基于Lumisoft.NET组件的POP3邮件接收和删除操作(转载)

    Lumisoft.NET组件是一个非常强大的邮件发送.邮件接收等功能的开源组件,一般用它来处理邮件的相关操作,是非常合适的.之前也写过一些该组件的随笔文章,不过主要是利用来发送邮件居多,最近由于项目需 ...

  3. 基于Lumisoft.NET组件的POP3邮件接收和删除操作

    From: http://www.cnblogs.com/wuhuacong/archive/2013/05/06/3063093.html Lumisoft.NET组件是一个非常强大的邮件发送.邮件 ...

  4. C#- 基于Lumisoft.NET组件的POP3邮件接管和删除操纵

    Lumisoft.NET组件是一个很是强大的邮件发送.邮件接管等功能的开源组件,一般用它来处理惩罚邮件的相干操纵,是很是合适的.之前也写过一些该组件的漫笔文章,不过主如果哄骗来发送邮件居多,比来因为项 ...

  5. Android javaMail使用imap协议接收邮件

    在这里说明一下,pop3和imap协议都是接收邮件的,但是他们还是有很多不同的. IMAP和POP有什么区别? POP允许电子邮件客户端下载服务器上的邮件,但是您在电子邮件客户端的操作(如:移动邮件. ...

  6. [PHP] PHP调用IMAP协议读取邮件类库

    socket.php 为连接socket的类库 imap.php 基于socket的imap协议封装 test.php 进行测试 require_once 'socket.php'; require_ ...

  7. 使用imap协议接收邮件

    之前一直使用PHPMail类进行发送邮件,这个是一个非常强大的类,但是其实底层就是使用mail()函数来进行发送的. 但是现在公司有个需求是  写个程序需要实时的接收邮件,主要是判断邮件发出去了,并且 ...

  8. [日常] imap协议读取邮件

    telnet imap.sina.net 143 A01 LOGIN shihan@appdev.sinanet.com 密码 A02 list "" * //列出邮件夹 * LI ...

  9. mail客户端POP和IMAP协议

    POP-邮局协议 mail客户端如果使用POP协议,那么线上服务器的邮件将会自动下载到客户端. IMAP-因特网消息访问协议 mail客户端如果使用IMAP协议,邮件服务器上的邮件将不会自动下载到客户 ...

随机推荐

  1. python07day

    回顾 id == is: ==: 数值是否相同 is: 内存地址是否相同 id: 获取对象的内存地址 代码块: 一个文件.交互式命令一行都是一个代码块 同一代码块下缓存机制(字符串驻留机制) 所有数字 ...

  2. python 小兵(6)函数根据问题详解

    _list = []for i in range(3): def func(a): return i+a_list.append(func)for f in _list: print(f(1)) 首先 ...

  3. 对于fetch的理解

    在一篇文章里见到一位作者是这么说的 XMLHttpRequest 是一个设计粗糙的 API,不符合关注分离(Separation of Concerns)的原则,配置和调用方式非常混乱,而且基于事件的 ...

  4. 各种形式存放token

    1.可以将token存储在 localstorage里面,在一个统一的地方复写请求头,让每次请求都在header中带上这个token, 当token失效的时候,后端肯定会返回401,这个时候在你可以在 ...

  5. Java Calendar类的使用总结【转】

    感谢!原文地址:https://www.cnblogs.com/huangminwen/p/6041168.html Java Calendar类的使用总结 在实际项目当中,我们经常会涉及到对时间的处 ...

  6. Swift中数据类型

    Swift类型的介绍 Swift中的数据类型也有:整型/浮点型/对象类型/结构体类型等等 先了解整型和浮点型 整型 有符号 Int8 : 有符号8位整型 Int16 : 有符号16位整型 Int32 ...

  7. ubuntu 修改文件及文件夹的权限

    转载请注明来源:https://www.cnblogs.com/hookjc/ 打开终端进入你需要修改的目录然后执行下面这条命令chmod 777 * -R全部子目录及文件权限改为 777 来源:py ...

  8. C语言中的typedef跟define的区别

    今天用C语言练习时涉及到了typedef和define的使用问题,那么他们的区别是啥?这种情况下为什么要用typedef?哪种情况下为什么要用define呢? 学习C的时候的你是否考虑过这个问题呢? ...

  9. 帆软报表(finereport)图表操作细节

    图表间之间的组件间隔:body-->属性-->布局-->组件间隔 决策报表背景水印:body-->属性-->水印 仪表盘指针/枢纽/背景颜色:样式-->系列 柱形图 ...

  10. HMS Core携手厦门大学打造AR增强现实技术

    HMS Core AR Engine团队联手厦门大学信息学院,与专业学生面对面深度交流行业发展与前沿成果.双方共同编写行业知识教材,引导学生开发AR游戏实践,为未来AR.VR人才培养培育可复制的教学模 ...