亚马逊SES停止工作

16
我设置了亚马逊SES,最初几个小时它能正常工作,但突然停止了。发送的所有电子邮件和我们的域名都已经得到验证。我们不会发送大量的电子邮件 - 每天仅有几百封。每当我对web.config进行更改时,似乎都可以让它再次工作2-3小时。例如,它停止工作,所以我将端口587切换到25,然后它开始工作了2-3个小时,然后停止了。然后我又切换回587,同样的事情发生了。一旦它停止工作,就不会自动重新启动。它正在运行两台负载均衡服务器上,asp.net框架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)

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

3个回答

25

听起来确实是个棘手的问题 - 我不完全确定,但你似乎忘记释放SMTP客户端,而这在更改为VPC实例后发送电子邮件通常非常缓慢中已经提到,会导致你看到的错误:

当我没有释放SmtpClient时,我得到了错误...

'Service not available, closing transmission channel. The server response was: Timeout waiting for data from client.'

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

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

因此,一个合适的模式应该是使用using语句,如入门指南Amazon SES和.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,由于通常暗示着发送限制,我强烈建议避免使用该端口。请见下面的 附录 以获取有关相关亚马逊EC2限制的详细信息。
祝你好运!

附录

亚马逊EC2上的25号端口限制

您可能已经意识到这一点(我实际上不认为这是一个问题),但是亚马逊EC2 对通过端口25发送的电子邮件施加默认的发送限制,并在您试图超过这些限制时限制出站连接,即使使用Amazon SES 也同样适用,请参阅Amazon SES SMTP Issues

您从Amazon EC2实例通过端口25发送到Amazon SES, 而您无法达到Amazon SES的发送限制或者您正在接收超时错误 — Amazon SES EC2 对 通过端口25发送的电子邮件施加默认的发送限制,并在您试图超过这些限制时限制出站连接。要去除这些限制,请提交一个请求,以去除电子邮件发送限制。您还可以通过端口465或端口587连接到 Amazon SES,这两个端口都没有被限制。

因此,在您的测试/切换方案中我会删除端口25,并仅使用端口465/587以避免错误(正如引用所述,您也可以请求去除这个限制,但需要几个小时,而且最好一开始就避免使用端口25)- 确实有点不幸,一些官方Amazon SES示例在使用端口25时甚至没有提到这个容易触发的问题。


2
谢谢回复,我会切换到端口587。我同意这似乎是一个连接重置问题,但在2.0框架中SmtpClient实际上不是可处理的。也许这就是问题所在,如果是这样,我需要找到一个解决方法。 - StronglyTyped
2
由于我们无法及时使其正常工作,不得不放弃亚马逊的解决方案。我将此标记为答案,因为我认为这些解决方案可能会解决其他人可能遇到的问题。微软Exchange增加了它们的发送限制,所以我们现在使用它们 - 之前,它们设置得太低,这就是为什么我们探索亚马逊选项的原因。 - StronglyTyped
3
我遇到了完全相同的问题,即使我使用的是 .Net 4,我也不知道 SmtpClient 现在可以被处理。一旦我改用 using 语句,一切都开始更加顺畅。很好的发现! - Scott Salyer
释放SmtpClient也对我有用。我以为我们可以在该对象上使用相当长的生命周期,但实际上它看起来应该是相当短的。 - heneryville

2
尽管此问题特定于 .NET v2.0,但我最近在 .NET v4.5 上也遇到了此问题。即使在 SMTP 客户端周围添加了 "using"(如早期帖子中建议的那样),我仍然会间歇性地收到此错误。经过多个小时的研究,我发现 AWS 支持 STARTTLS 端口(2587; http://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-connect.html),并且在微软的非常小的字体中,当 SMTP 客户端的 "EnableSsl" 设为 true 时,客户端会期望一个 STARTTLS 会话 (https://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.enablessl(v=vs.110).aspx)。因此,在将我的端口更新为 2587将 SmtpClient 包含在 "using {}" 中之后,我成功发送了约 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 客户端的真正配置情况,因此这还有些间接性。


0

我也在使用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

Hope this works for you.


1
你的代码与我的唯一区别是:enableSsl="true"。该属性在我使用的框架 v2.0 的配置中不受支持,但是你可以看到它被添加到我的 c# 代码中初始化 SmtpClient 对象时。 - StronglyTyped

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接