技术开发 频道

WebMail 开发手记 (六) 邮件收取

    【IT168技术文档】邮件的收发,无非就是使用一些组件,找到自己合适的那就用下去。当然如果技术很不错,可以自己动手分析邮件协议,那是另当别论了。

    目前用得比较多的,大概就是 jmail 了。我这里也就使用这个组件进行邮件的收取,邮件的发送就使用 .net 自带的组件了。

第一篇  WebMail 开发手记 (一)(二)
第二篇  WebMail 开发手记 (三) 用户信息存取
第三篇  WebMail 开发手记 (四) 邮件收发准备
第四篇  WebMail 开发手记 (五) 邮件操作类
第五篇  WebMail 开发手记 (六) 邮件收取
第六篇  WebMail 开发手记 (七) 邮件发送
第七篇  WebMail 开发手记 (八) WebService

    收发邮件中我们至少需要考虑下面几个因素:

    每个用户有多个邮箱配置信息;
    当前邮箱的收发状态;
    收发邮件异常;
    服务器允许的收发邮件时间间隔。(小于这个时间可能账户会被暂时屏蔽)
    首先我们增加一个继承自 IMailThread,IDisposable 的类 MailThread,既然是使用线程收发,那么必须定义的两个变量:

 


private Thread _threadReceive = null;// 收取
private Thread _threadSend = null;// 发送
 

好了,现在我们启动接收邮件线程:

 


public void ReceiveStart() {
// 判断当前用户和线程状态
if (userId == 0 || _threadReceive != null)
return;
lock (this) {// 锁定当前线程,否则可能出现邮件重复了。
if(_pop3State!=0) {
_pop3State = 0;
}
// 启动线程
_threadReceive = new Thread(new ThreadStart(BeginReceive));
_threadReceive.Start();
}
}
 

     相信大家已经注意到 BeginReceive 这个家伙了,在这个方法里面,我们首先从数据库中取出当前用户的所有邮箱配置信息,然后依次检查每个邮箱的收取状态,如果正在收取并且距离上一次收取的时间间隔不超过5分钟,就不能再收取。

 

 

private void BeginReceive() {
SqlDataReader configs = (new Config()).GetConfigs(userId);
if(configs != null) {
_pop3Time = DateTime.Now;
_pop3State = 1;
while(configs.Read()) {
DateTime pTime = DateTime.Parse(configs["pop3Time"].ToString());
TimeSpan m = DateTime.Now - pTime;
// 每5分钟收取邮件一次/超过100分钟也重新收取
if (( m.TotalMinutes >= 5 && configs["pop3Doing"].ToString() == "0") || m.TotalMinutes >= 100) {
_pop3Mail = string.Format("当前接收邮箱({0}):", configs["ConfigName"]);

dbmail.SetReceiveState(userId, configs["Id"], DateTime.Now, 1);

// 接收单个邮箱的邮件
Receive(
int.Parse(configs["ID"].ToString()),
configs["Pop3Uid"].ToString(),
MailHelper.Decrypt(configs["Pop3Pwd"].ToString(), "123456"),
configs["Pop3Address"].ToString(),
int.Parse(configs["Pop3Port"].ToString()),
byte.Parse(configs["Pop3Backup"].ToString()),
configs["SmtpReply"].ToString()
);
}
}
configs.Close();
_pop3State = 2;
_pop3Message = "接收完成";
} else {
_pop3State = 3;
_pop3Message = "无配置信息";
}
_threadReceive = null;
}


    实践证明,jmail 收取的邮件有两个地方必须自己处理一下,才能得到正确的结果。一个是主题,一个是日期,所以我在上一篇中提到了邮件头解码和日期处理的函数:

 

string subject = MailHelper.DecodeStr(message.Headers.GetHeader("Subject"));
string date = MailHelper.ParseDate(message.Headers.GetHeader("Date"));

 


#region 接收单个邮箱的邮件
/// <summary>
/// 接收单个邮箱的邮件
/// <param name="configId"></param>
/// <param name="pop3Address"></param>
/// <param name="pop3Backup"></param>
/// <param name="pop3Port"></param>
/// <param name="pop3Pwd"></param>
/// <param name="pop3Uid"></param>
/// <param name="smtpReply"></param>
/// </summary>
public void Receive(int configId, string pop3Uid, string pop3Pwd, string pop3Address, int pop3Port, byte pop3Backup, string smtpReply) {
if(!string.IsNullOrEmpty(pop3Address)) {
MailHelper.SaveLogs(basePath, _pop3Mail);//string.Format("开始收取 {0} 的邮件, 当前用户ID是 {1}", _pop3Mail, userId));

jmail.POP3Class p = new jmail.POP3Class();
p.Timeout = 100;
try {
// 连接服务器
p.Connect(pop3Uid, pop3Pwd, pop3Address, pop3Port);
jmail.Message message;
jmail.Attachments attachments;
string messageId, subject;

MailAddressCollection mailAddr;
// 总邮件数:p.Messages.Count-1
for(int i = 1; i < p.Messages.Count; i++) {
_pop3Message = string.Format("正在检查第 {0} 封邮件,共 {1} 封", i, p.Messages.Count - 1);

收取单封邮件
}

message = null;
attachments = null;
p.Disconnect();
} catch(Exception ex0) {
MailHelper.SaveLogs(basePath, "登录错误:" + ex0.Message);
}

// 保存最后接收时间
dbmail.SetReceiveState(userId, configId, DateTime.Now, 0);

MailHelper.SaveLogs(basePath, "邮件收取完成\r\n");
}
}
#endregion
 

0
相关文章