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秒間ハングするため、実際にはこれを実行したくない場合があります。私の意見では、とにかくWebページコードで直接メールを送信することを処理するべきではありません。バックグラウンドタスクが送信するためにそれをキューに入れる必要があります。しかし、それはまったく別の問題です。

あなたをより良いC#コーダーにするのに役立ついくつかのこと。

于 2012-07-10T05:07:06.600 に答える
1

ユーザーがメッセージを受け取ったかどうかをリアルタイムで確認する方法があるかどうかを尋ねているようです。もしそうなら、その道を追求しないことをお勧めします。ほとんどの場合、電子メールの配信は瞬時に行われるように見えますが、受信者のメールボックスに配信されるまでに、ある程度の時間がかかる可能性があります。

次の asp.net フォーラムのリンクを参照することをお勧めします:
SMTP サーバーと電子メール FAQ 電子メールの
送信時に配信通知
が機能しない

注: メッセージが実際に配信されたかどうかを確認する信頼できる方法はありません。

あなたが尋ねた別の SO スレッドが既に利用可能です:
How to check MailMessage was delivery in .NET?
ASP.NET MVC 電子メールが受信者に届かなかったかどうかを判断する方法

于 2012-07-10T05:35:32.707 に答える