无法从传输连接读取数据: net_io_Connectionclose

我使用 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 _ Connectionclose”。

我已经确认防火墙不是问题。端口在客户端和服务器之间打开得很好。我不确定还有什么可以抛出这个错误。

349111 次浏览

您的 SMTP 库是否支持加密连接?邮件服务器可能期望安全的 TLS 连接,因此在没有 TLS 握手的情况下关闭连接

试试这个: 这是我用来发送电子邮件给多个用户的代码。

 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;
}
}
}

编辑: 超级终极版

尝试端口587而不是465。端口465在技术上是不推荐的。


在一连串的数据包嗅探之后,我明白了。首先,这里有一个简短的答案:

那个。NET SmtpClient 只有通过 STARTTLS 支持加密。如果设置了 abc1标志,服务器必须用 STARTTLS 来响应 ehLO,否则将抛出异常。有关更多细节,请参见 MSDN文档。

其次,对于那些在未来偶然发现这个问题的人,我们简单介绍一下 SMTP 的历史经验:

回到过去,当服务还想提供加密时,它们被分配了一个不同的端口号,并且在这个端口号上,它们立即启动了 SSL 连接。随着时间的推移,他们意识到为一个服务浪费两个端口号是愚蠢的,他们为服务设计了一种方法,允许明文和加密在同一个端口使用 STARTTLS。通信将开始使用明文,然后使用 STARTTLS 命令升级到加密连接。STARTTLS 成为 SMTP 加密的标准。不幸的是,当一个新的标准被实现的时候,总是会出现与所有客户端和服务器兼容的大杂烩。

在我的例子中,我的用户试图将软件连接到一个服务器,这个服务器强制要求立即进行 SSL 连接,而 SSL 连接是微软在2010年不支持的遗留方法。NET.

将端口从465更改为587,它将工作。

你可能还需要更改 Gmail 账户上的“不太安全的应用程序”设置。EnableSsl,使用端口587并启用“不太安全的应用程序”。如果你谷歌不太安全的应用程序部分有谷歌帮助页面,将链接到您的帐户的权利页面。这是我的问题,但现在一切都工作感谢上述所有的答案。

如果您在同一个机器上使用 SMTP 服务器,并且您的 SMTP 绑定到一个 IP 地址而不是“任意分配”,那么它可能会失败,因为它正在尝试使用一个当前 SMTP 无法工作的 IP 地址(如127.0.0.1)。

对于那些无意中发现这篇文章想要寻找解决方案的人,你可以通过 Azure 设置 SMTP sendgrid

用户名不是您创建蔚蓝色 sendgrid 对象时设置的用户名。找到你的用户名;

  • 单击天蓝色的 SendGrid 对象并单击 management。您将被重定向到 SendGrid 站点。
  • 确认您的电子邮件,然后复制下来的用户名显示在那里... 这是一个自动生成的用户名。
  • 将来自 SendGrid 的用户名添加到 web.config 文件中的 SMTP 设置中。

希望这个能帮上忙!

如果以上所有的解决方案都不适合你,那么尝试更新下面的文件到你的服务器上(发布我的意思是,在那之前建立一个版本会很有帮助)。

bin-> projectname.dll

更新之后,您将看到此错误。 正如我用这个解决方案所解决的。

为了提升 jocull 在评论中提到的东西,我做了这个帖子中提到的所有事情,然后三振出局... ... 因为我的是一个循环,需要一遍又一遍地运行; 在第一次通过循环之后,它有时会失败。第一次循环的时候总是很有效。

需要说明的是: 循环包括创建 SmtpClient,然后执行。发送正确的数据。SmtpClient 是在 try/catch 块中创建的,用于捕获错误并确保对象在循环底部之前被销毁。

在我的例子中,解决方案是确保 SmtpClient 在循环中的每一次之后都被释放(通过使用()语句或者通过手动释放)。即使 SmtpClient 对象在循环中被隐式销毁,。NET 似乎正在留下的东西在周围冲突的下一次尝试。

对于前景使用后面的设置,不给我错误

SMTP 服务器名称 SMTP-mail.outlook.com

SMTP 端口587

我已经尝试了以上所有的答案,但仍然得到这个错误与 Office365帐户。这些代码在 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 客户端改为 Mailkit 解决了问题。系统。网。由于安全问题,现在不建议 Microsoft 使用 MailSmtp Client,您应该使用 MailKit。使用 Mailkit 提供了更清晰的错误消息,我可以理解找到问题的根本原因(许可证问题)。您可以通过下载作为 Nuget软件包的 Mailkit。

有关更多信息,请阅读有关 Smtp Client 的文档: Https://learn.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);
}

