Я пытаюсь решить ту же проблему, что и вы.Решение, которое я нашел, включало около часа заливки RFC2821 и интерпретации его как можно лучше.Если вы заинтересованы, вы можете найти его здесь - http://www.rfc -editor.org / rfc / rfc2821.txt
Большой отрыв от чтения RFC заключается в том, что коды вида4yz
указывает временный отрицательный код завершения, который требует повторной попытки.Коды вида 5yz
указывают на постоянный отрицательный код завершения, который НЕ следует повторять.
Таким образом, цель состоит в том, чтобы отфильтровать получателей, если повторная попытка оправдана, а какая - нет.Все коды 5yz
можно интерпретировать как «не повторять», за исключением 552, которые некоторые серверы могут ошибочно отправлять вместо 452. После этого вам необходимо решить:
- Является ли это серьезной технической ошибкой (503
BadCommandSequence
), которая должна привести к быстрому отказу службы без повторных попыток.
ИЛИ
- Это отрицательное постоянное завершениекод, который применяется только к одному получателю, и в этом случае вы просто оставляете данного получателя и повторяете операцию отправки.
Таким образом, мой подход такой:
- Обработка
SmtpFailedRecipientsException
и 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;
}
Дайте мне знать, если это имеет смысл или вам нужно увидеть больше кода, но это должно быть относительно ясно.