1

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

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

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

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

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

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

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

4

2 回答 2

0

另一种可能的选择可能是涉及Microsoft Exchange Webservices。您也可以使用它们发送电子邮件。这里的例子:

// 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>
于 2017-09-14T10:45:38.987 回答
0

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

在此处输入图像描述 在此处输入图像描述

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

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

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

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

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

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

于 2017-09-13T14:30:41.177 回答