System.Net.Mail.SmtpClient通过SSL/TLS协议发送邮件失败问题解决
原创原地址: https://ken.io/note/smtpclient-sending-mail-failure-via-ssl-or-tls-solved
一、问题描述
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 = "邮件测试html正文ken.io";
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://www.ruanyifeng.com/blog/2014/02/ssl_tls.html
- https://docs.microsoft.com/zh-cn/dotnet/api/system.net.mail.smtpclient
- https://docs.microsoft.com/zh-cn/dotnet/api/system.web.mail.smtpmail
- https://zh.wikipedia.org/wiki/传输层安全协议
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除
itfan123




