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 握手的情况下关闭连接

【讨论】:

它只是默认的.NET SmtpClient 库,它确实支持加密,服务器确实需要加密,我设置了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 &lt;httpRuntime targetFramework="4.8"/&gt;

【讨论】:

【参考方案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 扩展

我无法发送电子邮件 smtp 错误