【问题标题】:Amazon SES Stops WorkingAmazon SES 停止工作
【发布时间】:2013-01-11 20:38:48
【问题描述】:

我设置了 Amazon SES,它最初工作了几个小时,然后突然停止了。我发送的所有电子邮件以及我们的域都已通过验证。我们不会发送大量电子邮件 - 每天只有几百封。每当我对 web.config 进行更改时,它似乎允许它再次工作 2-3 小时。例如,它停止工作,所以我将端口 587 切换到 25,它开始工作 2-3 小时,然后停止。然后我切换回587,同样的事情发生了。一旦它停止工作,它似乎永远不会自行重新开始。它运行在两台负载平衡服务器上,asp.net framework v2.0、IIS 7.5。这是我正在使用的代码:

web.config:

<system.net>
  <mailSettings>
    <smtp deliveryMethod="Network" from="no-reply@ourdomain.com">
      <network defaultCredentials="false" host="email-smtp.us-east-1.amazonaws.com" userName="***" password="***" port="587" />
    </smtp>
  </mailSettings>
</system.net>

c#代码:

var smtpClient = new SmtpClient() { EnableSsl = true };

var mailMessage =
    new MailMessage(fromAddress, toAddress, subject, body)
    {
        IsBodyHtml = true
    };

smtpClient.Send(mailMessage);

这是我收到的两个错误:

The following exception was thrown by the web event provider '(null)' in the application '/' (in an application lifetime a maximum of one exception will be logged per provider instance):

System.Web.HttpException: Unable to send out an e-mail to the SMTP server. Please ensure that the server specified in the <smtpMail> section is valid. ---> System.Net.Mail.SmtpException: Failure sending mail. ---> System.IO.IOException: Received an unexpected EOF or 0 bytes from the transport stream.
   at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
   at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.Mail.SmtpConnection.Flush()
   at System.Net.Mail.ReadLinesCommand.Send(SmtpConnection conn)
   at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   --- End of inner exception stack trace ---
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   at System.Web.Management.MailWebEventProvider.SendMail(MailMessage msg)
   --- End of inner exception stack trace ---
   at System.Web.Management.MailWebEventProvider.SendMail(MailMessage msg)
   at System.Web.Management.SimpleMailWebEventProvider.SendMessageInternal(WebBaseEventCollection events, Int32 notificationSequence, Int32 begin, DateTime lastFlush, Int32 discardedSinceLastFlush, Int32 eventsInBuffer, Int32 messageSequence, Int32 messagesInNotification, Int32 eventsInNotification, Int32 eventsLostDueToMessageLimit)
   at System.Web.Management.SimpleMailWebEventProvider.SendMessage(WebBaseEvent eventRaised)
   at *****.Global.SimpleMailWithSslWebEventProvider.ProcessEvent(WebBaseEvent raisedEvent)
   at System.Web.Management.WebBaseEvent.RaiseInternal(WebBaseEvent eventRaised, ArrayList firingRuleInfos, Int32 index0, Int32 index1)

The following exception was thrown by the web event provider '(null)' in the application '/' (in an application lifetime a maximum of one exception will be logged per provider instance):

System.Web.HttpException: Unable to send out an e-mail to the SMTP server. Please ensure that the server specified in the <smtpMail> section is valid. ---> System.Net.Mail.SmtpException: Service not available, closing transmission channel. The server response was: Timeout waiting for data from client.
   at System.Net.Mail.MailCommand.CheckResponse(SmtpStatusCode statusCode, String response)
   at System.Net.Mail.SmtpTransport.SendMail(MailAddress sender, MailAddressCollection recipients, String deliveryNotify, SmtpFailedRecipientException& exception)
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   at System.Web.Management.MailWebEventProvider.SendMail(MailMessage msg)
   --- End of inner exception stack trace ---
   at System.Web.Management.MailWebEventProvider.SendMail(MailMessage msg)
   at System.Web.Management.SimpleMailWebEventProvider.SendMessageInternal(WebBaseEventCollection events, Int32 notificationSequence, Int32 begin, DateTime lastFlush, Int32 discardedSinceLastFlush, Int32 eventsInBuffer, Int32 messageSequence, Int32 messagesInNotification, Int32 eventsInNotification, Int32 eventsLostDueToMessageLimit)
   at System.Web.Management.SimpleMailWebEventProvider.SendMessage(WebBaseEvent eventRaised)
   at *****.Global.SimpleMailWithSslWebEventProvider.ProcessEvent(WebBaseEvent raisedEvent)
   at System.Web.Management.WebBaseEvent.RaiseInternal(WebBaseEvent eventRaised, ArrayList firingRuleInfos, Int32 index0, Int32 index1)

我试图在亚马逊论坛上寻求帮助,但没有任何运气。似乎有什么东西干扰了连接,但我不知道是什么。有任何想法吗?谢谢。

