NET邮件协议MailKit组件解析

by admin on 2019年2月19日

   发起的.NET
Core开源社团号召,进展的速度是小编自身也并未想到的,很多园友都积极参与(即使有点人诚心砸场子,即使以自小编在此此前的宝本性,那会应该被本人打住院了啊,不过幸亏是少数,做一件事总有人说好,也有人说是用塞内加尔达喀尔话说“闹眼子”),.NET社区不是绝非愿意共享文化的人,只是没有1个完完全全和赏心悦目的生态环境,总之希望国内的.NET发展进一步强大。小编在那边想到一句话“我们盼望团结能够做巨浪,但大家也乐于做巨浪来袭前的小浪”。

   发起的.NET
Core开源社团号召,进展的进程是自身要好也并未想到的,很多园友都积极加入(即便有点人由衷砸场子,假诺以我原先的宝性情,那会相应被自个儿打住院了吗,不过幸好是个别,做一件事总有人说好,也有人说是用斯特拉斯堡话说“闹眼子”),.NET社区不是绝非愿意共享知识的人,只是没有3个整体和优质的生态环境,可想而知希望国内的.NET发展尤其强大。小编在那里想到一句话“我们期望团结可以做巨浪,但大家也乐于做巨浪来袭前的小浪”。

 
 下面扯淡完结(作者那人干正事前,都要将有些拉扯的话,这么些习惯改不掉了…)

 
 下面扯淡完结(作者那人干正事前,都要将一些闲谈的话,那个习惯改不掉了…)

 
 项目中为了及时的通讯,有间接发多少到页面,也有使用短信文告,也有笔者门昨天牵线的邮件组件。大家今日的重中之重任务就是执教一下有二个.NET的免费开源的邮件组件MailKit。本文将一如既往的咬合实例和组件底层代码讲解一下巢倾卵破组件的文化。(项目招人的时候,小编都会问一下.NET的底部原理,有1个大神问我那样有啥样意思吗?大家也写不出.NET底层那样的优良处理方式,为什么取了然那一个,其实本身个人觉得,问底层的法则,只是向为了跟好的拍卖部分先后出现的题材,以及对先后编码的时候,采用最合适的法子提高质量,任何一种办法都有优势和逆风局,.NET的类库代码也是如此,固然大家知道.NET的平底已毕,大家在类型的要求已毕时,可以依照.NET底层达成,接纳适当的措施,以求质量最优)。

 
 项目中为了及时的通讯,有直接发多少到页面,也有应用短信通告,也有作者门后天介绍的邮件组件。大家前几日的首要职务就是上课一下有多个.NET的免费开源的邮件组件MailKit。本文将一如既往的整合实例和组件底层代码讲解一下唇亡齿寒组件的文化。(项目招人的时候,作者都会问一下.NET的底层原理,有一个大神问小编这么有怎么样含义呢?大家也写不出.NET底层那样的理想处理形式,为啥取明白那几个,其实小编个人认为,问底层的原理,只是向为了跟好的处理局地主次出现的标题,以及对程序编码的时候,拔取最合适的法门进步性能,任何一种艺术都有优势和逆风局,.NET的类库代码也是那样,如果大家知道.NET的底层落成,大家在品种的要求落成时,可以依照.NET底层完结,采纳合适的办法,以求质量最优)。

一.Mailkit组件概述

 
 项目中使用Email的操作机会相比多,一般不怎么大一些的品类,都会动用到邮件操作那三个操作。对于.NET邮件操作的零部件和艺术比较多,前几天大家就介绍一款邮件操作的组件MailKit,这一个邮件组件是一个开源免费的,大家今日就来驾驭一下那三个零部件的风味。MimeKit目的在于通过尽可能接近地依照MIME规范来化解这些难题,同时还为程序员提供了1个相当不难使用的尖端API。

 
 组件的支持的客户端类型相比多,例如SMTP客户端、POP3客户端、IMAP客户端。该器件是3个跨平台的Email组件,该零件匡助.NET
