如何使用C#MailMessage检查电子邮件是否已发送

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

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

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

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

  • SmtpException
  • SmtpFailedRecipientsException

更新后的几个笔记:

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

 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()) { // ... } 

然后你不必担心在你的finally块中调用Dispose() (那时你根本不需要它们)。

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#编码器。

这听起来像是在询问是否有实时检查用户是否收到消息的方法。 如果是这样,我建议你不要追求那条道路。 虽然大多数情况下电子邮件传递似乎是即时的,但在传送到收件人邮箱之前,它可能会被保留一段时间。

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

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

还有另一个SO线程已经可用,您已经问过:
如何检查MailMessage是否在.NET中提供?
ASP.NET MVC如何确定电子邮件是否未到达接收方