2

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

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

}
4

2 回答 2

11

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

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


更新后的几点说明:

您可能不是要这样做:

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

mailclient在尝试再次使用它之前,您正在处理它。

using

MailMessage并且SmtpClient都实现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# 编码器。

于 2012-07-10T05:07:06.600 回答
1

听起来你在问是否有办法实时检查你的用户是否收到了消息。如果是这样,我建议你不要走这条路。虽然大多数时候电子邮件传递似乎是即时的,但在传递到收件人邮箱之前,它可能会延迟任意时间。

我建议您通过以下 asp.net 论坛链接:
SMTP 服务器和电子邮件常见问题解答
发送电子邮件时发送通知不起作用
实施检查电子邮件是否发送的最佳实践

注意: 没有可靠的方法来确定消息是否确实已送达。

您已经询问过另一个 SO 线程:
如何检查 MailMessage 是否在 .NET 中传递?
ASP.NET MVC 如何确定电子邮件是否没有到达收件人

于 2012-07-10T05:35:32.707 回答