4.0,.NET 4.5,Xamarin.Android,Xamarin.iOS,Windows Phone
8.1等等平台。该零件提供了三个MIME解析器,组件具备的剖析天性灵活、品质高、很好的处理千丝万缕的破碎的MIME格式化。MimeKit的品质实际上与GMime至极。

   该零件在安全性的如故相比高的,处理平安的艺术较多,SASL认证、资助S /
MIME v3.② 、援助OpenPGP、协助DKIM签名等等方式。Mailkit组件可以经过CancellationToken撤销相应的操作,CancellationToken传播应撤废操作的打招呼,三个的CancellationToken使线程,线程池工作类型里面,或废除合营义务的对象。过实例化CancellationTokenSource对象来创制撤消令牌,该对象管理从其CancellationTokenSource.Token属性检索的吊销令牌。然后,将吊销令牌传递到应该接收撤消公告的即兴数量的线程,职分或操作。令牌不可以用于运行打消。

  MailKit组件协助异步操作,在里头编写的关于I/O异步操作的类。

一.Mailkit组件概述

 
 项目中使用Email的操作机会相比多,一般不怎么大一点的类型,都会接纳到邮件操作那三个操作。对于.NET邮件操作的机件和章程比较多,今天大家就介绍一款邮件操作的组件MailKit,这些邮件组件是2个开源免费的,大家后日就来打听一下那三个零件的表征。MimeKit目的在于通过尽或许接近地依据MIME规范来缓解这几个题材,同时还为程序员提供了三个非凡简单使用的高档API。

 
 组件的支撑的客户端类型相比较多,例如SMTP客户端、POP3客户端、IMAP客户端。该零件是2个跨平台的Email组件,该器件支持.NET
4.0,.NET 4.5,Xamarin.Android,Xamarin.iOS,Windows Phone
8.1之类平台。该器件提供了1个MIME解析器,组件具备的辨析天性灵活、品质高、很好的拍卖盘根错节的破碎的MIME格式化。MimeKit的个性实际上与GMime十分。

   该器件在安全性的照旧比较高的,处理平安的主意较多,SASL认证、帮助S /
MIME v3.② 、辅助OpenPGP、帮助DKIM签名等等格局。Mailkit组件可以通过CancellationToken打消相应的操作,CancellationToken传播应取消操作的关照,1个的CancellationToken使线程,线程池工作类型里面,或吊销合作义务的对象。过实例化CancellationTokenSource对象来创立撤废令牌,该目的管理从其CancellationTokenSource.Token属性检索的吊销令牌。然后,将废除令牌传递到应该接收废除布告的自由数量的线程,职务或操作。令牌不可以用来运维废除。

  MailKit组件帮衬异步操作,在里头编写的有关I/O异步操作的类。

二.MailKit实例:

   
上边介绍了Mail基特组件的背景和特色,那里就介绍一下Email组件的简单利用。

