C# 正在确定System.Net.Mail.SmtpClient.Send结果

C# 正在确定System.Net.Mail.SmtpClient.Send结果,c#,exception-handling,sendmail,C#,Exception Handling,Sendmail,我试图使用枚举总结System.Net.Mail.SmtpClient.Send的结果。这就是为什么我知道我是否应该重试发送电子邮件,并希望防止发送重复的电子邮件 public enum MailSendStatus { None, Sent, ErrorCannotSend, TryAgain, SentMaybe } 我已经捕获了Send中的所有异常,并从中分离出SmtpException.StatusCodes。故障看起来对吗?还是有更好的方法 t

我试图使用枚举总结
System.Net.Mail.SmtpClient.Send
的结果。这就是为什么我知道我是否应该重试发送电子邮件,并希望防止发送重复的电子邮件

public enum MailSendStatus {
    None,
    Sent,
    ErrorCannotSend,
    TryAgain,
    SentMaybe
}
我已经捕获了
Send
中的所有异常,并从中分离出
SmtpException.StatusCode
s。故障看起来对吗?还是有更好的方法

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;

我不喜欢这个。ArgumentNull、ObjectDisposed是编程错误(与InvalidOperation一样)。您不应将它们分解为SMTP错误,而应将其修复。Fpr这一点,使程序崩溃是好的(并输出堆栈跟踪)。方法“快速失败”。不要重新显示您不知道如何处理的异常,InvalidOperationException、ObjectDisposedException表示状态有问题,ArbumentNullException是一个使用/ui错误。

为了清楚起见,我省略了日志语句,但是的,这些应该主要在开发过程中捕获。我只是在msdn页面上列出了所有例外情况,我不喜欢这样。真正地问题是,它使我们很难在更远的地方捕捉到真正的花蕾。我从不隐藏内部错误,并希望它们尽可能可见,以便快速清理。如果我从捕获树中删除这些情况,将触发泛型
(异常e)
,返回一个“可能已发送”状态代码,这是不对的,它肯定是一个错误,我想我可以重新抛出异常啊,是和否。我从来没有这样做过(某些例外情况适用)有任何通用的异常处理程序。如果我不希望出现异常,应用程序会更好。异常主要是外部库的接口,我可以自由地将它们记录在异常处理程序中。其思想是:你不会捕捉到你不知道如何处理的异常,未知异常正是这种异常。有我不太同意这里的一些情况。例如,
SmtpStatusCode.CommandUnrecognized
,我认为,这表明smtp服务器或客户端正在以不兼容的方式进行通信,无法通过重试来纠正。
catch (ArgumentNullException e) {    return MailSendStatus.ErrorCannotSend;} catch 
(ObjectDisposedException e) {    return MailSendStatus.ErrorCannotSend;} catch 
(InvalidOperationException e) {    return MailSendStatus.ErrorCannotSend;