カテゴリー
Microsoft

【ASP.NET】【MVC5】メール送信時にサーバ接続エラー、送信アドレス誤りエラーを取得したい

ポイント

  • 送信アドレス誤りは同イントラ内限定で検出できた。別ドメインへのメール送信エラーは制御出来ない。
  • 複数のアドレスに送信するときにアドレス誤りを検出するには、SmtpFailedRedipientsException と SmtpFailedRecipientException の両方でキャッチする必要がある。
  • 1 つのアドレスにだけ送信する場合は、SmtpFailedRecipientException のみでよい。
  • 送信できなかったメールアドレスは、SmtpFailedRecipientException.FailedRecipient に格納されている。
  • Host、Port、userName、password に原因がある (つまりサーバに接続できない) 場合は SmtpException でキャッチできる。

他のポイント

  • メールを送るには、MailMessage クラス、SmtpClient クラスの 2 つが必要
  • MailMessage クラスはメール自体を扱うクラス
    • From、To、CC、BCC、添付ファイル、件名、本文などを扱う。
    • メールアドレスの追加は、MailAddress クラスにメールアドレス文字列を渡してインスタンス化したものを使う。
  • SmtpClient クラスはメールを送るときの認証情報を扱うクラス。
    • SMTP サーバ名、ポート番号、ユーザー名、パスワード、SSL の使用などを扱う。
    • ユーザ名、パスワード の追加は、NetworkCredential クラスにユーザー名、パスワード文字列渡してインスタンス化したものを使う。

ソースコード

の環境、ファイルは同じです。リンク先の投稿のファイルを編集しました。

public ActionResult Index()
{
    return View();
}

[HttpPost, ActionName("Index")]
[ValidateAntiForgeryToken]
public ActionResult IndexExec()
{
    //Hotmailでメールを送信する

    //MailMessageの作成
    var from = "xxxxx@hotmail.co.jp";
    var to = "yyyyy@gmail.com";
    var to2 = "zzzzz@gmail.com";
    var subject = "テスト";
    var body = "このメールは、テストです。";

    MailMessage msg = new MailMessage();
    msg.From = new MailAddress(from);
    msg.To.Add(new MailAddress(to));
    msg.To.Add(new MailAddress(to2));
    msg.Subject = subject;
    msg.Body = body;

    SmtpClient sc = new SmtpClient();
    //SMTPサーバーなどを設定する
    sc.Host = "smtp.live.com";
    sc.Port = 587;
    sc.DeliveryMethod = SmtpDeliveryMethod.Network;

    //ユーザー名とパスワードを設定する
    var userName = "xxxxx@hotmail.co.jp";
    var password = "zzzzz";
    sc.Credentials = new NetworkCredential(userName, password);
    //SSLを使用する
    sc.EnableSsl = true;

    // 次のメール送信エラーハンドリング
    // - サーバ接続エラー
    // - 送信アドレス誤りエラー(同イントラ内。別ドメインへのメール送信エラーは制御出来ない)
    try
    {
        //メッセージを送信する
        sc.Send(msg);
        ViewBag.Message = "送信成功";
    }
    catch (SmtpFailedRecipientsException e)
    {
        // 送信アドレス誤りエラーが2件以上の場合
        // 誤ったアドレス分、例外を発生させる。
        // 正しいアドレスには、メールが送られる。
        var message = "SmtpFailedRecipientsException 発生で2件以上送信アドレス誤りエラー: ";
        foreach (var item in e.InnerExceptions)
        {
            message = message + " " + item.FailedRecipient;
        }
        ViewBag.Message = message;
    }
    catch (SmtpFailedRecipientException e)
    {
        // 送信アドレス誤りエラーが1件のみの場合
        ViewBag.Message = "SmtpFailedRecipientException 発生で1件だけ送信アドレス誤りエラー: " + e.Message;
    }
    catch (SmtpException e)
    {
        // SmtpException クラス (System.Net.Mail) https://msdn.microsoft.com/ja-jp/library/system.net.mail.smtpexception(v=vs.110).aspx
        // Host、Port、userName、Password に原因がある
        // Host が原因ならば、SmtpException.InnerException に格納された WebException
        // Port が原因ならば、SmtpException.InnerException.InnerException に格納された SocketException
        // userName、password が原因ならば、SmtpException
        // WebException、SocketException を個別にキャッチすることはできない。
        ViewBag.Message = "SmtpException 発生でサーバ接続エラー: " + e.Message;
    }
    finally
    {
        //後始末
        msg.Dispose();
        sc.Dispose();
    }
    return View();
}
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="メール送信" class="btn btn-default" />
            </div>
        </div>

    </div>
}
<h3>@ViewBag.Message</h3>

実行した時のエラーメッセージ

パスワードを間違えた時

SmtpException 発生でサーバ接続エラー: メールボックスが使用できません。 サーバーの応答:5.7.3 Requested action aborted; user not authenticated

おわりに

メール送受信時のエラーは、メールが相手に届いたかどうか確認できたら素晴らしいのに、、、と思うのですけれどもメールが送信元のサーバーをはなれてしまうためどうにもなりません><。

思ったよりもサポートできる範囲が限られてしまう印象ですの。

以上です。

コメントを残す