Как проверить, было ли доставлено письмо с использованием 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();
    }

}

2 ответа

Решение

Ну, у вас есть все тело кода, завернутого в try блок с пустым catch блок. Таким образом, если сообщение не удастся отправить по какой-либо причине, вы не будете знать, потому что ваша функция просто вернется.

Если вы посмотрите на документацию MSDN для SmtpClient.Send вы увидите, что есть ряд различных исключений, которые он может генерировать по разным причинам. Пара интересных:

  • SmtpException
  • SmtpFailedRecipientsException

Пару заметок после вашего обновления:

Вы, вероятно, не хотите делать это:

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#.

Похоже, вы спрашиваете, есть ли способ в режиме реального времени проверить, получил ли ваш пользователь сообщение. Если это так, я бы порекомендовал вам не идти по этому пути. Хотя в большинстве случаев доставка электронной почты кажется мгновенной, ее можно отложить на любой промежуток времени до доставки в почтовый ящик получателя.

Я предлагаю вам перейти по следующим ссылкам на форуме asp.net:
SMTP-сервер и электронная почта FAQ
Уведомление о доставке не работает при отправке писем
Лучшая практика для осуществления проверки, если электронное письмо отправлено

Примечание. Не существует надежного способа узнать, действительно ли сообщение было доставлено.

Есть еще одна тема, которую вы уже просили:
Как проверить, что MailMessage был доставлен в.NET?
ASP.NET MVC Как определить, не достигла ли электронная почта получателя

Другие вопросы по тегам