本人都会问一下.NET的最底层原理,可以遵照.NET底层实现

   发起的.NET
Core开源协会号召,进展的进度是我自己也从未想到的,很多园友都积极参加(固然有些人由衷砸场子,倘使以自我原先的宝脾气,这会应该被自己打住院了呢,但是幸而是少数,做一件事总有人说好,也有人说是用惠灵顿话说“闹眼子”),.NET社区不是未曾愿意共享知识的人,只是没有一个总体和赏心悦目的生态环境,不问可知希望国内的.NET发展进一步强大。我在这边想到一句话“大家愿意团结可以做巨浪,但大家也心甘情愿做巨浪来袭前的小浪”。

   发起的.NET
Core开源协会号召,进展的进度是自己自己也远非想到的,很多园友都积极出席(尽管有些人诚心诚意砸场子,假诺以自己在此以前的宝脾气,这会相应被自己打住院了吧,不过幸而是个别,做一件事总有人说好,也有人说是用西安话说“闹眼子”),.NET社区不是从未愿意共享知识的人,只是没有一个完全和大好的生态环境,可想而知希望国内的.NET发展尤其强大。我在此处想到一句话“我们盼望自己可以做巨浪,但我们也乐意做巨浪来袭前的小浪”。

 
 下边扯淡完毕(我这人干正事前,都要将一些拉扯的话,这些习惯改不掉了…)

 
 上边扯淡完毕(我那人干正事前,都要将一部分闲话的话,这多少个习惯改不掉了…)

 
 项目中为了及时的通信,有平素发多少到页面,也有利用短信通告,也有我门明天牵线的邮件组件。我们明日的机要职责就是教课一下有一个.NET的免费开源的邮件组件Mail基特。本文将一如既往的整合实例和组件底层代码讲解一下息息相关组件的文化。(项目招人的时候,我都会问一下.NET的底部原理,有一个大神问我这样有什么样意义呢?咱们也写不出.NET底层这样的绝妙处理形式,为什么取了然这么些,其实我个人认为,问底层的规律,只是向为了跟好的处理局部顺序出现的题目,以及对程序编码的时候,拔取最合适的艺术提升性能,任何一种情势都有优势和劣势,.NET的类库代码也是这样,假如我们知道.NET的底层实现,大家在品种的要求实现时,可以依据.NET底层实现,采纳适当的办法,以求性能最优)。

 
 项目中为了及时的通信,有一贯发多少到页面,也有采纳短信通知,也有我门明天介绍的邮件组件。大家前日的首要任务就是上课一下有一个.NET的免费开源的邮件组件Mail基特。本文将一如既往的三结合实例和零部件底层代码讲解一下相关组件的知识。(项目招人的时候,我都会问一下.NET的底层原理,有一个大神问我如此有哪些含义呢?我们也写不出.NET底层这样的完美处理模式,为啥取领悟这多少个,其实自己个人觉得,问底层的原理,只是向为了跟好的拍卖部分先后现身的题材,以及对先后编码的时候,拔取最合适的主意提升性能,任何一种方法都有优势和劣势,.NET的类库代码也是这么,如果我们知道.NET的最底层实现,我们在品种的急需实现时,可以依照.NET底层实现,选取非凡的不二法门,以求性能最优)。

一.Mailkit组件概述

 
 项目中运用Email的操作机会相比较多,一般不怎么大一些的类型,都会拔取到邮件操作那多少个操作。对于.NET邮件操作的组件和模式比较多,前几天大家就介绍一款邮件操作的机件Mail基特(Kit),这多少个邮件组件是一个开源免费的,我们今日就来询问一下这么些零部件的特性。Mime基特(Kit)目的在于通过尽可能接近地遵守MIME规范来化解那么些题目,同时还为程序员提供了一个相当容易使用的高等API。

 
 组件的协助的客户端类型相比多,例如SMTP客户端、POP3客户端、IMAP客户端。该器件是一个跨平台的Email组件,该零件匡助.NET
4.0,.NET 4.5,Xamarin.Android,Xamarin.iOS,Windows Phone
8.1等等平台。该器件提供了一个MIME解析器,组件具备的解析特性灵活、性能高、很好的拍卖千头万绪的破碎的MIME格式化。Mime基特的习性实际上与GMime出色。

   该器件在安全性的仍然比较高的,处理平安的办法较多,SASL认证、辅助S /
MIME v3.2、辅助OpenPGP、匡助DKIM签名等等格局。Mailkit组件可以由此CancellationToken废除相应的操作,CancellationToken传播应撤废操作的通报,一个的CancellationToken使线程,线程池工作项目里面,或收回合作任务的对象。过实例化CancellationTokenSource对象来制造撤废令牌,该目标管理从其CancellationTokenSource.Token属性检索的吊销令牌。然后,将注销令牌传递到应该接收撤销布告的随机数量的线程,任务或操作。令牌无法用于启动撤销。

  Mail基特(Kit)组件帮忙异步操作,在里头编写的关于I/O异步操作的类。

