Я пытаюсь обобщить результаты System.Net.Mail.SmtpClient.Send, используя перечисление. Это делается для того, чтобы я знал, следует ли мне повторить попытку отправки электронной почты и, надеюсь, предотвратить отправку дубликатов электронных писем.

public enum MailSendStatus {
    None,
    Sent,
    ErrorCannotSend,
    TryAgain,
    SentMaybe
}

Я перехватил все исключения из Send и выделил SmtpException.StatusCode из http://msdn.microsoft.com/en-us/library/system.net.mail.smtpstatuscode(v=vs.80).aspx< /а>. Развал выглядит правильно? Или есть лучший способ сделать это?

try {
    smtp.Send(msg);
} catch (ArgumentNullException e) {
    return MailSendStatus.ErrorCannotSend;
} catch (ObjectDisposedException e) {
    return MailSendStatus.ErrorCannotSend;
} catch (InvalidOperationException e) {
    return MailSendStatus.ErrorCannotSend;
} catch (SmtpFailedRecipientsException e) {
    return MailSendStatus.ErrorCannotSend;
} catch (SmtpException e) {
    switch(e.StatusCode) {
        case SmtpStatusCode.BadCommandSequence:
        case SmtpStatusCode.MailboxNameNotAllowed:
        case SmtpStatusCode.HelpMessage:
        case SmtpStatusCode.SyntaxError:
        case SmtpStatusCode.SystemStatus:
            return MailSendStatus.ErrorCannotSend;
        case SmtpStatusCode.CannotVerifyUserWillAttemptDelivery:
        case SmtpStatusCode.UserNotLocalWillForward:
            return MailSendStatus.SentMaybe;
        case SmtpStatusCode.ClientNotPermitted:
        case SmtpStatusCode.CommandNotImplemented:
        case SmtpStatusCode.CommandParameterNotImplemented:
        case SmtpStatusCode.CommandUnrecognized:
        case SmtpStatusCode.ExceededStorageAllocation:
        case SmtpStatusCode.GeneralFailure:
        case SmtpStatusCode.InsufficientStorage:
        case SmtpStatusCode.LocalErrorInProcessing:
        case SmtpStatusCode.MailboxBusy:
        case SmtpStatusCode.MailboxUnavailable:
        case SmtpStatusCode.MustIssueStartTlsFirst:
        case SmtpStatusCode.ServiceClosingTransmissionChannel:
        case SmtpStatusCode.ServiceNotAvailable:
        case SmtpStatusCode.ServiceReady:
        case SmtpStatusCode.StartMailInput:
        case SmtpStatusCode.TransactionFailed:
        case SmtpStatusCode.UserNotLocalTryAlternatePath:
            return MailSendStatus.TryAgain;
        case SmtpStatusCode.Ok:
            break;
    }
} catch (Exception e) { 
    return MailSendStatus.SentMaybe;
}
return MailSendStatus.Sent;
3
djeeg 14 Апр 2011 в 09:35
Здесь есть несколько случаев, с которыми я не совсем согласен. Например, я думаю, что SmtpStatusCode.CommandUnrecognized указывает на то, что smtp-сервер или клиент обмениваются данными несовместимым образом, который нельзя исправить повторной попыткой.
 – 
Kelly Elton
8 Мар 2019 в 19:34

1 ответ

catch (ArgumentNullException e) {    return MailSendStatus.ErrorCannotSend;} catch 
(ObjectDisposedException e) {    return MailSendStatus.ErrorCannotSend;} catch 
(InvalidOperationException e) {    return MailSendStatus.ErrorCannotSend;

Мне это не нравится. ArgumentNull, ObjectDisposed — ошибки программирования (как и InvalidOperation). Вы не должны разбивать их на ошибку SMTP, а исправлять их. Для этого сбой программы — это хорошо (и вывод трассировки стека). Подход «быстро ошибаться». Не повторяйте исключения, которые вы не знаете, как обрабатывать, а InvalidOperationException, ObjectDisposedException указывают на то, что что-то не так с состоянием, ArbumentNullException — это ошибка использования/пользовательского интерфейса.

2
Oded 14 Апр 2011 в 09:48
Я опустил операторы журнала для ясности, но да, в основном они должны быть обнаружены в процессе разработки. Я только что включил все исключения на страницу msdn msdn.microsoft.com/en- нас/библиотека/swas0fwc.aspx
 – 
djeeg
14 Апр 2011 в 09:45
Мне это не нравится. Действительно. Проблема в том, что очень трудно поймать настоящую почку ниже. Я никогда не скрываю внутренние ошибки и хочу, чтобы они были как можно более заметными для быстрой очистки.
 – 
TomTom
14 Апр 2011 в 09:46
Если я удалю эти случаи из дерева улавливания, сработает универсальный (Exception e), возвращающий код состояния "возможно, отправлено", что неверно, это определенно была ошибка, я полагаю, что мог бы повторно выдать исключение
 – 
djeeg
14 Апр 2011 в 09:53
Ах да и нет. У меня НИКОГДА (применяются некоторые исключения) нет НИКАКИХ общих обработчиков исключений. Если я не ожидаю исключения, приложение лучше не работает. Исключение - это ПОЧТИ интерфейс для внешней библиотеки, где я могу регистрировать их в обработчике исключений. Идея в том, что вы не поймаете исключение, с которым не знаете, как поступить, а неизвестные исключения как раз и являются такими исключениями.
 – 
TomTom
14 Апр 2011 в 10:52