【问题标题】:How do deal with SMTP timeouts如何处理 SMTP 超时
【发布时间】:2018-02-22 02:30:19
【问题描述】:

我正在使用用 C# 编写的客户端应用程序向公司交换服务器发送大量电子邮件。

客户端应用程序超时(而不是服务器)可能会发生,并且确实如此。 由于无法知道服务器是否完成了请求,这种情况下如何处理重试?

没有涉及可用于避免重复的 ID。 设置长时间超时甚至无限超时都不是一个好策略。

我正在使用指数退避算法进行重试。在这种情况下,它应该只发送一个副本,因为下次它会等待更长的时间。

我认为没有子弹教授解决方案。无论如何,由于它是此类项目的第一个项目,我需要检查是否有人有我想念的解决方案。

更新: 交易所正在做中继。我正在使用 SmtpClient 发送电子邮件。 问题是服务器可以发送 250 Ok 消息,但接收方始终没有收到,然后重试。这是我在这篇文章中试图解决的唯一问题。

在 Rest 服务中,推荐的方法是使用并发错误。如果客户端发布某些内容并获得“409 - 冲突”状态,则表示该消息已存储在服务器上。但是为了让这种情况发生在那里,它是由客户端创建的消息的密钥,并且是消息的一部分。 SMTP 似乎没有可以防止这种情况发生的机制。

【问题讨论】:

  • 你找到合理的解决方案了吗?
  • 没有。我不能保证没有重复。无论如何,到目前为止,使用指数退避策略似乎可以正常工作。我不知道有任何重复。将超时值设置得越高,就会越不喜欢它。这就是路的尽头。

标签: error-handling smtp exchange-server connection-timeout retrypolicy


【解决方案1】:

在使用标准 SMTP 时,通常 SMTP 服务器会向您提供他是否接受电子邮件的信息。下面是一个通过 telnet 的例子:

因此,您的应用程序只需要在此处跟踪响应,如果发生超时,您无需继续处理所有电子邮件,而需要从停止的地方继续。顺便说一句,您的应用程序应该在每次响应时检查发送方或接收方可能不被接受...

RFC 5321 中提到了这一点(您可以在该文档中滚动):

当接收者-SMTP 接受一封邮件时(通过发送“250 OK”消息以响应 DATA),它正在承担责任 用于传递或中继消息。它必须采取这个 认真负责。它不能丢失消息 琐碎的原因,例如因为主机后来崩溃或 因为可以预见的资源短缺。 [...] 成功接收并存储文本结尾后,SMTP 接收器会发送“250 OK”回复。

当您发送电子邮件时,我认为第 4.5.4.1 节。如果您不使用某种框架来处理符合 RFC 的外发电子邮件,这可能很重要。

示例:您的客户正在生成一封电子邮件,但在从正文提交期间(电子邮件传输的最后一部分)连接断开。然后不允许服务器继续发送电子邮件。从技术上讲,他可能会获得所有信息,但 RFC 不允许他将其发送出去,因为客户端超时并且没有完成整个过程。

更新: 最好的方法是使用C# SmtpClient method,然后检查smtpStatusCode OK(=“电子邮件已成功发送到 SMTP 服务。”),您也可以在 telnet 示例中看到。该方法在这里(技术上)没有做任何其他事情。该方法也符合 RFC 5321,因此您无需重新发明 smtp 发送轮。如果您在此期间未获得 OK,则可能发生了某些事情,您需要检查结果然后执行重新发送(或者如果错误消息表明电子邮件地址无效或需要放弃,或者类似的东西以避免无限循环)。

【讨论】:

  • 我不明白。如果客户端超时,则意味着客户端放弃等待服务器响应,因此他无法知道请求的结果是什么,因为他不会监听。例如:如果通讯中断,服务器将继续进行到最后,但客户端不会收到应答。另一个例子,服务器很忙,所以它在 31 秒后处理了请求,但客户端在 30 秒后放弃了。
  • 这很简单:那些日子的每个 SMTP 服务器都必须遵循 RFC 5321 请注意您可以在该 URL 上滚动您的应用程序必须符合 RFC 5321 否则您将发送多封电子邮件。这意味着如果进程在中间被切断,服务器将无法继续处理电子邮件,它将根本无法工作并且违反 RFC 5321。这意味着如果您的应用程序获得 RFC 中提到的 250 OK,那么电子邮件被远程服务器接受。如果没有,必须重新发送。
  • 我不确定我们是否在同一页面上。 Microsoft 交换服务器配置为为我中继消息,因此该服务器应确保 RFC 5321。我是否需要以任何方式遵守 RFC 5321?我一次发送一条消息,提前检查结果。如果出现错误,我会重试 5 次,这就是我最初的问题所在。如果我有超时,如何继续。
  • 您充当 SMTP 客户端,因此需要遵守 RFC 5321 以及您是发件人。为什么不使用 C# 中可以处理 timeouts and exceptionsSmtpClient 方法?然后您应该能够发现问题并执行重试。然后您可以在我之前提到的 SMTPStatusCode here 中检查 250 OK。
  • 我正在使用 SmtpClient 并处理异常。底线是,服务器可以发送 OK 消息,但客户端由于我们的其他原因从未收到。在 Rest 服务中,推荐的方法是使用并发错误。如果客户端发布某些内容并获得“409 - 冲突”状态,则表示该消息已存储在服务器上。但要做到这一点,需要有一个由客户端创建的消息的密钥,它是消息的一部分。所以,我仍然不明白如何正确处理超时。
【解决方案2】:

另一个可能的选择可能是涉及Microsoft Exchange Webservices。您也可以使用它们发送电子邮件。来自here的示例:

// Create an email message and identify the Exchange service.
EmailMessage message = new EmailMessage(service);

// Add properties to the email message.
message.Subject = "Interesting";
message.Body = "The merger is finalized.";
message.ToRecipients.Add("user1@contoso.com");

// Send the email message and save a copy.
message.SendAndSaveCopy();

他们也会给你回复:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <h:ServerVersionInfo MajorVersion="14" 
               MinorVersion="0" 
               MajorBuildNumber="639" 
               MinorBuildNumber="20" 
               Version="Exchange2010" 
               xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types" 
               xmlns="http://schemas.microsoft.com/exchange/services/2006/types" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xm=""lns:xsd="http://www.w3.org/2001/XMLSchema" />
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <m:CreateItemResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" 
               xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
      <m:ResponseMessages>
        <m:CreateItemResponseMessage ResponseClass="Success">
          <m:ResponseCode>NoError</m:ResponseCode>
          <m:Items />
        </m:CreateItemResponseMessage>
      </m:ResponseMessages>
    </m:CreateItemResponse>
  </s:Body>
</s:Envelope>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-03
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多