SmtpException:无法从传输连接中读取数据:net_io_connectionclosed
Posted
技术标签:
【中文标题】SmtpException:无法从传输连接中读取数据:net_io_connectionclosed【英文标题】:SmtpException: Unable to read data from the transport connection: net_io_connectionclosed 【发布时间】:2013-12-12 06:41:32 【问题描述】:我正在使用SmtpClient
库通过以下方式发送电子邮件:
SmtpClient client = new SmtpClient();
client.Host = "hostname";
client.Port = 465;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.EnableSsl = true;
client.Credentials = new NetworkCredential("User", "Pass);
client.Send("from@hostname", "to@hostname", "Subject", "Body");
代码在我的测试环境中运行良好,但是当我使用生产 SMTP 服务器时,代码失败并显示SmtpException
“发送邮件失败”。带有内部IOException
“无法从传输连接读取数据:net_io_connectionclosed”。
我已经确认防火墙不是问题。端口在客户端和服务器之间打开得很好。我不确定还有什么可能引发此错误。
【问题讨论】:
【参考方案1】:编辑:超级 Redux 版本
尝试使用端口 587 而不是 465。端口 465 在技术上已被弃用。
经过一堆数据包嗅探后,我想通了。首先,这是一个简短的答案:
.NET SmtpClient
仅支持通过 STARTTLS 进行加密。如果设置了EnableSsl
标志,则服务器必须使用 STARTTLS 响应 EHLO,否则将抛出异常。有关详细信息,请参阅MSDN 文档。
其次,为将来偶然发现此问题的人提供的快速 SMTP 历史课程:
过去,当服务还想提供加密时,它们被分配了一个不同的端口号,并在该端口号上立即启动 SSL 连接。随着时间的推移,他们意识到为一个服务浪费两个端口号是愚蠢的,他们设计了一种服务方法,允许使用 STARTTLS 在同一个端口上进行明文和加密。通信将使用明文开始,然后使用 STARTTLS 命令升级到加密连接。 STARTTLS 成为 SMTP 加密的标准。不幸的是,在实施新标准时总是会发生这种情况,因此与那里的所有客户端和服务器的兼容性都是大杂烩。
在我的例子中,我的用户试图将软件连接到强制立即 SSL 连接的服务器,这是 Microsoft 在 .NET 中不支持的旧方法。
【讨论】:
如何判断我连接的服务器是否有同样的问题?我正在尝试将 SmtpClient 与 yahoo 和/或 gmail 一起使用并得到描述的错误。当我尝试使用 2013 交换服务器时,我的代码运行良好。 最简单的测试方法是尝试使用端口 587 而不是 465。虽然一些 SMTP 服务器支持 465(有时甚至是 25)上的 TLS,但只需要端口 587 即可支持 TLS。除此之外,自 1998 年以来 (en.wikipedia.org/wiki/SMTPS) 已弃用端口 465,尽管实际上许多服务器已为旧版客户端启用它。 是的,改成 587 就行了。感谢您为我指明正确的方向。 587 有效,尽管 smtp.att.yahaoo.com 说使用 465。谢谢伙计。 对于一个实际的解决方案,请参阅***.com/a/1014876/247702 使用(已弃用)支持隐式 SSL 的 System.Web.Mail。【参考方案2】:对于偶然发现这篇文章并寻找解决方案并且您已通过 Azure 设置 SMTP sendgrid 的任何人。
用户名不是您在 Azure 中创建 sendgrid 对象时设置的用户名。查找您的用户名;
在 azure 中单击您的 sendgrid 对象,然后单击管理。您将被重定向到 SendGrid 站点。 确认您的电子邮件,然后复制那里显示的用户名。这是一个自动生成的用户名。 将 SendGrid 中的用户名添加到 web.config 文件中的 SMTP 设置中。希望这会有所帮助!
【讨论】:
这可能看起来很愚蠢,但您可能要检查的其他内容是密码是否适用于 SMTP SendGrid 设置。我们的设置最初是有效的,然后有一天我们开始收到 OP 的异常消息。在 WWW 上的搜索大多指向查看其他 SMTP 服务器配置,但最终发现密码不正确。团队中有人将配置文件中的密码更改为首字母不大写的变体。 在我的情况下,用户名不正确并且有错字。但是错误的密码也会给出“无法从传输连接读取数据:net_io_connectionclosed”。错误。所以检查用户名和密码。对于 Azure 用户,用户名的格式为“azure_guid-withoutdashes@azure.com”(例如:azure_e9e062db4bfd491296bec77bcff49ed9@azure.com)【参考方案3】:将端口从 465 更改为 587 即可。
【讨论】:
我不确定发生了什么,但这对我使用 gmail smtp 有效。你能解释一下为什么会这样吗?【参考方案4】:我已尝试上述所有答案,但 Office 365 帐户仍然出现此错误。当允许不太安全的应用程序时,该代码似乎可以与 Google 帐户和 smtp.gmail.com 一起正常工作。
我可以尝试任何其他建议吗?
这是我正在使用的代码
int port = 587;
string host = "smtp.office365.com";
string username = "smtp.out@mail.com";
string password = "password";
string mailFrom = "noreply@mail.com";
string mailTo = "to@mail.com";
string mailTitle = "Testtitle";
string mailMessage = "Testmessage";
using (SmtpClient client = new SmtpClient())
MailAddress from = new MailAddress(mailFrom);
MailMessage message = new MailMessage
From = from
;
message.To.Add(mailTo);
message.Subject = mailTitle;
message.Body = mailMessage;
message.IsBodyhtml = true;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Host = host;
client.Port = port;
client.EnableSsl = true;
client.Credentials = new NetworkCredential
UserName = username,
Password = password
;
client.Send(message);
更新以及我是如何解决的:
通过将 Smtp Client 更改为 Mailkit 解决了问题。由于安全问题,Microsoft 现在不建议使用 System.Net.Mail Smtp 客户端,您应该改用 MailKit。使用 Mailkit 给了我更清晰的错误消息,我可以理解找到问题的根本原因(许可证问题)。您可以通过将 Mailkit 下载为 Nuget 包来获取它。
阅读有关 SMTP 客户端的文档以获取更多信息: https://docs.microsoft.com/es-es/dotnet/api/system.net.mail.smtpclient?redirectedfrom=MSDN&view=netframework-4.7.2
这是我使用 MailKit 实现 SmtpClient 的方法
int port = 587;
string host = "smtp.office365.com";
string username = "smtp.out@mail.com";
string password = "password";
string mailFrom = "noreply@mail.com";
string mailTo = "mailto@mail.com";
string mailTitle = "Testtitle";
string mailMessage = "Testmessage";
var message = new MimeMessage();
message.From.Add(new MailboxAddress(mailFrom));
message.To.Add(new MailboxAddress(mailTo));
message.Subject = mailTitle;
message.Body = new TextPart("plain") Text = mailMessage ;
using (var client = new SmtpClient())
client.Connect(host , port, SecureSocketOptions.StartTls);
client.Authenticate(username, password);
client.Send(message);
client.Disconnect(true);
【讨论】:
如果您收到“SMTP 服务器已意外断开连接”。可能是您的提供商没有 TLS。即使我的提供商说 TLS 兼容,它也不起作用,所以我尝试使用 SecureSocketOptions.SslOnConnect 并让它工作。如果它可以帮助某人。【参考方案5】:您可能还需要更改 Gmail 帐户上的“不太安全的应用”设置。 EnableSsl,使用端口 587 并启用“不太安全的应用程序”。如果您使用 google 搜索不太安全的应用程序部分,则会有 google 帮助页面将您直接链接到您帐户的页面。那是我的问题,但由于以上所有答案,现在一切正常。
【讨论】:
谢谢比尔。这仍然适用于我的标准 gmail 帐户。如果您不使用“不太安全的应用程序”设置,则必须使用 OAuth2 两部分身份验证。当您只想从网站发送确认电子邮件时,这是不切实际的。 “不太安全的应用程序”设置在哪里。我正在我的 gmail 帐户中寻找它。 我找到了“不太安全的应用程序”设置 - 它不在 Gmail 设置中,而是在 Google 帐户设置中:我的帐户 > 登录和安全myaccount.google.com/…【参考方案6】:针对 Outlook Mailer 的答复
var SmtpClient = new SmtpClient
DeliveryMethod = SmtpDeliveryMethod.Network,
Credentials = new System.Net.NetworkCredential("email", "password"),
Port = 587,
Host = "smtp.office365.com",
EnableSsl = true
https://admin.exchange.microsoft.com/#/settings -> 点击邮件流
-> 检查 - 启用旧 TLS 客户端的使用
-> 保存
【讨论】:
【参考方案7】:删除
client.UseDefaultCredentials = false;
似乎为我解决了这个问题。
【讨论】:
【参考方案8】:把这个放在我的方法的开头为我解决了这个问题
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12
【讨论】:
这似乎是2022年的正确答案。我还添加了一些其他协议> ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 |安全协议类型.Tls |安全协议类型.Tls11 | SecurityProtocolType.Tls12; 测试了其他答案,但只有这个对我有用【参考方案9】:您的 SMTP 库是否支持加密连接?邮件服务器可能期待安全的 TLS 连接,因此在没有 TLS 握手的情况下关闭连接
【讨论】:
它只是默认的.NETSmtpClient
库,它确实支持加密,服务器确实需要加密,我设置了client.EnableSssl = true;
。虽然我想我会用 Wireshark 进一步说明这一点。【参考方案10】:
如果您在同一个盒子上使用 SMTP 服务器,并且您的 SMTP 绑定到 IP 地址而不是“任何已分配”,则它可能会失败,因为它试图使用 SMTP 所在的 IP 地址(如 127.0.0.1)目前没有工作。
【讨论】:
【参考方案11】:为了提升 jocull 在评论中提到的内容,我正在做这个线程中提到的所有事情并删除......因为我的循环被一遍又一遍地运行;第一次通过循环后,有时会失败。总是第一次通过循环。
需要明确:循环包括创建 SmtpClient,然后使用正确的数据执行 .Send。 SmtpClient 是在 try/catch 块内创建的,用于捕获错误并确保对象在循环底部之前被销毁。
在我的情况下,解决方案是确保在循环中的每次之后处理 SmtpClient(通过 using() 语句或通过手动处理)。即使 SmtpClient 对象在循环中被隐式销毁,.NET 似乎也会留下一些东西以与下一次尝试发生冲突。
【讨论】:
【参考方案12】:将端口号从 465 更改为 587
【讨论】:
【参考方案13】:在我的例子中,客户忘记在他们的 SMTP 设置中添加新的 IP 地址。在设置 smtp 的服务器中打开 IIS 6.0,右键单击 Smtp 虚拟服务器,选择属性,访问选项卡,单击连接,添加新服务器的 IP 地址。然后单击中继,同时添加新服务器的 IP 地址。这解决了我的问题。
【讨论】:
【参考方案14】:如果您的邮件服务器是 Gmail (smtp.google.com),当您达到邮件限制时,您会收到此错误消息。 Gmail 允许通过 SMTP 每 24 小时最多发送 2000 封邮件。
【讨论】:
【参考方案15】:我在使用 smtp.office365.com 时遇到了这个问题,使用端口 587 和 SSL。我能够使用 portal.office.com 登录该帐户,并且可以确认该帐户具有许可证。但是当我触发发送电子邮件的代码时,我不断收到 net_io_connectionclosed 错误。
我花了一些时间才弄明白,但 Exchange 管理员找到了罪魁祸首。我们使用的是 O365,但 Exchange 服务器处于混合环境中。尽管我们尝试使用的帐户已同步到 Azure AD 并具有有效的 O365 许可证,但由于某种原因,邮箱仍驻留在混合 Exchange 服务器上 - 而不是 Exchange Online。在交换管理员使用“移动邮箱”命令将邮箱从混合交换服务器移动到 O365 之后,我们可以使用代码使用 o365 发送电子邮件。
【讨论】:
【参考方案16】:如果您使用的是 Sendgrid 并且收到此错误,那是因为 sendgrid 不再允许基本身份验证。我们需要创建 API 密钥并将其用作 NetworkCredential。 username="apikey" 密码将是您的 API 密钥 参考——https://docs.sendgrid.com/for-developers/sending-email/integrating-with-the-smtp-api
【讨论】:
【参考方案17】:我在使用 .NET smtp 客户端 + office 365 邮件服务器时遇到了同样的问题:有时邮件发送成功,有时不成功(间歇性发送失败)。
问题已通过将所需的 TLS 版本设置为 1.2 仅 得到解决。原始代码(在 2021 年年中开始失败 - BTW)允许 TLS 1.0、TLS 1.1 和 TLS 1.2。
代码(CLI/C++)
int tls12 = 3072; // Tls12 is not defined in the SecurityProtocolType enum in CLI/C++ / ToolsVersion="4.0"
System::Net::ServicePointManager::SecurityProtocol = (SecurityProtocolType) tls12;
(注意:问题已在 Win 8.1 机器上重现并修复)
【讨论】:
【参考方案18】:试试这个:这是我用来向多个用户发送电子邮件的代码。
public string gmail_send()
using (MailMessage mailMessage =
new MailMessage(new MailAddress(toemail),
new MailAddress(toemail)))
mailMessage.Body = body;
mailMessage.Subject = subject;
try
SmtpClient SmtpServer = new SmtpClient();
SmtpServer.Credentials =
new System.Net.NetworkCredential(email, password);
SmtpServer.Port = 587;
SmtpServer.Host = "smtp.gmail.com";
SmtpServer.EnableSsl = true;
mail = new MailMessage();
String[] addr = toemail.Split(','); // toemail is a string which contains many email address separated by comma
mail.From = new MailAddress(email);
Byte i;
for (i = 0; i < addr.Length; i++)
mail.To.Add(addr[i]);
mail.Subject = subject;
mail.Body = body;
mail.IsBodyHtml = true;
mail.DeliveryNotificationOptions =
DeliveryNotificationOptions.OnFailure;
// mail.ReplyTo = new MailAddress(toemail);
mail.ReplyToList.Add(toemail);
SmtpServer.Send(mail);
return "Mail Sent";
catch (Exception ex)
string exp = ex.ToString();
return "Mail Not Sent ... and ther error is " + exp;
【讨论】:
SmtpClient
也是一次性的,所以它应该被包裹在一个 using
块中【参考方案19】:
如果上述所有解决方案都不适合您,请尝试将以下文件更新到您的服务器(我的意思是发布,在此之前的构建会有所帮助)。
bin-> projectname.dll
更新后你会看到这个错误。 正如我用这个解决方案解决的那样。
【讨论】:
令人惊讶的是这对我有用!允许不安全的应用程序已打开,并且端口已设置为 587。 谢谢,刚刚意识到我不是唯一一个遇到这个问题的人。很乐意提供帮助。【参考方案20】:对于 Outlook 使用以下不会给我错误的设置
SMTP 服务器名称 smtp-mail.outlook.com
SMTP 端口 587
【讨论】:
【参考方案21】:此错误非常普遍。可能是由于多种原因,例如 邮件服务器不正确。 一些托管公司使用 mail.domainname 格式。 如果你只是使用域名,它不会工作。 检查凭据 主机名 如果需要,用户名密码 请咨询托管公司。
<smtp from="info@india.uu.com">
<!-- Uncomment to specify SMTP settings -->
<network host="domain.com" port="25" password="Jin@" userName="info@india.xx.com"/>
</smtp>
</mailSettings>
【讨论】:
【参考方案22】:在我的情况下,Web 服务器 IP 在邮件服务器上被阻止,需要由您的托管公司解除阻止并将其列入白名单。另外,使用端口 587。
【讨论】:
【参考方案23】:我最初的问题是间歇性发送失败。例如。第一个 Send()
成功,第二个 Send()
失败,第三个 Send()
成功。起初我以为我没有正确处理。于是我求助于using()
。
反正后来我加了UseDefaultCredentials = false
,Send()终于稳定了。
不知道为什么。
【讨论】:
【参考方案24】:我最近不得不在我们所有的应用程序上设置新的邮件设置,并在多个项目中遇到了这个错误。
对我来说,解决方案是在我的一些项目中将目标框架更新为较新的版本。
我还有一个 ASP.net 网站项目,其中更新目标框架还不够,我还必须将以下代码添加到 web.config <httpRuntime targetFramework="4.8"/>
【讨论】:
【参考方案25】:准备: 1. HostA 是 SMTP 虚拟服务器,默认端口为 25 2. HostB 是我使用 SmtpClient 发送邮件的工作站 并模拟不稳定的网络 I use clumsy
案例 1 如果 HostB 是 2008R2 当我发送电子邮件时。 那么就会出现这个问题。
案例 2 如果 HostB 是 2012 或更高版本 当我发送电子邮件时。 然后邮件就发出去了。
结论:这个根本原因与Windows Server 2008R2有关。
【讨论】:
以上是关于SmtpException:无法从传输连接中读取数据:net_io_connectionclosed的主要内容,如果未能解决你的问题,请参考以下文章
SendGrid 无法从传输连接读取数据:net_io_connectionclosed
azure blob storage-无法从传输连接读取数据:现有连接被远程主机强行关闭
System.Net.Mail.SmtpException:SMTP 服务器需要安全连接或客户端未通过身份验证
无法使用 gmail 通过 python 发送电子邮件 - smtplib.SMTPException:服务器不支持 SMTP AUTH 扩展