MailKit的使用心得

Mailkit 支持 Pop3、IMAP,STMP是目前.Net端最全的郵件開源項目了。

1、Pop3:跟其他的pop3操作類沒有太大區別,跟OpenPop.NET等都差不多

2、IMAP:功能上比Pop3要強大太多,優勢是功能強大、可以搜索郵箱的所有文件夾,Pop3只能搜索INBOX(收件箱),如果要做收信,還是IMAP首選。缺點是每一次操作都會與服務器同步,比如讀取了郵件,服務器上也會變爲已讀,而Pop3不會。

如果做郵箱收信的話,還是必須同時支持 Pop3、IMAP。

大體使用方式:

1、在設計模式上實現一個抽象類GetEmail_base

2、然後再寫一個IMAP、Pop3操作類並繼承抽象類( GetMail_IMAP : GetEmail_base、GetMail_Pop : GetEmail_base)

3、最後在寫一個GetEmail類對外使用,通過字段 private GetEmail_base GetEmail_Bll 將IMAP、Pop3操作合併統一操作郵件。

4、具體實現比較多,由於GetEmail類夾雜了很多我自有的判斷,所以不方便上傳。

今天要說的並不是Mailkit的基礎操作,而是遇到過的一個大坑!!!!

在使用過程中,我曾遇到一個很蛋疼的問題,跑着跑着Mailkit 突然就卡住了,既不報錯,也沒有異常,就在那卡着,無論是Connect、Login又或者是其他任何操作,即便你設置了imapClient.Timeout、pop3Client.Timeout。

最開始十分疑惑,也沒有找到原因,在嘗試折騰了N次,並查看了源碼之後發現,雖然我調用的是同步方法(Mailkit 支持異步),可是Mailkit 內部實際還是用的等待異步來執行的,而異步執行中有一個很重要的參數cancellationToken我沒有填,因爲這個參數支持默認值,一開始我以爲既然有默認值,而且同步執行應該可以不需要設置這個參數,設置 Timeout就可以了,事實證明還是太年輕了。cancellationToken、Timeout分管的是兩個不同的東西。

解決方法:在每個帶有cancellationToken參數的方法中都帶上自定義參數

var TokenSource = new CancellationTokenSource(30000);//30s超時

folder.Open(FolderAccess.ReadWrite, cancellationToken: TokenSource.Token);

var msg = folder.GetMessage(Index, cancellationToken: TokenSource.Token); 

folder.Close(cancellationToken: TokenSource.Token);

imapClient.Identify(clientImplementation, cancellationToken: TokenSource.Token);

IMAP、Pop3都需要!!!設置好之後再也沒有出現卡住不動的情況

 

