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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11406889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 17:44:46  来源:igfitidea点击:

How to check if email was delivered using C# MailMessage

c#asp.netwebformsasp.net-mail

提问by Learning

I am using below code to send email it works fine most of the time & during test we found sometimes it doesn't deliver email. How can i alter this code to check the email delivery status or font any other failure.

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

        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("[email protected]");
            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("[email protected]", "xxxx123");//ForGmail
            mailclient.Send(mail);
            mailclient.Dispose();
    }
                    catch (Exception ex)
                    {
    throw ex;
                        }
    }

I know SMTP is responsible for sending email & it is not possible to delivery status but is their a way around to check the status of the email delivery

我知道 SMTP 负责发送电子邮件,并且无法查看递送状态,但这是一种检查电子邮件递送状态的方法

UPDATED CODE(is this correct)

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

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("[email protected]");
    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("[email protected]", "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();
    }

}

采纳答案by Jonathon Reinhart

Well, you have the entire body of code wrapped in a tryblock with an empty catchblock. So, if the message fails to send for whatever reason, you will have no ideabecause your function will simply return.

好吧,您将整个代码体包裹在一个try带有空catch块的块中。因此,如果消息由于某种原因未能发送,您将一无所知,因为您的函数只会返回。

If you look at the MSDN documentation for SmtpClient.Sendyou'll see that there are a number of different exceptions it can throw for various reasons. A couple interesting ones:

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



A couple of notes after your update:

更新后的一些注意事项:

You probably don't mean to do this:

你可能不是故意这样做:

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

You're disposing mailclientbefore trying to use it again.

mailclient在尝试再次使用它之前进行处理。

using

using

MailMessageand SmtpClientboth implement IDisposable, so it would be best practice (and easiest) to put them in a usingblock:

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

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

Then you won't have to worry about calling Dispose()in your finallyblocks (you may not need them at all then).

然后,你将不必担心通话Dispose()在你的finally块(你可能根本不会再需要它们)。

throw

throw

You're probably aware, but there's no point in:

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

catch (Exception ex)
{
    throw ex; 
}

foreach

foreach

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

Can be re-written as:

可以改写为:

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

Thread.Sleep()

Thread.Sleep()

If this code is user-facing, you probably don't really want to do this, as it is going to cause the page to hang for 5 seconds waiting to send. In my opinion, you shouldn't handle sending mail directly in the web page code anyway, you should queue it up for a background task to send. But that's an entirely different issue.

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

Just a few things to help make you a better C# coder.

只需几件事就可以帮助您成为更好的 C# 编码员。

回答by Niranjan Singh

It sounds like you're asking if there's a way in real time to check to see if your user got the message. If so, I would recommend that you don't pursue that path. While most times email delivery seems to be instantaneous, it could be held up for any length of time prior to being delivered to the recipient's mailbox.

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

I suggest you to go through following asp.net forum links:
SMTP server and email FAQ
Delivery Notification Not Working when Sending Emails
Best Practice to do implement checking if the email sent

我建议您查看以下 asp.net 论坛链接:
SMTP 服务器和电子邮件常见问题解答
发送电子邮件时无法正常工作的
最佳实践检查电子邮件是否已发送

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

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

There are another SO thread already availalbe that you have asked:
How to check MailMessage was delivered in .NET?
ASP.NET MVC How to determine if the e-mail didn't reach the receiver

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