二.MailKit实例:

   
上面介绍了Mail基特组件的背景和特点,那里就介绍一下Email组件的简要利用。

  1.开立邮件形式:

 public void SentEmail(string path)
        {
            var message = new MimeMessage();
            //获取From标头中的地址列表,添加指定的地址
            message.From.Add(new MailboxAddress("Joey", "joey@friends.com"));
            //获取To头中的地址列表,添加指定的地址
            message.To.Add(new MailboxAddress("Alice", "alice@wonderland.com"));
            //获取或设置消息的主题
            message.Subject = "How you doin?";
            // 创建我们的消息文本,就像以前一样(除了不设置为message.Body)
            var body = new TextPart("plain")
            {
                Text = @"Hey Alice-- Joey"
            };
            // 为位于路径的文件创建图像附件
            var attachment = new MimePart("image", "gif")
            {
                ContentObject = new ContentObject(File.OpenRead(path), ContentEncoding.Default),
                ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
                ContentTransferEncoding = ContentEncoding.Base64,
                FileName = Path.GetFileName(path)
            };
            // 现在创建multipart / mixed容器来保存消息文本和图像附件
            var multipart = new Multipart("mixed")
            {
                body, attachment
            };
            // 现在将multipart / mixed设置为消息正文 
            message.Body = multipart;
        }

 
 调用该零件发送邮件和为邮件添加附件是比较简单的,第①步是实例化MimeMessage对象,对于该目的的解析将在上面举办,拿到MimeMessage对象后,指定邮件的地址和主旨等等相关音信。第2步实例化TextPart对象,为目的设定文本音信。若须求问邮件创立文件的附件,能够运用MimePart对象,包涵内容(如音讯正文文本或)的叶节点MIME部分2个附件。第4步为创立的邮件主体和文件以及附件音讯后,可以创设Multipart对象,成立邮件容器,用来装载文本音信和附件。最后调用MimeMessage.body属性获取或设置音信的正文。

  1.创设邮件情势:

 public void SentEmail(string path)
        {
            var message = new MimeMessage();
            //获取From标头中的地址列表,添加指定的地址
            message.From.Add(new MailboxAddress("Joey", "joey@friends.com"));
            //获取To头中的地址列表,添加指定的地址
            message.To.Add(new MailboxAddress("Alice", "alice@wonderland.com"));
            //获取或设置消息的主题
            message.Subject = "How you doin?";
            // 创建我们的消息文本,就像以前一样(除了不设置为message.Body)
            var body = new TextPart("plain")
            {
                Text = @"Hey Alice-- Joey"
            };
            // 为位于路径的文件创建图像附件
            var attachment = new MimePart("image", "gif")
            {
                ContentObject = new ContentObject(File.OpenRead(path), ContentEncoding.Default),
                ContentDisposition = new ContentDisposition(ContentDisposition.Attachment),
                ContentTransferEncoding = ContentEncoding.Base64,
                FileName = Path.GetFileName(path)
            };
            // 现在创建multipart / mixed容器来保存消息文本和图像附件
            var multipart = new Multipart("mixed")
            {
                body, attachment
            };
            // 现在将multipart / mixed设置为消息正文 
            message.Body = multipart;
        }

 
 调用该零件发送邮件和为邮件添加附件是相比简单的,第①步是实例化MimeMessage对象,对于该目标的剖析将在上面举办,拿到MimeMessage对象后,钦点邮件的地方和主旨等等相关新闻。第三步实例化TextPart对象,为目标设定文本音讯。若须要问邮件创设文件的附件,可以运用MimePart对象,包含内容(如音信正文文本或)的叶节点MIME部分1个附件。第⑤步为开创的邮件主体和文书以及附件消息后,可以创制Multipart对象,创造邮件容器,用来装载文本音信和附件。最终调用MimeMessage.body属性获取或设置音信的正文。

    2.邮件音讯的辨析:

var message = MimeMessage.Load(stream);

 
 邮件的音讯我们需求进行相应的解析,那里大家应用MimeMessage的Load方法,该方法从内定的流加载MimeKit.MimeMessage。另一个加载数据的章程,可以利用MimeParser类,那里就不再解析了。

    2.邮件音讯的解析:

