SmtpException:无法从传输连接中读取数据:net_io_connectionclosed

时间:2013-11-26 21:47:27

标签: c# smtp

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

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

22 个答案:

答案 0 :(得分:160)

编辑:Super Redux版本

尝试端口587而不是465.端口465在技术上已弃用。


经过一堆数据包嗅探后,我发现了它。首先,这是简短的回答:

.NET SmtpClient 仅支持通过STARTTLS进行加密。如果设置了EnableSsl标志,则服务器必须使用STARTTLS响应EHLO,否则将引发异常。有关详细信息,请参阅MSDN文档。

其次,为将来偶然发现此问题的人提供快速的SMTP历史课程:

当天,当服务还希望提供加密时,他们会被分配一个不同的端口号,并且在该端口号上,他们立即启动了SSL连接。随着时间的推移,他们意识到为一项服务浪费两个端口号是愚蠢的,他们设计了一种服务方式,允许使用STARTTLS在同一端口上进行明文和加密。通信将以明文开始,然后使用STARTTLS命令升级到加密连接。 STARTTLS成为SMTP加密的标准。不幸的是,由于在实施新标准时总会发生这种情况,因此存在与所有客户端和服务器兼容的大杂烩。

在我的情况下,我的用户试图将软件连接到强制立即进行SSL连接的服务器,这是Microsoft在.NET中不支持的遗留方法。

答案 1 :(得分:16)

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

答案 2 :(得分:15)

对于任何偶然发现此帖子寻找解决方案并且您已通过Azure设置SMTP sendgrid的人。

用户名不是您在azure中创建sendgrid对象时设置的用户名。要查找您的用户名;

  • 单击azure中的sendgrid对象,然后单击“管理”。您将被重定向到SendGrid站点。
  • 确认您的电子邮件,然后复制显示在那里的用户名..它是一个自动生成的用户名。
  • 将SendGrid中的用户名添加到web.config文件中的SMTP设置中。

希望这有帮助!

答案 3 :(得分:7)

您可能还需要更改不太安全的应用程序"设置您的Gmail帐户。 EnableSsl,使用端口587并启用"安全性较低的应用程序"。如果您谷歌的安全性较低的应用程序部分有谷歌帮助页面,将链接到您的帐户页面。这是我的问题,但由于上面的所有答案,现在一切正常。

答案 4 :(得分:4)

我尝试了以上所有答案,但仍然使用Office 365帐户遇到此错误。当允许使用不太安全的应用程序时,该代码似乎可以与Google帐户和smtp.gmail.com一起正常工作。

还有其他可以尝试的建议吗?

这是我正在使用的代码

(SoapFault): Authorization Required

更新以及如何解决:

通过将Smtp客户端更改为Mailkit解决了问题。由于安全性问题,现在不建议Microsoft使用System.Net.Mail Smtp客户端,而应该使用MailKit。使用Mailkit给我提供了更清晰的错误消息,我可以理解这些错误消息是找到问题(许可证问题)的根本原因。您可以通过以Nuget程序包的形式下载Mailkit。

阅读有关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 = "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);
}

答案 5 :(得分:3)

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

答案 6 :(得分:2)

如果您在同一个盒子上使用SMTP服务器并且您的SMTP绑定到IP地址而不是“任何已分配”,则可能会失败,因为它尝试使用SMTP是的IP地址(如127.0.0.1)目前没有工作。

答案 7 :(得分:1)

如果以上所有解决方案都不适合您,请尝试将以下文件更新到您的服务器(通过发布我的意思是,之前的构建会有所帮助)。

bin-> projectname.dll 

更新后,您将看到此错误。 因为我用这个解决方案解决了。

答案 8 :(得分:1)

为了提升jocull在评论中提到的内容,我正在执行此线程中提到的所有内容并删除……因为我的循环在不断地重复进行;在第一次通过循环后,有时会失败。总是在循环中第一次工作。

要清楚:循环包括创建SmtpClient,然后使用正确的数据进行发送。 SmtpClient是在try / catch块内创建的,以捕获错误并确保对象在循环底部之前被破坏。

在我的情况下,解决方案是确保SmtpClient在每次循环后都被处置(通过using()语句或通过手动处置)。即使SmtpClient对象在循环中被隐式破坏,.NET似乎也会留下东西来与下次尝试冲突。

答案 9 :(得分:1)

删除

client.UseDefaultCredentials = false; 

似乎为我解决了。

答案 10 :(得分:0)

如果您正在使用 Sendgrid 并且收到此错误,那是因为 sendgrid 不再允许基本身份验证。我们需要创建 API 密钥并将它们用作 NetworkCredential。 username="apikey" 密码将是您的 API 密钥 参考 - https://docs.sendgrid.com/for-developers/sending-email/integrating-with-the-smtp-api

答案 11 :(得分:0)

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

反正后来加了UseDefaultCredentials = false,Send()终于稳定了。 不知道为什么。

答案 12 :(得分:0)

在使用smtp.office365.com时,使用端口587和SSL时,我遇到了这个问题。我能够使用portal.office.com登录到该帐户,并且可以确认该帐户具有许可证。但是,当我触发代码发送电子邮件时,我不断收到net_io_connectionclosed错误。

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

答案 13 :(得分:0)

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

答案 14 :(得分:0)

对于我来说,Web服务器IP在邮件服务器上已被阻止,您的托管公司需要将其取消阻止并将其列入白名单。另外,使用端口587。

答案 15 :(得分:0)

将端口号从465更改为587

答案 16 :(得分:0)

在我的情况下,客户忘记在其SMTP设置中添加新的IP地址。在设置smtp的服务器中打开IIS 6.0,右键单击Smtp虚拟服务器,选择“属性”,“访问”选项卡,单击“连接”,添加新服务器的IP地址。然后单击中继,还添加新服务器的IP地址。这解决了我的问题。

答案 17 :(得分:0)

此错误非常笼统,可能是由于多种原因引起的,例如 邮件服务器不正确。 一些托管公司使用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>

答案 18 :(得分:0)

对于Outlook,请使用以下不会给我错误的设置

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

SMTP端口587

答案 19 :(得分:0)

//Try this out... Port 465 is not there anymore for use
     string emailFrom = "sender email here";
    string recieverEmail ="reciever email here";
            string subject = "subject here";
            string body = "message here";
            MailMessage maile = new MailMessage(emailFrom, recieverEmail, subject,body);
            SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
            client.Credentials = new System.Net.NetworkCredential("senders gmail account username here", "senders gmail account password here");
            client.EnableSsl = true;

答案 20 :(得分:0)

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

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

答案 21 :(得分:-1)

准备: 1. HostA是具有默认端口25的SMTP虚拟服务器 2. HostB是一个工作站,我在该工作站上使用SmtpClient发送邮件    并模拟不稳定的网络 I use clumsy

案例1 如果HostB为2008R2,则给出 当我发送电子邮件时。 然后会发生此问题。

案例2 如果HostB是2012或更高版本,则给出 当我发送电子邮件时。 然后邮件已发送出去。

结论:根本原因与Windows Server 2008R2有关。