C# 接收POP3服务器的邮件

发布时间:2010年04月30日      浏览次数:1454 次
注意接收邮件的协议有两种,一种是POP3,另外一种较为高级的协议是IMAP4,有的邮箱使用的是POP3协议,比如网易163免费邮箱、新浪免费邮箱、搜狐免费邮箱,有的邮箱使用的是IMAP4协议,比如Gmail免费邮箱,有的两种都可以,比如QQ邮箱。这些免费邮箱都需要做一些设置(例如选择开启POP3)才能开启从客户端(比如自己做的接收邮件的程序)接收邮件的功能。
using LumiSoft.Net.MIME;
using LumiSoft.Net.POP3.Client;
using LumiSoft.Net.Mail;
public void 收邮件()
{
POP3_Client _POP3客户端 = new POP3_Client();
string POP3服务器 = "pop.163.com";
string 用户名 = "user@163.com";
string 密码 = "password";
Mail_Message mime;
//POP3_ClientMessage message;
try
{
//if (_POP3客户端.IsConnected == false)
_POP3客户端.Connect(POP3服务器, 110);
_POP3客户端.Authenticate(用户名, 密码, true);
var q = (from POP3_ClientMessage x in _POP3客户端.Messages select x).OrderBy(x=>-x.SequenceNumber );
foreach (POP3_ClientMessage message in q)//倒序对于新邮件比较快
{
try
{
mime = Mail_Message.ParseFromByte(message.HeaderToByte());
}
catch { continue; }
//下面是接收附件的一种方法,假设只有一个附件。
mime = Mail_Message.ParseFromByte(message.MessageToByte());
Stream decodedDataStream = ((MIME_b_SinglepartBase)mime.Attachments[0].Body).GetDataStream();
string file = mime.Attachments[0].ContentType.Param_Name;
using (FileStream fs = File.Create(file ))
{ LumiSoft.Net.Net_Utils.StreamCopy(decodedDataStream, fs, 4000); }

_POP3客户端.Dispose(); _POP3客户端 = null;
}
}
catch (Exception x)
{
MessageBox.Show("接收邮件时发生异常: " + x.Message, "接收邮件", MessageBoxButtons.OK, MessageBoxIcon.Hand);
}
}
C#并没有一个类专门用来接收邮件,所以这里使用了第三方组件LumiSoft.Net,如果不用这些组件就得自己去研究POP3协议了这通常是一件吃力不讨好的事情。
接收邮件的步骤如下:
1,先连接POP3服务器,这里需要几个参数,一个是服务器,比如“pop.163.com”这个是网易免费邮箱用的。一个是服务器的端口,一般是110,不过不排除某些服务器有自己规定的可能。另外一个参数可能是关于是否开启SSL加密的选项。比如Gmail 邮箱就需要SSL加密连接。
_POP3客户端.Connect(POP3服务器, 110);
2,验证身份,至少需要用户名(一般就是邮箱地址了)、密码。有的可能允许用加密的方法验证,以防止帐户信息泄露。
_POP3客户端.Authenticate(用户名, 密码, true);
上面两步都有异步方式的方法,可以避免阻塞当前UI线程。
3,验证身份成功后就会得到一些基本的信息,比如邮箱中邮件的总数,总大小。在上面的代码中邮件叫作“message”。即 邮件=message
4,通过 foreach ( POP3_ClientMessage message in _POP3客户端.Messages )
可以一封一封的查看邮件。
这个时候整个邮件并没有下载下来,通过调用一些方法,可以下载指定的部分。
比如
mime = Mail_Message.ParseFromByte(message.HeaderToByte());
这个将读取指定的邮件的头部(Header)。为什么只读取头部呢?头部的字节数比较少,从中可以了解一些信息,比如邮件的主题、发信人、接收时间。有时根据一些字段(比如发信人、主题)就可以决定是否要下载整个邮件,这样可以加快遍历。如果邮件比较大(尤其是带有大附件的时候)下载整个邮件是需要比较长的时间的。
如果要下载附件,就是
mime = Mail_Message.ParseFromByte(message.MessageToByte());
Stream decodedDataStream = ((MIME_b_SinglepartBase)mime.Attachments[0].Body).GetDataStream();
检查 Attachments 的长度就知道有多少个附件了。不过关于附件在协议上是一个复杂的概念,例如附件有复合的附件、单独的附件等。一般以文件为附件的是单独类型的附件。
下载第二个附件就是 mime.Attachments[1] 。
string file = mime.Attachments[0].ContentType.Param_Name;
using (FileStream fs = File.Create(file ))
{ LumiSoft.Net.Net_Utils.StreamCopy(decodedDataStream, fs, 4000); }
mime.Attachments[0].ContentType.Param_Name; 是附件的文件名,也可以自定义。
另外一种比较简短的方法是:
mime = Mail_Message.ParseFromByte(message.MessageToByte());
byte[] bs=ss = ((MIME_b_SinglepartBase)mime.Attachments[0].Body).Data;
但此方法对于很大的附件例如 1G的附件可能会产生内存耗尽的问题。而采用流复制的方法则下载一部分就写到文件中一部分,不是一次性全下载到内存中。
关于UID
UID是邮件的标识,就像数组的下标一样。可以用 _POP3客户端.Messages[UID]引用指定的邮件。所以如果记录了UID,要想下载这个邮件就像索引数组那样简单,而不需要去对照邮件的字段例如 主题。
删除邮件
Messages.MarkForDeletion();
但这个删除操作是在释放客户端后才执行的。如果在正常的释放客户端资源之前发生异常,有可能不删除邮件。好像是因为没有接收到一个退出命令之前标记为删除的邮件是不会删除的。而客户端(指 POP3_Client 对象)在_POP3客户端.Dispose(); _POP3客户端 = null; 之前发生异常即可能意味着不能发出退出指令……
邮件的顺序
大体上,POP3_Client .Messages 中的对象其顺序是由时间顺序排列的,即先发的邮件排在前,后发的排在后。所以遍历操作先读到旧邮件。如果采用倒序方式来遍历,则先读到新邮件。
不过试验表明,在几分钟之内连续发的邮件,遍历到的顺序并不是按发邮件的时间排序的。例如:
2010-1-29 20:37:31 完成发送邮件:第 1 封邮件
2010-1-29 20:39:26 完成发送邮件:第 2 封邮件
2010-1-29 20:41:43 完成发送邮件:第 3 封邮件
2010-1-29 20:49:24 完成发送邮件:第 4 封邮件
2010-1-29 20:52:00 完成发送邮件:第 5 封邮件
2010-1-29 20:59:15 完成发送邮件:第 6 封邮件
2010-1-29 21:01:24 完成发送邮件:第 7 封邮件
2010-1-29 21:02:12 完成发送邮件:第 8 封邮件
2010-1-29 20:59:15 接收到邮件:第 6 封邮件
2010-1-29 20:41:43 接收到邮件:第 3 封邮件
2010-1-29 21:01:24 接收到邮件:第 7 封邮件
2010-1-29 20:49:23 接收到邮件:第 4 封邮件
2010-1-29 20:37:31 接收到邮件:第 1 封邮件
2010-1-29 20:39:25 接收到邮件:第 2 封邮件
2010-1-29 20:52:00 接收到邮件:第 5 封邮件
2010-1-29 21:02:12 接收到邮件:第 8 封邮件
但在大尺度时间范围,比如天与天之间的邮件则按时间顺序可以遍历:先读到旧邮件再到新邮件。可以考虑采用倒序方式遍历。
免责声明:本站相关技术文章信息部分来自网络,目的主要是传播更多信息,如果您认为本站的某些信息侵犯了您的版权,请与我们联系,我们会即时妥善的处理,谢谢合作!