美文网首页ASP.NET Core 2.1 入门教程.NET
System.Net.Mail.SmtpClient通过SSL/

System.Net.Mail.SmtpClient通过SSL/

作者: KenTalk | 来源:发表于2020-03-09 22:02 被阅读0次

    一、问题描述

    1、问题现象

    通过System.Net.Mail.SmtpClient使用SSL/TLS协议发送邮件失败并报错
    System.Net.Mail.SmtpException: Failure sending mail

    详细报错信息:

    System.Net.Mail.SmtpException: Failure sending mail.
     ---> System.IO.IOException: Unable to read data from the transport connection: The connection was closed.
       at System.Net.Mail.SmtpReplyReaderFactory.ProcessRead(Byte[] buffer, Int32 offset, Int32 read, Boolean readLine)
       at System.Net.Mail.SmtpReplyReaderFactory.ReadLines(SmtpReplyReader caller, Boolean oneLine)
       at System.Net.Mail.SmtpReplyReaderFactory.ReadLine(SmtpReplyReader caller)
       at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
       at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port)
       at System.Net.Mail.SmtpClient.GetConnection()
       at System.Net.Mail.SmtpClient.Send(MailMessage message)
       --- End of inner exception stack trace ---
       at System.Net.Mail.SmtpClient.Send(MailMessage message)
    

    2、问题原因

    这个问题跟SSL/TLS的协议版本有关系,SSL演化到3.0之后还是不够安全,因此又出现了SSL的升级版TLS协议,由于建立连接时的区别又分别被称为显示SSL和隐式SSL。SSL/TLS协议通常是结对出现SSL/TLS,不过大家还是喜欢简称为SSL。

    目前最新版本是TLS 1.3,其他可用版本是TLS 1.2和TLS 1.1,其中TLS1.1计划于2020年弃用

    所以,目前主流的邮箱服务商加密协议使用的都是TLS。
    但是System.Net.Mail.SmtpClient 不支持较新的TLS协议,具体的TLS协议版本支持情况MSDN上并未找到相关说明

    截止到2020年3月受影响的框架版本:

    • .NET Core 2.0-3.1
    • .NET Framework 2.0-4.8

    目前微软MSDN已经将System.Net.Mail.SmtpClient标记为已过期(obsolete),但源码中并未标记,也并未给出替代实现。

    二、解决办法

    1、使用System.Web.Mail

    System.Web.Mail.SmtpMail虽然已被标记为已过期,但是毕竟他支持新的SSL/TLS协议。

    不过,需要注意的是,System.Web.Mail.SmtpMail,只适用于 .NET Framework(>=2.0)

    示例代码

    using System.Web.Mail;
    using System;
    
    namespace Ken.IO.Util {
    
        class Program
        {
            public static void Main (string[] args)
            {
                MailMessage mmsg = new MailMessage();
                mmsg.Subject = "邮件测试主题ken.io";
                mmsg.BodyFormat = MailFormat.Html;
                mmsg.Body = "邮件测试正文ken.io";
                mmsg.BodyEncoding = Encoding.UTF8;
                //优先级
                mmsg.Priority = MailPriority.High;
                //发件者邮箱地址
                mmsg.From = "xxx@qq.com";
                //收件人收箱地址
                mmsg.To = "xxx@163.com";
                mmsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1");
                //用户名
                mmsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", mmsg.From);
                //密码
                mmsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", "password");
                //端口 
                mmsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport", 465);
                //使用SSL 
                mmsg.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpusessl", "true");
                //Smtp服务器
                SmtpMail.SmtpServer = "smtp.qq.com";
                SmtpMail.Send(mmsg);
            }
        }
    }
    

    2、使用MailKit

    MailKit是一个开源的基于MimeKit的跨平台邮件收发类库,支持IMAP、POP3、SMTP。其中SmtpClient也支持TLS协议.

    可以很好的支持 .NET Core以及 .NET Framework框架的邮件发送

    安装Nuget Package

    #.NET Core
    dotnet add package MailKit --version 2.5.1
    
    #.NET Framework
    Install-Package MailKit -Version 2.5.1
    

    示例代码

    using System;
    using MailKit.Net.Smtp;
    using MailKit;
    using MimeKit;
    
    namespace Ken.IO.Util {
        
        class Program
        {
            public static void Main (string[] args)
            {
                var message = new MimeMessage ();
                message.From.Add (new MailboxAddress ("test", "xxx@qq.com"));
                message.To.Add (new MailboxAddress ("test", "xxx@163.com"));
                message.Subject = "邮件测试";
                //html or plain
                var bodyBuilder = new BodyBuilder ();
                bodyBuilder.HtmlBody = "<b>邮件测试html正文ken.io</b>";
                bodyBuilder.TextBody = "邮件测试文本正文ken.io";
                message.Body = bodyBuilder.ToMessageBody();
    
                using (var client = new SmtpClient ()) {
                    client.ServerCertificateValidationCallback = (s,c,h,e) => true;
                    //smtp服务器,端口,是否开启ssl
                    client.Connect ("smtp.qq.com", 465, true);
                    client.Authenticate ("xxx@qq.com", "password");
                    client.Send (message);
                    client.Disconnect (true);
                }
            }
        }
    }
    

    三、备注

    1、附录


    本文首发于:https://ken.io/note/smtpclient-sending-mail-failure-via-ssl-or-tls-solved

    相关文章

      网友评论

        本文标题:System.Net.Mail.SmtpClient通过SSL/

        本文链接:https://www.haomeiwen.com/subject/mpnmdhtx.html