Asp.net

Amazon SES 停止工作

  • October 20, 2015

我設置了 Amazon SES,它最初工作了幾個小時,然後突然停止了。我發送的所有電子郵件以及我們的域都已通過驗證。我們不會發送大量電子郵件 - 每天只有幾百封。每當我對 web.config 進行更改時,它似乎允許它再次工作 2-3 小時。例如,它停止工作,所以我將埠 587 切換到 25,它開始工作 2-3 小時,然後停止。然後我切換回587,同樣的事情發生了。一旦它停止工作,它似乎永遠不會自行重新開始。它執行在兩台負載平衡伺服器上,asp.net framework v2.0、IIS 7.5。這是我正在使用的程式碼:

網路配置:

<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)

我試圖在亞馬遜論壇上尋求幫助,但沒有任何運氣。似乎有什麼東西干擾了連接,但我不知道是什麼。有任何想法嗎?謝謝。

這聽起來確實是一個棘手的問題 - 我對此不是 100% 肯定,但您似乎錯過了處理 SMTP 客戶端,在更改為 VPC 實例後發送電子郵件通常很慢中提到,這會導致您遇到的錯誤看到:

當我不處理 SmtpClient 時,我收到錯誤…

‘服務不可用,正在關閉傳輸通道。伺服器響應是:超時等待來自客戶端的數據。

這實際上是對間歇性問題的一個很好的解釋,即根據執行的程式碼路徑,此問題可能會觸發與Amazon SES的 SMTP 連接掛起,這顯然可以通過切換到另一個埠來解決,這意味著連接被重置 - 這就是SmtpClient.Dispose 方法也確保:

向 SMTP 伺服器發送 QUIT 消息,優雅地結束 TCP 連接,並釋放SmtpClient類的目前實例使用的所有資源。

因此,適當的模式是促進using Statement,如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,由於通常隱含的發送限制,我強烈建議您避免使用該埠,有關各個 Amazon EC2 限制的詳細資訊,請參閱下面的附錄。

祝你好運!


附錄

Amazon EC2 在埠 25 上進行節流

您可能已經意識到這一點(實際上我認為這不是問題),但是Amazon EC2 對通過埠 25 發送的電子郵件施加了預設發送限制,如果您嘗試超過使用Amazon時仍然適用的限制,則會限制出站連接SES,請參閱Amazon SES SMTP 問題

您正在通過埠 25 從 Amazon EC2 實例發送到 Amazon SES,但您無法達到您的 Amazon SES 發送限製或您收到超時- Amazon SES EC2 對通過埠 25 發送的電子郵件施加預設發送限制,如果您嘗試,則會限制出站連接超過這些限制。要刪除這些限制,請送出 刪除電子郵件發送限制的請求。您還可以通過埠 465 或埠 587 連接到 Amazon SES,這兩個埠都不受限制。

因此,我會從您的測試/切換場景中刪除埠 25 並僅使用埠 465/587 以避免錯誤的線索(如引用的那樣,您也可以請求刪除此限制,但這需要幾個小時和埠 25 似乎首先最好避免使用)- 有點不幸的是,幾個官方的 Amazon SES 範例正在使用埠 25,甚至沒有提及這個容易觸發的問題。

引用自:https://stackoverflow.com/questions/14563200