var message = MimeMessage.Load(stream);

 
 邮件的新闻大家需求展开相应的辨析,那里我们接纳MimeMessage的Load方法,该措施从指定的流加载Mime基特.MimeMessage。另两个加载数据的不二法门,能够使用MimeParser类,这里就不再解析了。

    3.邮件的采取:

   public static void HandleMimeEntity(MimeEntity entity)
        {
            //MimeEntity转化为Multipart实体
            var multipart = entity as Multipart;
            if (multipart != null)
            {
                for (int i = 0; i < multipart.Count; i++)
                    HandleMimeEntity(multipart[i]);
                return;
            }
            var rfc822 = entity as MessagePart;

            if (rfc822 != null)
            {
                var message = rfc822.Message;
                HandleMimeEntity(message.Body);
                return;
            }
            var part = (MimePart)entity;
        }

 
 以上是对接到到的音信的三个遍历,选用递归遍历MIME结构。MIME是内容的树结构,很像2个文件系统。MIME确实定义了一组通用规则,用于邮件客户端怎样分解MIME部分的树结构。的 内容处置头是为了给接受客户端提供提示以怎么着部分是为了显得作为音信体的一有的,并且意在被解说为附件。别的二种办法这离就不做牵线了。

    3.邮件的收到:

   public static void HandleMimeEntity(MimeEntity entity)
        {
            //MimeEntity转化为Multipart实体
            var multipart = entity as Multipart;
            if (multipart != null)
            {
                for (int i = 0; i < multipart.Count; i++)
                    HandleMimeEntity(multipart[i]);
                return;
            }
            var rfc822 = entity as MessagePart;

            if (rfc822 != null)
            {
                var message = rfc822.Message;
                HandleMimeEntity(message.Body);
                return;
            }
            var part = (MimePart)entity;
        }

 
 以上是对接收到的音信的多个遍历,采纳递归遍历MIME结构。MIME是内容的树结构,很像1个文件系统。MIME确实定义了一组通用规则,用于邮件客户端怎么着分解MIME部分的树结构。的 内容处置头是为了给接受客户端提供提示以什么部分是为着显得作为音讯体的一局地,并且旨在被分解为附件。别的二种格局那离就不做牵线了。

三.MailKit主旨对象解析

 
 上边介绍了Email的基本操作就不做过多的介绍,在行使该零件时,较为的粗略。那里就来探视该器件的种类结构和局地主导目的。类库结构有如下图:

图片 1

三.MailKit主题对象解析

 
 上边介绍了Email的基本操作就不做过多的介绍,在使用该零件时,较为的总结。那里就来探视该器件的类型结构和一些中坚目标。类库结构有如下图:

图片 2

    1.MimeMessage.Load():

public static MimeMessage Load (ParserOptions options, Stream stream, bool persistent, 
                                CancellationToken cancellationToken = default (CancellationToken))
        {
            if (options == null)
                throw new ArgumentNullException (nameof (options));

            if (stream == null)
                throw new ArgumentNullException (nameof (stream));

            var parser = new MimeParser (options, stream, MimeFormat.Entity, persistent);

            return parser.ParseMessage (cancellationToken);
        }

   
 该措施从钦定的流加载MimeMessage,具有四个点子重载。该格局重回二个MimeMessage对象,有源码可以看出,在该办法内部创设了二个MimeParser对象,MimeParser包括内容(例如邮件正文文本或附件)的叶节点MIME部分。调用ParseMessage方法,解析来自流的新闻。

   2.TextPart.Text:

public string Text {
            get {
                if (ContentObject == null)
                    return string.Empty;
                var charset = ContentType.Parameters["charset"];
                using (var memory = new MemoryStream ()) {
                    ContentObject.DecodeTo (memory);
                    var content = memory.ToArray ();
                    Encoding encoding = null;
                    if (charset != null) {
                        try {
                            encoding = CharsetUtils.GetEncoding (charset);
                        } catch (NotSupportedException) {
                        }
                    }
                    if (encoding == null) {
                        try {
                            return CharsetUtils.UTF8.GetString (content, 0, (int) memory.Length);
                        } catch (DecoderFallbackException) {
                            encoding = CharsetUtils.Latin1;
                        }
                    }
                    return encoding.GetString (content, 0, (int) memory.Length);
                }
            }
            set {
                SetText (Encoding.UTF8, value);
            }
        }

   
该属性获取解码的文书内容。该属性是二个可读可写的品质。ContentType.Parameters[“charset”]用以获取charset参数的值。该方法用来将参数的值设置为多少流并设置相应的编码。看到此间的非凡处理社团,就想大致的谈几句,.NET的万分相比的薄弱,很多时候在写.NET的11分时就尤其的简约,以上是对至极知识捕获,有个别地方并从未做处理,有些地方是对丰裕的地点举行回复。

    1.MimeMessage.Load():