【问题讨论】:

    标签: asp.net amazon-web-services smtp amazon-ses


    【解决方案1】:

    虽然这个问题是 .NET v2.0 特有的,但我最近在 .NET v4.5 上也遇到了这个问题。即使在添加了 using around SMTP client(如之前的帖子中所建议的那样)之后,我仍然间歇性地收到此错误。经过数小时的研究,我发现了 AWS 对 STARTTLS 端口(2587;http://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-connect.html)的支持,并且在非常精美的字样中,Microsoft 声明当 SMTP 客户端上的“EnableSsl”为真时,客户端需要一个 STARTTLS 会话(https://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.enablessl(v=vs.110).aspx) .因此,在将我的端口更新为 2587 将 SmtpClient 包围在“使用 {}”中后,我能够成功发送大约 20k 封电子邮件而不会重现错误。

    因此,工作配置将是:

    <system.net>
      <mailSettings>
        <smtp deliveryMethod="Network">
          <network host="email-smtp.us-west-2.amazonaws.com" port="2587" enableSsl="true" password="password" />
        </smtp>
      </mailSettings>
    </system.net>
    

    一个免责声明是,我仍然不完全了解 AWS 或 .NET SMTP 客户端的真实配置,所以这仍然有点间接。

    【讨论】:

      【解决方案2】:

      这听起来确实是一个棘手的问题 - 我对此不是 100% 肯定,但您似乎错过了处置 SMTP 客户端,Sending email is often very slow after changing to VPC instance 中提到会导致您看到的错误:

      当我不处理 SmtpClient 时,我收到错误...

      '服务不可用,正在关闭传输通道。服务器 响应是:等待来自客户端的数据超时。'

      这实际上是对间歇性问题的一个很好的解释,即根据执行的代码路径,此问题可能会触发与Amazon SES 的 SMTP 连接挂起,这显然可以通过切换到另一个端口来解决,这意味着连接被重置- 这也是SmtpClient.Dispose Method 所确保的:

      向 SMTP 服务器发送 QUIT 消息,优雅地结束 TCP 连接,并释放当前实例使用的所有资源 SmtpClient 类。

      因此,适当的模式是促进using Statement,如Getting Started with Amazon SES and .NET 所示:

        String username = "SMTP-USERNAME";  // Replace with your SMTP username.
        String password = "SMTP-PASSWORD";  // Replace with your SMTP password.
        String host = "email-smtp.us-east-1.amazonaws.com";
        int port = 25;
      
        using (var client = new System.Net.Mail.SmtpClient(host, port))
        {
          client.Credentials = new System.Net.NetworkCredential(username, password);
          client.EnableSsl = true;
      
          client.Send
          (
                    "FROM@EXAMPLE.COM",  // Replace with the sender address.
                    "TO@EXAMPLE.COM",    // Replace with the recipient address.
                    "Testing Amazon SES through SMTP",              
                    "This email was delivered through Amazon SES via the SMTP end point."
          );
        }
      

      请注意,该示例使用端口 25,由于通常隐含的发送限制,我强烈建议您避免使用该端口,有关各个 Amazon EC2 限制的详细信息,请参阅下面的附录

      祝你好运!


      附录

      Amazon EC2 在端口 25 上节流

      您可能知道这一点(实际上我认为这不是问题),但Amazon EC2 对通过端口 25 发送的电子邮件施加默认发送限制,如果您尝试超过这些限制,则会限制出站连接限制 在使用Amazon SES 时仍然适用,请参阅Amazon SES SMTP Issues

      您正在通过端口 25 从 Amazon EC2 实例发送到 Amazon SES 并且您无法达到您的 Amazon SES 发送限制,或者您正在 接收超时 — Amazon SES EC2 对 通过端口 25 发送的电子邮件并限制出站连接,如果您 试图超越这些限制。要取消这些限制,请提交 Request to Remove Email Sending Limitations。您还可以连接到 Amazon SES 通过端口 465 或端口 587,这两个端口都没有受到限制。

      因此,我会从您的测试/切换方案中删除端口 25,而仅使用端口 465/587 以避免虚假线索(如引用的那样,您也可以请求删除此限制,但这需要几个小时,似乎最好首先避免使用端口 25)- 有点不幸的是,几个官方的 Amazon SES 示例都在使用端口 25,甚至没有提及这个容易触发的问题。

      【讨论】:

      • 感谢回复,我会切换到587端口。我同意这似乎是一个连接重置问题,但SmtpClient在2.0框架中实际上不是一次性的。也许这就是问题所在,在这种情况下,我需要找到解决办法。
      • 不得不放弃亚马逊解决方案,因为我们无法使其及时工作。我将此标记为答案,因为我认为这些解决方案可能会解决其他人可能遇到的问题。 Microsoft Exchange 提高了它们的发送限制,因此我们改为使用它们 - 以前,它们设置得太低,这就是我们探索亚马逊选项的原因。
      • 我遇到了同样的问题,即使我在 .Net 4 上,我也不知道 SmtpClient 现在是一次性的。一旦我切换到 using 语句,一切都开始变得更加顺畅。很好的发现!
      • 处理 SmtpClient 也使这项工作对我有用。我认为我们可以在该对象上使用相当长的生命周期,但它看起来应该很短。
      【解决方案3】:

      我也在使用 AWS ses 服务

       smtp deliveryMethod="Network" from="XXXXXXX@ZXXX.com"
          network enableSsl="true" host="email-smtp.us-east-1.amazonaws.com" userName="******" password="*********" port="25" 
       smtp
      

      希望这对你有用。

      【讨论】:

      • 您的代码与我的唯一区别是:enableSsl="true"。我正在使用的框架 v2.0 的配置中不支持该属性,但是您可以看到它是在我的 C# 代码中初始化 SmtpClient 对象时添加的。
      猜你喜欢
      • 1970-01-01
      • 2014-06-09
      • 2017-07-14
      • 2011-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-27
      相关资源
      最近更新 更多