ImapClient擴展類

    public static class ImapClientEx
        {
        /// <summary>
        /// task取消時間
        /// </summary>
        private static readonly int CancelTokenMillSecends = 30000;
        /// <summary>
        /// 模擬郵件客戶端信息(是出自:https://www.cnblogs.com/zuimengaitianya/p/8579315.html)
        /// </summary>
        /// <param name="imapClient"></param>
        public static void Identify(this ImapClient imapClient)
            {
            List<ImapImplementation> Implements = new List<ImapImplementation>()
                {
                new ImapImplementation() {Name = "foxmail",Version = "7.2.9.156", },
                new ImapImplementation() {Name = "outlook",Version = "14.0.4760.1000", },
                };
            Func<ImapCapabilities, ImapCapabilities, bool> HasImapCapabilitiesId = (sourceFlag, targetFlag) => { return ((sourceFlag | targetFlag) == sourceFlag); };
            if (HasImapCapabilitiesId(imapClient.Capabilities, ImapCapabilities.Id))
                {
                var clientImplementation = new ImapImplementation
                    {
                    Name = "foxmail",
                    Version = "7.2.9.156",
                    };
                var TokenSource = new CancellationTokenSource(CancelTokenMillSecends);
                var serverImplementation = imapClient.Identify(clientImplementation, cancellationToken: TokenSource.Token);
                }
            }

        public static int GetMessageCount(this ImapClient imapClient, IMailFolder folder, bool closeFolder = false)
            {
            if (imapClient == null)
                return 0;
            var TokenSource = new CancellationTokenSource(CancelTokenMillSecends);
            if (!folder.IsOpen)
                folder.Open(MailKit.FolderAccess.ReadWrite, cancellationToken: TokenSource.Token);
            var Count = folder.Count;
            if (closeFolder)
                folder.Close(cancellationToken: TokenSource.Token);

            return Count;
            }
        public static int GetMessageCount(this ImapClient imapClient, IMailFolder folder, SearchQuery Query, bool closeFolder = false)
            {
            var Count = imapClient.GetManyMessageUids(folder, Query, closeFolder)?.Count;
            return Count ?? 0;
            }

        public static List<UniqueId> GetManyMessageUids(this ImapClient imapClient, IMailFolder folder, SearchQuery Query, bool closeFolder = false)
            {
            if (imapClient == null)
                return null;
            //List<IMailFolder> mailFolderList = imapClient.GetFolders(imapClient.PersonalNamespaces[0]).ToList();//取所有文件夾
            if (folder == null)
                return null;
            var TokenSource = new CancellationTokenSource(CancelTokenMillSecends);
            if (!folder.IsOpen)
                folder.Open(FolderAccess.ReadWrite, cancellationToken: TokenSource.Token);
            var uids = folder.Search(Query, cancellationToken: TokenSource.Token);
            if (closeFolder)
                folder.Close(cancellationToken: TokenSource.Token);
            return uids?.ToList();
            }

        public static MimeMessage GetMessage(this ImapClient imapClient, UniqueId Id, IMailFolder folder, bool closeFolder = false)
            {
            if (imapClient == null)
                return null;
            //List<IMailFolder> mailFolderList = imapClient.GetFolders(imapClient.PersonalNamespaces[0]).ToList();//取所有文件夾
            if (folder == null)
                return null;
            var TokenSource = new CancellationTokenSource(CancelTokenMillSecends);
            if (!folder.IsOpen)
                folder.Open(MailKit.FolderAccess.ReadWrite, cancellationToken: TokenSource.Token);
            var msg = folder.GetMessage(Id, cancellationToken: TokenSource.Token);
            if (closeFolder)
                folder.Close(cancellationToken: TokenSource.Token);
            return msg;
            }
        public static MimeMessage GetMessage(this ImapClient imapClient, int Index, IMailFolder folder, bool closeFolder = false)
            {
            if (imapClient == null)
                return null;
            //List<IMailFolder> mailFolderList = imapClient.GetFolders(imapClient.PersonalNamespaces[0]).ToList();//取所有文件夾
            if (folder == null)
                return null;
            var TokenSource = new CancellationTokenSource(CancelTokenMillSecends);
            if (!folder.IsOpen)
                folder.Open(FolderAccess.ReadWrite, cancellationToken: TokenSource.Token);
            var msg = folder.GetMessage(Index, cancellationToken: TokenSource.Token); 
            if (closeFolder)
                folder.Close(cancellationToken: TokenSource.Token);
            return msg;
            }

        public static IList<IMessageSummary> FetchMessage(this ImapClient imapClient, List<UniqueId> Ids, IMailFolder folder, MessageSummaryItems Item, bool closeFolder = false)
            {
            if (imapClient == null)
                return null;
            //List<IMailFolder> mailFolderList = imapClient.GetFolders(imapClient.PersonalNamespaces[0]).ToList();//取所有文件夾
            if (folder == null)
                return null;
            var TokenSource = new CancellationTokenSource(CancelTokenMillSecends);
            if (!folder.IsOpen)
                folder.Open(FolderAccess.ReadWrite, cancellationToken: TokenSource.Token);
            var msg = folder.Fetch(Ids, Item, cancellationToken: TokenSource.Token);
            if (closeFolder)
                folder.Close(cancellationToken: TokenSource.Token);
            return msg;
            }
        public static IList<IMessageSummary> FetchMessage(this ImapClient imapClient, List<int> indexes, IMailFolder folder, MessageSummaryItems Item, bool closeFolder = false)
            {
            if (imapClient == null)
                return null;
            //List<IMailFolder> mailFolderList = imapClient.GetFolders(imapClient.PersonalNamespaces[0]).ToList();//取所有文件夾
            if (folder == null)
                return null;
            var TokenSource = new CancellationTokenSource(CancelTokenMillSecends);
            if (!folder.IsOpen)
                folder.Open(FolderAccess.ReadWrite, cancellationToken: TokenSource.Token);
            var msg = folder.Fetch(indexes, Item, cancellationToken: TokenSource.Token);
            if (closeFolder)
                folder.Close(cancellationToken: TokenSource.Token);
            return msg;
            }

        public static bool DeleteMessage(this ImapClient imapClient, UniqueId Id, IMailFolder folder, SearchQuery Query, bool closeFolder = false)
            {
            if (imapClient == null)
                return false;
            //List<IMailFolder> mailFolderList = imapClient.GetFolders(imapClient.PersonalNamespaces[0]).ToList();//取所有文件夾
            if (folder == null)
                return false;
            var TokenSource = new CancellationTokenSource(CancelTokenMillSecends);
            if (!folder.IsOpen)
                folder.Open(FolderAccess.ReadWrite, cancellationToken: TokenSource.Token);
            //設置狀態
            folder.SetFlags(Id, MessageFlags.Deleted, false, cancellationToken: TokenSource.Token);
            //或者刪除郵件
            folder.RemoveFlags(Id, MessageFlags.Deleted, false);
            //主要針對Exchange 讓刪除指令執行
            folder.Expunge(cancellationToken: TokenSource.Token);

            if (closeFolder)
                folder.Close(cancellationToken: TokenSource.Token);
            return true;
            }
        public static bool DeleteMessage(this ImapClient imapClient, int EmailIndex, IMailFolder folder, SearchQuery Query, bool closeFolder = false)
            {
            if (imapClient == null)
                return false;
            //List<IMailFolder> mailFolderList = imapClient.GetFolders(imapClient.PersonalNamespaces[0]).ToList();//取所有文件夾
            if (folder == null)
                return false;
            var TokenSource = new CancellationTokenSource(CancelTokenMillSecends);
            if (!folder.IsOpen)
                folder.Open(FolderAccess.ReadWrite, cancellationToken: TokenSource.Token);
            //設置狀態
            folder.SetFlags(EmailIndex, MessageFlags.Deleted, false, cancellationToken: TokenSource.Token);
            //或者刪除郵件
            folder.RemoveFlags(EmailIndex, MessageFlags.Deleted, false, cancellationToken: TokenSource.Token);
            //主要針對Exchange 讓刪除指令執行
            folder.Expunge(cancellationToken: TokenSource.Token);

            if (closeFolder)
                folder.Close(cancellationToken: TokenSource.Token);
            return true;
            }
        }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章