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

时间:2012-07-10 05:01:08

标签: 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;
                        }
    }

我知道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();
    }

}

2 个答案:

答案 0 :(得分:11)

好吧,你将整个代码包裹在try块中,并带有一个空的catch块。因此,如果邮件因任何原因无法发送,您将不知道,因为您的功能只会返回。

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


更新后的几点说明:

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

mailclient.Send(mail);
mailclient.Dispose();
try
{
    mailclient.Send(mail);
    mailclient.Dispose();
}

您在尝试再次使用之前处置mailclient

using

MailMessageSmtpClient都实现IDisposable,因此将它们放在using块中是最佳做法(也是最简单的):

using (var mail = new MailMessage())
using (var mailclient = new SmtpClient())
{
    // ...
}

然后,您不必担心在Dispose()块中调用finally(您可能根本不需要它们)。

throw

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

catch (Exception ex)
{
    throw ex; 
}

foreach

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

可以重写为:

foreach (var innerEx in ex.InnerExceptions)
{
    var status = innerEx.StatusCode;
}

Thread.Sleep()

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

帮助您成为更好的C#编码器的一些事情。

答案 1 :(得分:1)

  

听起来你问是否有实时检查方法   看看你的用户是否收到了消息。如果是这样,我会建议你   不要追求那条道路。虽然大多数时候电子邮件发送似乎是   瞬间,它可以在任何时间之前保持不变   被送到收件人的邮箱。

我建议你通过以下asp.net论坛链接:
SMTP server and email FAQ
Delivery Notification Not Working when Sending Emails
Best Practice to do implement checking if the email sent

注意: There is no reliable way to find out if a message was indeed delivered.

还有另一个SO线程已经可用,你已经问过:
How to check MailMessage was delivered in .NET?
ASP.NET MVC How to determine if the e-mail didn't reach the receiver