一.Mailkit组件概述

 
 项目中运用Email的操作机会相比多,一般不怎么大一些的花色,都会利用到邮件操作这多少个操作。对于.NET邮件操作的零部件和形式相比较多,前天大家就介绍一款邮件操作的零件Mail基特,这多少个邮件组件是一个开源免费的,我们现在就来询问一下这一个零件的特性。Mime基特目的在于通过尽可能接近地遵照MIME规范来化解这么些问题,同时还为程序员提供了一个非常容易使用的尖端API。

 
 组件的支撑的客户端类型相比多,例如SMTP客户端、POP3客户端、IMAP客户端。该器件是一个跨平台的Email组件,该零件援助.NET
4.0,.NET 4.5,Xamarin.Android,Xamarin.iOS,Windows Phone
8.1等等平台。该器件提供了一个MIME解析器,组件具备的解析特性灵活、性能高、很好的拍卖千头万绪的破损的MIME格式化。Mime基特(Kit)的性质实际上与GMime相当。

   该器件在安全性的仍旧相比高的,处理平安的章程较多,SASL认证、扶助S /
MIME v3.2、协助OpenPGP、襄助DKIM签名等等格局。Mailkit组件可以由此CancellationToken撤除相应的操作,CancellationToken传播应废除操作的布告,一个的CancellationToken使线程,线程池工作项目里面,或吊销合作任务的对象。过实例化CancellationTokenSource对象来创设裁撤令牌,该指标管理从其CancellationTokenSource.Token属性检索的吊销令牌。然后,将撤消令牌传递到应该接收撤消文告的自由数量的线程,任务或操作。令牌不可能用来启动撤废。

  Mail基特(Kit)组件协助异步操作,在其间编写的有关I/O异步操作的类。

二.MailKit实例:

   
下面介绍了Mail基特(Kit)组件的背景和特点,这里就介绍一下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对象后,指定邮件的地方和焦点等等相关音信。第二步实例化TextPart对象,为对象设定文本信息。若需要问邮件创制文件的附件,可以运用MimePart对象,包含内容(如信息正文文本或)的叶节点MIME部分一个附件。第四步为成立的邮件主体和文件以及附件音讯后,可以创造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部分一个附件。第四步为成立的邮件主体和文书以及附件信息后,可以创立Multipart对象,创立邮件容器,用来装载文本消息和附件。最终调用MimeMessage.body属性获取或设置信息的正文。

    2.邮件音信的辨析:

var message = MimeMessage.Load(stream);

 
 邮件的音讯大家需要展开相应的分析,那里大家选择MimeMessage的Load方法,该办法从指定的流加载Mime基特(Kit).MimeMessage。另一个加载数据的不二法门,可以拔取MimeParser类,这里就不再解析了。

    2.邮件消息的剖析:

var message = MimeMessage.Load(stream);

 
 邮件的音信大家需要展开对应的辨析,这里我们使用MimeMessage的Load方法,该措施从指定的流加载Mime基特(Kit).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是内容的树结构,很像一个文件系统。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是内容的树结构,很像一个文件系统。MIME确实定义了一组通用规则,用于邮件客户端怎么样分解MIME部分的树结构。的 内容处置头是为了给接受客户端提供提示以如何部分是为着展现作为信息体的一有些,并且意在被演讲为附件。其它二种艺术这离就不做牵线了。

三.Mail基特主题对象解析

 
 下面介绍了Email的基本操作就不做过多的介绍,在运用该器件时,较为的简练。这里就来看望该器件的花色结构和部分着力目的。类库结构有如下图:

图片 1

三.Mail基特主题对象解析

 
 上边介绍了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,具有6个章程重载。该情势再次来到一个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的万分时就更是的粗略,以上是对丰盛知识捕获,有些地点并从未做处理,有些地方是对那一个的地点举办复苏。

    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,具有6个措施重载。该措施再次来到一个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的特别时就越是的简便,以上是对这些知识捕获,有些位置并不曾做拍卖,有些地点是对特其余地点开展还原。

   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判断是否可写。该措施定义为虚方法,在延续此形式后,可以在子类种对该方法举办重写。

四.总结

 
 本人觉得在品种开发中,假诺引入了第三方组件,大家尽量引入组件的源码,这样我们对整个组件的结构有一个认识,组件的兑现形式我们也可以开展精雕细刻了解,尤其是我们在进展调试的事后更加有用,我们得以逐一的展开断点调试。以上是对该零件的一个简单介绍,有趣味的可以去深刻的明白和读书。

四.总结

 
 本人觉得在项目开发中,假诺引入了第三方组件,我们尽量引入组件的源码,这样我们对任何组件的结构有一个认识,组件的兑现模式大家也得以开展仔细了然,尤其是咱们在开展调试的将来愈来愈有用,我们可以逐一的拓展断点调试。以上是对该零件的一个粗略介绍,有趣味的能够去长远的垂询和读书。