呼之欲出 WebMail 开发手记 (六) 邮件收取

使用JMail组件实现邮件收发
本文介绍如何使用JMail组件实现邮件的收取与发送功能。通过创建线程进行邮件处理,确保邮件操作的效率与准确性。文章详细展示了如何通过JMail连接邮件服务器、获取邮件信息并保存至数据库的过程。

题外话:首先谢谢各位无论是喜欢我的文章不喜欢我的文章的朋友,有你们的帮助我才会成长。上面两篇文章可能确实没有什么实际的意义,让大家对我的文章有个误解,但我想那是为后面的文章铺路,文章里面的签名也只是防止其他网站的转载,可能大家的想法不一样。我以后的文章还是希望前辈多多批评指正,谢谢。

 

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

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

只是现在网络可能过于发达了,要的东西找不到,不要的东西一大堆,就拿收邮件来说,一搜索到处就是一样的文章,抄来抄去,抄也就算了,站长也不检查检查,感觉一点没劲,时不时会骂一句:站长真会偷牛!!

 

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

  1. 每个用户有多个邮箱配置信息;
  2. 当前邮箱的收发状态;
  3. 收发邮件异常;
  4. 服务器允许的收发邮件时间间隔。(小于这个时间可能账户会被暂时屏蔽)

首先我们增加一个继承自 IMailThread,IDisposable 的类 MailThread,既然是使用线程收发,那么必须定义的两个变量:

 

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

 

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

 

ContractedBlock.gifExpandedBlockStart.gifCode
        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分钟,就不能再收取。

 

 

ContractedBlock.gifExpandedBlockStart.gifBeginReceive
ExpandedBlockStart.gifContractedBlock.gifprivate void BeginReceive() {
    SqlDataReader configs 
= (new Config()).GetConfigs(userId);
ExpandedSubBlockStart.gifContractedSubBlock.gif    
if(configs != null{
        _pop3Time 
= DateTime.Now;
        _pop3State 
= 1;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
while(configs.Read()) {
            DateTime pTime 
= DateTime.Parse(configs["pop3Time"].ToString());
            TimeSpan m 
= DateTime.Now - pTime;
            
// 每5分钟收取邮件一次/超过100分钟也重新收取
ExpandedSubBlockStart.gifContractedSubBlock.gif
            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 
= "接收完成";
ExpandedSubBlockStart.gifContractedSubBlock.gif    }
 else {
        _pop3State 
= 3;
        _pop3Message 
= "无配置信息";
    }

    _threadReceive 
= null;
}


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

 

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


 

ContractedBlock.gifExpandedBlockStart.gifReceive:接收单个邮箱的邮件
ContractedBlock.gifExpandedBlockStart.gif接收单个邮箱的邮件#region 接收单个邮箱的邮件
ExpandedSubBlockStart.gifContractedSubBlock.gif
/**//// <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>

ExpandedSubBlockStart.gifContractedSubBlock.gifpublic void Receive(int configId, string pop3Uid, string pop3Pwd, string pop3Address, int pop3Port, byte pop3Backup, string smtpReply) {
ExpandedSubBlockStart.gifContractedSubBlock.gif    
if(!string.IsNullOrEmpty(pop3Address)) {
        MailHelper.SaveLogs(basePath, _pop3Mail);
//string.Format("开始收取 {0} 的邮件, 当前用户ID是 {1}", _pop3Mail, userId));

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

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

ContractedSubBlock.gifExpandedSubBlockStart.gif                
收取单封邮件#region 收取单封邮件
ExpandedSubBlockStart.gifContractedSubBlock.gif                
try {
                    
// 判断是否收取过
                    messageId = p.GetMessageUID(i);

ExpandedSubBlockStart.gifContractedSubBlock.gif                    
if (dbmail.Exists(userId, configId, messageId)) {
                        
continue;
                    }


                    
// 获取邮件信息
                    message = p.Messages[i];

ExpandedSubBlockStart.gifContractedSubBlock.gif                    
if(string.IsNullOrEmpty(message.Charset)) {
                        message.Charset 
= "gb2312";
                    }

ExpandedSubBlockStart.gifContractedSubBlock.gif                    
if(string.IsNullOrEmpty(message.Encoding)) {
                        message.Encoding 
= "base64";
                    }

                    message.ISOEncodeHeaders 
= false;

                    
bool isHtml = true;
                    
string body = message.HTMLBody;
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
if(body == null{
                        isHtml 
= false;
                        body 
= message.Body;
                    }

                    
// 重新处理主题
                    subject = MailHelper.DecodeStr(message.Headers.GetHeader("Subject"));
                    
string date = message.Headers.GetHeader("Date");
                    mailAddr 
= MailHelper.GetAddress(message.From);
                    
string mailFrom = mailAddr.Count > 0 ? mailAddr[0].Address : message.From;
                    
                    
// 保存邮件
                    attachments = message.Attachments;
                    
int mailId = dbmail.SaveMail(userId, 0, configId, messageId, subject, body, mailFrom, smtpReply,
                        
"", isHtml, message.Size, message.Priority, attachments.Count > 04, MailHelper.ParseDate(date), 10);

                    
// 保存附件
ExpandedSubBlockStart.gifContractedSubBlock.gif
                    if(mailId > 0{
ExpandedSubBlockStart.gifContractedSubBlock.gif                        
for(int j = 0; j < attachments.Count; j++{
                            
string attname = attachments[j].Name;
                            
string fileext = "";
ExpandedSubBlockStart.gifContractedSubBlock.gif                            
if(attname.IndexOf("."!= -1{
                                fileext 
= attname.Substring(attname.LastIndexOf("."));
                            }

                            
string fileurl = MailHelper.MakeFileName() + i.ToString().PadLeft(3'0'+ j.ToString().PadLeft(2'0'+ fileext;

                            attachments[j].SaveToFile(basePath 
+ fileurl);

                            dbmail.SaveAttachment(attname, fileurl, attachments[j].ContentType, attachments[j].Size, mailId);
                        }

                    }

                    
// 删除服务器上的邮件
ExpandedSubBlockStart.gifContractedSubBlock.gif
                    if(pop3Backup == 0{
                        p.DeleteSingleMessage(i);
                    }


ExpandedSubBlockStart.gifContractedSubBlock.gif                }
 catch(Exception ex) {
                    MailHelper.SaveLogs(basePath, 
"接收第" + i.ToString() + "封邮件时出错:" + ex.Message);
                }
 
                
#endregion

            }


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


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

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

}

#endregion


其中 dbmail 是邮件系统与数据库打交道的类,在本系列讲完,将提供下载。

请关注我的下一篇文章,并给予支持批评教育,谢谢大家。

转载于:https://www.cnblogs.com/lyout/archive/2009/07/10/webmail6.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值