带有SmtpStatusCode的.Net smtp发送-应在何时重试?

带有SmtpStatusCode的.Net smtp发送-应在何时重试?,.net,smtp,.net,Smtp,我有一个服务,发送电子邮件和存储在数据库中的出站电子邮件。 我正在使用.NET本机Smtp类进行电子邮件传输。我有一个错误标志,这是设置如果电子邮件未能送达 我的服务将定期检查未送达的邮件,并尝试重新发送。在什么情况下应该重试发送电子邮件?我注意到,即使电子邮件地址不正确,它也会抛出异常,但我希望我的服务丢弃任何无效的电子邮件,否则它将永远重试 基本上,我想抓住一个例外,即有一个很好的机会,电子邮件可以重新交付。我猜这只是网络错误,而不是电子邮件帐户。 以下哪个SmtpStatusCode表示值

我有一个服务,发送电子邮件和存储在数据库中的出站电子邮件。 我正在使用.NET本机Smtp类进行电子邮件传输。我有一个错误标志,这是设置如果电子邮件未能送达

我的服务将定期检查未送达的邮件,并尝试重新发送。在什么情况下应该重试发送电子邮件?我注意到,即使电子邮件地址不正确,它也会抛出异常,但我希望我的服务丢弃任何无效的电子邮件,否则它将永远重试

基本上,我想抓住一个例外,即有一个很好的机会,电子邮件可以重新交付。我猜这只是网络错误,而不是电子邮件帐户。 以下哪个SmtpStatusCode表示值得重试:


我正试图解决与你完全相同的问题。我提出的解决方案涉及大约一个小时的RFC2821,并尽可能地解释它。如果您感兴趣,可以在这里找到-

读取RFC的最大好处是
4yz
形式的代码表示一个暂时的负完成代码,这保证了重试。格式为
5yz
的代码表示永久性负完成代码,您不应重试

因此,我们的目标是筛选出有权重试和无权重试的收件人。所有
5yz
代码都可以解释为“不要重试”,552除外,某些服务器可能会错误地发送552而不是452。从那时起,您需要决定:

  • 这是一个严重的技术错误(503
    BadCommandSequence
    ),它会导致您的服务在不重试的情况下快速失败

  • 这是一个只适用于单个收件人的负永久完成代码,在这种情况下,您只需忽略有问题的收件人,然后重试发送操作
因此,我的方法是:

  • 处理
    SmtpFailedRecipientException
    SmtpFailedRecipientException
  • 将所有失败的收件人存储到列表中
  • 对于每个失败的收件人,调用我的特殊
    HandleFailedRecipient()
    方法来解释SMTP代码。如果在任何时候该方法返回
    false
    ,那么这表示一个更严重的错误,我的服务应该很快就会失败(不尝试重新发送电子邮件)
  • 否则,该方法可能重新添加收件人,也可能不重新添加收件人(取决于SMTP代码)
  • 最后,如果邮件还有剩余的收件人,请尝试重新发送
以下是我解释SMTP代码的方法:

    private bool HandleFailedRecipient(MailMessage message, string emailAddress, SmtpStatusCode statusCode, AddressType addressType)
    {            
        //Notify any event subscribers that a recipient failed and give them the SMTP code.
        RecipientFailedOnSend(this, new MailAddressEventArgs() { Address = emailAddress, AddressType = addressType, StatusCode = statusCode });

        //5yz codes typically indicate a 'Permanent Negative Completion reply', which means we should NOT keep trying to send the message.
        //The codes below can be interpreted as exceptions to the rule. In these cases we will just strip the user and try to resend.
        if (statusCode == SmtpStatusCode.MailboxUnavailable ||              //550 = "No such user"
            statusCode == SmtpStatusCode.MailboxNameNotAllowed ||           //553 = "User name ambiguous"
            statusCode == SmtpStatusCode.UserNotLocalTryAlternatePath ||    //551 = "Mail address not deliverable"
            statusCode == SmtpStatusCode.TransactionFailed)                 //554 = "Transaction failed / no valid recipients"
        {
            return true;
        }

        //The 4yz codes are 'Transient Negative Completion reply' codes, which means we should re-add the recipient and let the calling routine try again after a timeout.
        if (statusCode == SmtpStatusCode.ServiceNotAvailable ||
            statusCode == SmtpStatusCode.MailboxBusy ||
            statusCode == SmtpStatusCode.LocalErrorInProcessing ||
            statusCode == SmtpStatusCode.InsufficientStorage ||
            statusCode == SmtpStatusCode.ClientNotPermitted ||
//The ones below are 'Positive Completion reply' 2yz codes. Not likely to occur in this scenario but we will account for them anyway.
            statusCode == SmtpStatusCode.SystemStatus ||
            statusCode == SmtpStatusCode.HelpMessage ||
            statusCode == SmtpStatusCode.ServiceReady ||
            statusCode == SmtpStatusCode.ServiceClosingTransmissionChannel ||
            statusCode == SmtpStatusCode.Ok ||
            statusCode == SmtpStatusCode.UserNotLocalWillForward ||
            statusCode == SmtpStatusCode.CannotVerifyUserWillAttemptDelivery ||
            statusCode == SmtpStatusCode.StartMailInput ||
            statusCode == SmtpStatusCode.CannotVerifyUserWillAttemptDelivery ||
            //The code below (552) may be sent by some incorrect server implementations instead of 452 (InsufficientStorage).
            statusCode == SmtpStatusCode.ExceededStorageAllocation)
        {
            if ((addressType & AddressType.To) != 0)
            {
                message.To.Add(emailAddress);
            }
            if ((addressType & AddressType.CC) != 0)
            {
                message.CC.Add(emailAddress);
            }
            if ((addressType & AddressType.BCC) != 0)
            {
                message.Bcc.Add(emailAddress);
            }
            return true;
        }

        //Anything else indicates a very serious error (probably of the 5yz variety that we haven't handled yet). Tell the calling routine to fail fast.
        return false;
    }

让我知道这是否有意义,或者您是否需要查看更多代码,但从这里开始应该相对清晰。

嘿,您认为您可以在麻省理工学院下许可此代码吗?谢谢