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;
            }
        }

 

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值