public static MimeMessage Load (ParserOptions options, Stream stream, bool persistent, 
                                CancellationToken cancellationToken = default (CancellationToken))
        {
            if (options == null)
                throw new ArgumentNullException (nameof (options));

            if (stream == null)
                throw new ArgumentNullException (nameof (stream));

            var parser = new MimeParser (options, stream, MimeFormat.Entity, persistent);

            return parser.ParseMessage (cancellationToken);
        }

   
 该办法从内定的流加载MimeMessage,具有几个办法重载。该措施再次回到贰个MimeMessage对象,有源码可以看出,在该方法内部创建了2个MimeParser对象,MimeParser包括内容(例如邮件正文文本或附件)的叶节点MIME部分。调用ParseMessage方法,解析来自流的音讯。

   2.TextPart.Text:

public string Text {
            get {
                if (ContentObject == null)
                    return string.Empty;
                var charset = ContentType.Parameters["charset"];
                using (var memory = new MemoryStream ()) {
                    ContentObject.DecodeTo (memory);
                    var content = memory.ToArray ();
                    Encoding encoding = null;
                    if (charset != null) {
                        try {
                            encoding = CharsetUtils.GetEncoding (charset);
                        } catch (NotSupportedException) {
                        }
                    }
                    if (encoding == null) {
                        try {
                            return CharsetUtils.UTF8.GetString (content, 0, (int) memory.Length);
                        } catch (DecoderFallbackException) {
                            encoding = CharsetUtils.Latin1;
                        }
                    }
                    return encoding.GetString (content, 0, (int) memory.Length);
                }
            }
            set {
                SetText (Encoding.UTF8, value);
            }
        }

   
该属性获取解码的文件内容。该属性是二个可读可写的质量。ContentType.Parameters[“charset”]用以获取charset参数的值。该方法用来将参数的值设置为数量流并设置相应的编码。看到此间的丰裕处理社团,就想几乎的谈几句,.NET的那么些相比较的软弱,很多时候在写.NET的要命时就越发的归纳,以上是对非常知识捕获,有个别地点并从未做处理,有些地点是对丰裕的地点举行复原。

   3.MimeEntity.WriteTo():

public virtual void WriteTo (FormatOptions options, Stream stream, bool contentOnly, 
                            CancellationToken cancellationToken = default (CancellationToken))
        {
            if (options == null)
                throw new ArgumentNullException (nameof (options));

            if (stream == null)
                throw new ArgumentNullException (nameof (stream));

            if (!contentOnly)
                Headers.WriteTo (options, stream, cancellationToken);
        }

   
该方法将MimeEntity写入到钦命的数量流中,该办法接受参数options格式选项。stream输出数据流,contentOnly判断是还是不是可写。该格局定义为虚方法,在继承此方法后,可以在子类种对该办法举办重写。

   3.MimeEntity.WriteTo():

public virtual void WriteTo (FormatOptions options, Stream stream, bool contentOnly, 
                            CancellationToken cancellationToken = default (CancellationToken))
        {
            if (options == null)
                throw new ArgumentNullException (nameof (options));

            if (stream == null)
                throw new ArgumentNullException (nameof (stream));

            if (!contentOnly)
                Headers.WriteTo (options, stream, cancellationToken);
        }

   
该形式将MimeEntity写入到内定的多少流中,该方法接受参数options格式选项。stream输出数据流,contentOnly判断是不是可写。该措施定义为虚方法,在继续此格局后,可以在子类种对该方法开展重写。

四.总结

 
 自己认为在类型支付中,如若引入了第③方组件,我们尽量引入组件的源码,那样大家对总体组件的布局有1个认识,组件的完结格局大家也足以开展仔细了然,尤其是大家在进展调节的之后更是有用,我们可以逐一的展开断点调试。以上是对该零件的三个不难介绍,有趣味的能够去长远的垂询和学习。

四.总结

 
 自身觉得在档次开支中,即使引入了第1方组件,大家尽量引入组件的源码,那样咱们对整个组件的结构有一个认识,组件的兑现方式我们也足以展开细致精通,尤其是我们在展开调节的之后更进一步有用,大家得以逐一的拓展断点调试。以上是对该器件的一个简约介绍,有趣味的可以去长远的垂询和学习。

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图