如何检查是否使用C#MailMessage传递了电子邮件

Lea*_*ing 1 c# asp.net webforms asp.net-mail

我使用下面的代码来发送电子邮件,它在大多数时间工作正常,在测试期间,我们发现有时它不会发送电子邮件.如何更改此代码以检查电子邮件传递状态或字体任何其他故障.

        public static void SendEmail(string to, string subject, string message, bool isHtml)
        {
            try
            {
            var mail = new MailMessage();

            // Set the to and from addresses.
            // The from address must be your GMail account
            mail.From = new MailAddress("noreplyXYZ@gmail.com");
            mail.To.Add(new MailAddress(to));

            // Define the message
            mail.Subject = subject;
            mail.IsBodyHtml = isHtml;
            mail.Body = message;

            // Create a new Smpt Client using Google's servers
            var mailclient = new SmtpClient();
            mailclient.Host = "smtp.gmail.com";//ForGmail
            mailclient.Port = 587; //ForGmail


            // This is the critical part, you must enable SSL
            mailclient.EnableSsl = true;//ForGmail
            //mailclient.EnableSsl = false;
            mailclient.UseDefaultCredentials = true;

            // Specify your authentication details
            mailclient.Credentials = new System.Net.NetworkCredential("noreplyXYZ@gmail.com", "xxxx123");//ForGmail
            mailclient.Send(mail);
            mailclient.Dispose();
    }
                    catch (Exception ex)
                    {
    throw ex;
                        }
    }
Run Code Online (Sandbox Code Playgroud)

我知道SMTP负责发送电子邮件并且无法传递状态但是他们可以检查电子邮件传递的状态

更新的代码(这是正确的)

public static void SendEmail(string to, string subject, string message, bool isHtml)
{
    var mail = new MailMessage();

    // Set the to and from addresses.
    // The from address must be your GMail account
    mail.From = new MailAddress("noreplyXYZ@gmail.com");
    mail.To.Add(new MailAddress(to));

    // Define the message
    mail.Subject = subject;
    mail.IsBodyHtml = isHtml;
    mail.Body = message;

    // Create a new Smpt Client using Google's servers
    var mailclient = new SmtpClient();
    mailclient.Host = "smtp.gmail.com";//ForGmail
    mailclient.Port = 587; //ForGmail

    mailclient.EnableSsl = true;//ForGmail
    //mailclient.EnableSsl = false;
    mailclient.UseDefaultCredentials = true;

    // Specify your authentication details
    mailclient.Credentials = new System.Net.NetworkCredential("noreplyXYZ@gmail.com", "xxxx123");//ForGmail
    mailclient.Send(mail);
    mailclient.Dispose();
    try
    {
        mailclient.Send(mail);
        mailclient.Dispose();
    }
    catch (SmtpFailedRecipientsException ex)
    {
        for (int i = 0; i < ex.InnerExceptions.Length; i++)
        {
            SmtpStatusCode status = ex.InnerExceptions[i].StatusCode;
            if (status == SmtpStatusCode.MailboxBusy ||status == SmtpStatusCode.MailboxUnavailable)
            {
                // Console.WriteLine("Delivery failed - retrying in 5 seconds.");
                System.Threading.Thread.Sleep(5000);
                mailclient.Send(mail);
            }
            else
            {
                //  Console.WriteLine("Failed to deliver message to {0}", ex.InnerExceptions[i].FailedRecipient);
                throw ex;
            }
        }
    }
    catch (Exception ex)
    {
        //  Console.WriteLine("Exception caught in RetryIfBusy(): {0}",ex.ToString());
        throw ex;
    }
    finally
    {
        mailclient.Dispose();
    }

}
Run Code Online (Sandbox Code Playgroud)

Jon*_*art 11

好吧,你将整个代码体包装在一个try带有空catch块的块中.因此,如果消息由于某种原因无法发送,您将不知道因为您的函数将简单地返回.

如果您查看MSDN文档,SmtpClient.Send您会发现由于各种原因可能会抛出许多不同的异常.一些有趣的:


更新后的几个笔记:

你可能并不是故意这样做:

mailclient.Send(mail);
mailclient.Dispose();
try
{
    mailclient.Send(mail);
    mailclient.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

mailclient在尝试再次使用它之前要处置它.

using

MailMessage并且SmtpClient都实现IDisposable,因此将它们放在using块中是最佳实践(也是最简单的):

using (var mail = new MailMessage())
using (var mailclient = new SmtpClient())
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

然后你不必担心调用Dispose()你的finally块(你可能根本不需要它们).

throw

你可能知道,但是没有意义:

catch (Exception ex)
{
    throw ex; 
}
Run Code Online (Sandbox Code Playgroud)

foreach

for (int i = 0; i < ex.InnerExceptions.Length; i++)
{
    SmtpStatusCode status = ex.InnerExceptions[i].StatusCode;
    // ... 
}
Run Code Online (Sandbox Code Playgroud)

可以重写为:

foreach (var innerEx in ex.InnerExceptions)
{
    var status = innerEx.StatusCode;
}
Run Code Online (Sandbox Code Playgroud)

Thread.Sleep()

如果此代码面向用户,您可能真的不想这样做,因为它会导致页面挂起5秒钟等待发送.在我看来,你不应该处理直接在网页代码中发送邮件,你应该排队等待后台任务发送.但这是一个完全不同的问题.

只需要做一些事情就可以帮助你成为更好的C#编码器.