呼之欲出 WebMail 開發手記 (六) 郵件收取

iDotNetSpace發表於2009-07-15


題外話:首先謝謝各位無論是喜歡我的文章不喜歡我的文章的朋友,有你們的幫助我才會成長。上面兩篇文章可能確實沒有什麼實際的意義,讓大家對我的文章有個誤解,但我想那是為後面的文章鋪路,文章裡面的簽名也只是防止其他網站的轉載,可能大家的想法不一樣。我以後的文章還是希望前輩多多批評指正,謝謝。

 

郵件的收發,無非就是使用一些元件,找到自己合適的那就用下去。當然如果技術很不錯,可以自己動手分析郵件協議,那是另當別論了。

目前用得比較多的,大概就是  jmail 了。我這裡也就使用這個元件進行郵件的收取,郵件的傳送就使用 .net 自帶的元件了。

只是現在網路可能過於發達了,要的東西找不到,不要的東西一大堆,就拿收郵件來說,一搜尋到處就是一樣的文章,抄來抄去,抄也就算了,站長也不檢查檢查,感覺一點沒勁,時不時會罵一句:站長真會偷牛!!

 

收發郵件中我們至少需要考慮下面幾個因素:

  1. 每個使用者有多個郵箱配置資訊;
  2. 當前郵箱的收發狀態;
  3. 收發郵件異常;
  4. 伺服器允許的收發郵件時間間隔。(小於這個時間可能賬戶會被暫時遮蔽)

首先我們增加一個繼承自 IMailThread,IDisposable 的類 MailThread,既然是使用執行緒收發,那麼必須定義的兩個變數:

 

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

 

好了,現在我們啟動接收郵件執行緒:

 

呼之欲出 WebMail 開發手記 (六) 郵件收取
        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分鐘,就不能再收取。

 

 

呼之欲出 WebMail 開發手記 (六) 郵件收取
呼之欲出 WebMail 開發手記 (六) 郵件收取private void BeginReceive() {
    SqlDataReader configs 
= (new Config()).GetConfigs(userId);
呼之欲出 WebMail 開發手記 (六) 郵件收取    
if(configs != null{
        _pop3Time 
= DateTime.Now;
        _pop3State 
= 1;
呼之欲出 WebMail 開發手記 (六) 郵件收取        
while(configs.Read()) {
            DateTime pTime 
= DateTime.Parse(configs["pop3Time"].ToString());
            TimeSpan m 
= DateTime.Now - pTime;
            
// 每5分鐘收取郵件一次/超過100分鐘也重新收取
呼之欲出 WebMail 開發手記 (六) 郵件收取
            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 
= "接收完成";
呼之欲出 WebMail 開發手記 (六) 郵件收取    }
 else {
        _pop3State 
= 3;
        _pop3Message 
= "無配置資訊";
    }

    _threadReceive 
= null;
}


實踐證明,jmail 收取的郵件有兩個地方必須自己處理一下,才能得到正確的結果。一個是主題,一個是日期,所以我在上一篇中提到了郵件頭解碼和日期處理的函式:

 

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


 

呼之欲出 WebMail 開發手記 (六) 郵件收取
呼之欲出 WebMail 開發手記 (六) 郵件收取#region 接收單個郵箱的郵件
呼之欲出 WebMail 開發手記 (六) 郵件收取
/// 
/// 接收單個郵箱的郵件
/// 
/// 
/// 
/// 
/// 
/// 
/// 
/// 

呼之欲出 WebMail 開發手記 (六) 郵件收取public void Receive(int configId, string pop3Uid, string pop3Pwd, string pop3Address, int pop3Port, byte pop3Backup, string smtpReply) {
呼之欲出 WebMail 開發手記 (六) 郵件收取    
if(!string.IsNullOrEmpty(pop3Address)) {
        MailHelper.SaveLogs(basePath, _pop3Mail);
//string.Format("開始收取 {0} 的郵件, 當前使用者ID是 {1}", _pop3Mail, userId));

        jmail.POP3Class p 
= new jmail.POP3Class();
        p.Timeout 
= 100;
呼之欲出 WebMail 開發手記 (六) 郵件收取        
try {
            
// 連線伺服器
            p.Connect(pop3Uid, pop3Pwd, pop3Address, pop3Port);
            jmail.Message message;
            jmail.Attachments attachments;
            
string messageId, subject;

            MailAddressCollection mailAddr;
            
// 總郵件數:p.Messages.Count-1
呼之欲出 WebMail 開發手記 (六) 郵件收取
            for(int i = 1; i < p.Messages.Count; i++{
                _pop3Message 
= string.Format("正在檢查第 {0} 封郵件,共 {1} 封", i, p.Messages.Count - 1);

呼之欲出 WebMail 開發手記 (六) 郵件收取                
收取單封郵件
            }


            message 
= null;
            attachments 
= null;
            p.Disconnect();
呼之欲出 WebMail 開發手記 (六) 郵件收取        }
 catch(Exception ex0) {
            MailHelper.SaveLogs(basePath, 
"登入錯誤:" + ex0.Message);
        }


        
// 儲存最後接收時間
        dbmail.SetReceiveState(userId, configId, DateTime.Now, 0);

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

}

#endregion


其中 dbmail 是郵件系統與資料庫打交道的類,在本系列講完,將提供下載。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-609236/,如需轉載,請註明出處,否則將追究法律責任。

相關文章