1. 程式人生 > 其它 >基於Lumisoft.NET元件,使用IMAP協議收取郵件

基於Lumisoft.NET元件,使用IMAP協議收取郵件

在早期一直使用Lumisoft.NET元件來進行郵件的處理查詢,對於郵件的處理非常方便,之前在隨筆《基於Lumisoft.NET元件的POP3郵件接收和刪除操作》中也介紹過基於POP3和SMPT進行郵件的收發處理,一般郵件伺服器對於Pop3都是支援很好的,常規使用測試多個伺服器都沒問題,所以就沒怎麼研究IMAP協議的處理,本篇隨筆基於原來POP3 的需求擴充套件了IMAP協議的處理。

在早期一直使用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 [email protected] for help

如有興趣,瞭解Lumisoft.NET元件的相關使用內容,請參考我相關隨筆,謝謝。

基於Lumisoft.NET元件和.NET API實現郵件傳送功能的對比

基於Lumisoft.NET實現的郵件傳送功能

基於Lumisoft.NET元件開發碰到亂碼等一些問題的解決

基於Lumisoft.NET元件的SMTP賬號登陸檢測

郵件代收代發軟件操作說明

郵件代收代發功能模組的操作介面設計和階段性總結

主要研究技術:程式碼生成工具、會員管理系統、客戶關係管理軟體、病人資料管理軟體、Visio二次開發、酒店管理系統、倉庫管理系統等共享軟體開發
專注於Winform開發框架/混合式開發框架Web開發框架Bootstrap開發框架微信門戶開發框架的研究及應用
  轉載請註明出處:
撰寫人:伍華聰  http://www.iqidi.com