这个错误是非常普遍的。它可能是由于许多原因,例如 邮件服务器不正确。 一些托管公司使用 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>

准备: HostA 是具有默认端口25的 SMTP 虚拟服务器 2. HostB 是我用 SmtpClient 发送邮件的工作站 模拟不稳定网络 我用的是笨拙

案例1 假设 HostB 是2008R2 当我发邮件的时候。 然后就出现了这个问题。

案例2 假设 HostB 是2012或更高版本 当我发邮件的时候。 然后邮件就寄出去了。

结论: 此根本原因与 WindowsServer2008R2有关。

在我的例子中,客户忘记在其 SMTP 设置中添加新的 IP 地址。在设置 Smtp 的服务器中打开 IIS 6.0,右键单击 Smtp 虚拟服务器,选择 Properties,Access 选项卡,单击 Connections,添加新服务器的 IP 地址。然后单击 Relay,同时添加新服务器的 IP 地址。这解决了我的问题。

将端口号从465更改为587

移除

client.UseDefaultCredentials = false;

似乎解决了我的问题。

在我的情况下,网络服务器的 IP 被封锁在邮件服务器上,它需要被解封由您的托管公司,使其白名单。另外,使用端口端口587。

如果您的邮件服务器是 Gmail (smtp.google.com) ,当您达到消息限制时,您将得到此错误。Gmail 允许通过 SMTP 每24小时最多发送2000条消息。

我在使用带 SSL 的端口587 smtp.office365.com 时遇到了这个问题。我可以用 portal.office.com 登录到这个账户,我可以确认这个账户有许可证。但是,当我启动发送电子邮件的代码时,我不断收到 net _ io _ Connectionclose 错误。

我花了点时间才想明白但是 Exchange 管理员找到了罪魁祸首。我们使用的是 O365,但是 Exchange 服务器处于混合环境中。尽管我们尝试使用的帐户已经同步到 Azure AD,并且拥有有效的 O365许可证,但由于某种原因,邮箱仍然驻留在混合 Exchange 服务器上,而不是在线 Exchange。在交换管理员使用“ Move-Mailbox”命令将邮箱从混合交换服务器移动到 O365之后,我们可以使用该代码使用 o365发送电子邮件。

我最初的问题是关于间歇性发送故障。例如,第一次 Send()成功,第二次 Send()失败,第三次 Send()成功。起初我以为我没有处理好。所以我求助于 using()

不管怎样,后来我添加了 UseDefaultCredentials = false,Send ()最终变得稳定了。 不知道为什么。

如果您正在使用 Sendgrid,并且收到了这个错误,那是因为 Sendgrid 不再允许基本身份验证。我们需要创建 API 密钥并将它们用作 NetworkCredential。Username = “ apikey”密码将是您的 API 密钥 参考文献—— ref = “ https://docs.sendgrid.com/for-developers/send-email/Integration-with-the-smtp-api”rel = “ nofollow norefrer”> https://docs.sendgrid.com/for-developers/sending-email/integrating-with-the-smtp-api

OutlookMailer 的特定答案

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 - > 按邮件流程

- > Check-打开旧的 TLS 客户端的使用

- > 保存

enter image description here

我也有同样的问题。NET smtp client + 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机器上重现并修复的)

把这个放在方法的开头为我修复了这个问题

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12

我最近不得不在我们所有的应用程序上设置新的邮件设置,并且在多个项目中遇到了这个错误。

对我来说,解决方案是在我的一些项目中将目标框架更新为更新的版本。

我还有一个 ASP.net 网站项目,更新目标框架是不够的,我还必须添加以下代码到 web.config <httpRuntime targetFramework="4.8"/>

无法从传输连接读取数据: net _ io _ Connectionclose

有两种解决方案。第一个解决方案针对应用程序级(需要部署) ,第二个解决方案针对机器级(特别是如果您使用开箱即用/现成的应用程序)

当我们检查异常时,我们看到协议是“ ssl | tls”非格式化对。

因为我们不想部署,所以我们更喜欢机器级别的更改(解决方案2)。

8月18日,微软宣布,他们将在“2022年”禁用到 Exchange Online 的传输层安全(TLS)1.0和1.1连接 Https://office365itpros.com/2021/08/19/exchange-online-to-introduce-legacy-smtp-endpoint-in-2022/

首先让我们检查一下网络(任何阻止您发送电子邮件请求的东西? 防火墙、 IDS 等等)

通过使用 PowerShell 检查传输层安全协议

[Net.ServicePointManager]::SecurityProtocol

我的输出 : Tls,Tls11,Tls12

在 TLS 上测试 SMTP 身份验证

$HostName = [System.Net.DNS]::GetHostByName($Null).HostName
$Message = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient("smtp.office365.com", 587)
$smtp.Credentials = New-Object System.Net.NetworkCredential("me@me.com", "PassMeme");
$smtp.EnableSsl = $true
$smtp.Timeout = 400000
$Message.From = "sender@me.com"
$Message.Subject = $HostName + " PowerShell Email Test"
$Message.Body = "Email Body Message"
$Message.To.Add("receiver@me.com")
#$Message.Attachments.Add("C:\foo\attach.txt")
$smtp.Send($Message)

我的输出: 没有错误消息 如果您的输出中有任何消息,那么您的电子邮件发送请求就会受到阻碍。

如果一切正常,应该有两种解决方案。

解决方案1:

应用程序级 TLS 1.2配置(可选) 需要应用程序部署。

在 C # 或 VB 代码中明确选择 TLS:

ServicePointManager.SecurityProtocol |=  SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
System.Net.ServicePointManager.SecurityProtocol = System.Net.ServicePointManager.SecurityProtocol Or SecurityProtocolType.Tls11 Or SecurityProtocolType.Tls12

解决方案2:

机器级 TLS 1.2. NET Framework 配置 不需要应用程序部署。

将 SchUseStrongCrypto 注册表设置为 DWORD: 0000001。应该重新启动服务器。

对于32位系统上的32位应用程序或64位系统上的64位应用程序,更新以下子密钥值:

HKEY_LOCAL_MACHINE\SOFTWARE\
\Microsoft\.NETFramework\\<version>
SchUseStrongCrypto = (DWORD): 00000001

对于在基于 x64的系统上运行的32位应用程序,请更新以下子键值:

HKEY_LOCAL_MACHINE\SOFTWARE\
Wow6432Node\Microsoft\\.NETFramework\\<version>
SchUseStrongCrypto = (DWORD): 00000001

有关“如何在客户端启用 TLS 1.2”的详细信息,请访问 Https://learn.microsoft.com/en-us/mem/configmgr/core/plan-design/security/enable-tls-1-2-client

我们的电子邮件服务是 Azure SendGrid。 有一天,我们的应用程序停止发送电子邮件,错误消息是“ SmtpException: 无法从传输连接接收数据: netio 连接关闭。”我们发现问题是由于我们的 Pro 300K 订阅用完了。当我们增加订阅量时,电子邮件开始发送。

我的.NET 应用程序也面临着同样的问题。

问题: 我使用的.NET 版本是4.0,它创建了整个混乱。

原因: 这个问题背后的全部原因是微软已经取消了对 TLS 1.0和 TLS 1.1的支持。NET 框架比4.6。

FIX: 您只需要将.NET 框架版本更新到4.6或更高版本来解决这个问题。

首次使用端口 = 587

通常需要 STARTTLS 来发送邮件,添加安全协议 Tls12将有助于解决这个问题。

然后使用 Powershell 对 stmp 连接进行测试

$userName = 'username_here'
$password = 'xxxxxxxxx'
$pwdSecureString = ConvertTo-SecureString -Force -AsPlainText $password
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $userName, $pwdSecureString


$sendMailParams = @{
From = 'abc.com'
To = 'xyz@gmail.com'
Subject = 'Test SMTP'
Body = 'Test SMTP'
SMTPServer = 'smtp.server.com'
Port = 587
UseSsl = $true
Credential = $credential
}


Send-MailMessage @sendMailParams


第三,如果发送电子邮件,在 SmtpClient 函数中添加以下代码:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

更新项目的.NETFramework 目标为我解决了这个问题。

下面是为我工作的代码

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;


// Create the email object first, then add the properties.
SmtpClient client = new SmtpClient()
{
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
//Set Credentials
UseDefaultCredentials = false,
Credentials = new NetworkCredential(_username, _password),
Host = "smtp.office365.com"
};
client.Send(mail);

我已经找到了这个问题的最终答案。我在这个错误上花了大约一个星期的时间,找到了一个用 smtp 修复这个问题的 nuget 包。您可以使用 MailKit nugt 并使用它。要学习如何使用它,你可以只谷歌它的名称,你会发现一个 github 存储库,他解释完全在自述文件。

自2022年1月22日以来,Google 已经提高了 TLS 版本要求。同时,微软已经取消了对 TLS 1.0和 TLS 1.1的支持。NET 框架比4.6。

因此,我们可以解决以下两个解决方案之一的问题。

1.在创建 smtp 客户端 > > ServicePointManager 之前添加一些其他协议。SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

2. 只需要将.NET 框架版本更新到4.6或更高版本,就可以解决这个问题。