web-dev-qa-db-ja.com

client.Send()を呼び出す前にSmtpClientをテストできますか?

これは先日私が尋ねた質問に関連しています メールの送信方法

私の新しい関連する質問はこれです...私のアプリケーションのユーザーがファイアウォールの後ろにいる場合、または回線client.Send(mail)が機能しないその他の理由がある場合はどうなりますか...

行の後:

SmtpClient client = new SmtpClient("mysmtpserver.com", myportID);
client.Credentials = new System.Net.NetworkCredential("myusername.com", "mypassword");

送信する前にクライアントをテストするためにできることはありますか?

これをtry/catchループに入れることを考えましたが、テストを実行してから、「smtpなどにアクセスできません」というダイアログをポップアップ表示したいと思います。

(私も、場合によってはアプリケーションユーザーも、ファイアウォール設定を調整する機能を持っていないと思います。たとえば、職場でアプリをインストールし、職場でインターネットを制御することはできません)

-アディーナ

21
adeena

これは、例外処理が好ましい解決策になる場合だと思います。試してみるまで、それが機能するかどうかは本当にわかりません。失敗は例外です。

編集:

SmtpExceptionを処理する必要があります。これにはStatusCodeプロパティがあります。これは、Send()が失敗した理由を示す列挙型です。

8
Jon B

SMTPのテストを検討している場合は、実際に電子メールを送信せずに、構成とネットワークの可用性を検証する方法を探していると思います。意味のあるダミーの電子メールがなかったので、とにかくそれが必要でした。

私の仲間の開発者の提案で、私はこの解決策を思いつきました。以下の使用法を持つ小さなヘルパークラス。メールを送信するサービスのOnStartイベントで使用しました。

注:TCPソケットのもののクレジットは、Peter A. Bromberg( http://www.eggheadcafe.com/articles/20030316.asp )と構成に送られますここでみんなに読んでください: C#でプログラム的にapp.configからsystem.net設定にアクセスしてください

ヘルパー:

public static class SmtpHelper
{
    /// <summary>
    /// test the smtp connection by sending a HELO command
    /// </summary>
    /// <param name="config"></param>
    /// <returns></returns>
    public static bool TestConnection(Configuration config)
    {
        MailSettingsSectionGroup mailSettings = config.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;
        if (mailSettings == null)
        {
            throw new ConfigurationErrorsException("The system.net/mailSettings configuration section group could not be read.");
        }
        return TestConnection(mailSettings.Smtp.Network.Host, mailSettings.Smtp.Network.Port);
    }

    /// <summary>
    /// test the smtp connection by sending a HELO command
    /// </summary>
    /// <param name="smtpServerAddress"></param>
    /// <param name="port"></param>
    public static bool TestConnection(string smtpServerAddress, int port)
    {
        IPHostEntry hostEntry = Dns.GetHostEntry(smtpServerAddress);
        IPEndPoint endPoint = new IPEndPoint(hostEntry.AddressList[0], port);
        using (Socket tcpSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
        {
            //try to connect and test the rsponse for code 220 = success
            tcpSocket.Connect(endPoint);
            if (!CheckResponse(tcpSocket, 220))
            {
                return false;
            }

            // send HELO and test the response for code 250 = proper response
            SendData(tcpSocket, string.Format("HELO {0}\r\n", Dns.GetHostName()));
            if (!CheckResponse(tcpSocket, 250))
            {
                return false;
            }

            // if we got here it's that we can connect to the smtp server
            return true;
        }
    }

    private static void SendData(Socket socket, string data)
    {
        byte[] dataArray = Encoding.ASCII.GetBytes(data);
        socket.Send(dataArray, 0, dataArray.Length, SocketFlags.None);
    }

    private static bool CheckResponse(Socket socket, int expectedCode)
    {
        while (socket.Available == 0)
        {
            System.Threading.Thread.Sleep(100);
        }
        byte[] responseArray = new byte[1024];
        socket.Receive(responseArray, 0, socket.Available, SocketFlags.None);
        string responseData = Encoding.ASCII.GetString(responseArray);
        int responseCode = Convert.ToInt32(responseData.Substring(0, 3));
        if (responseCode == expectedCode)
        {
            return true;
        }
        return false;
    }
}

使用法:

if (!SmtpHelper.TestConnection(ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)))
{
    throw new ApplicationException("The smtp connection test failed");
}
40
Four

SmtpException例外をキャッチすると、サーバーに接続できなかったために失敗したかどうかが通知されます。

試行する前にサーバーへの接続を開くことができるかどうかを確認する場合は、TcpClientを使用してSocketExceptionsをキャッチします。これを行うことと、Smtp.Sendから問題をキャッチすることには何のメリットもありません。

2
Darryl Braaten

電子メールを送信する前に、HELOコマンドを送信して、サーバーがアクティブで実行されているかどうかをテストすることができます。ユーザーが存在するかどうかを確認したい場合は、VRFYコマンドを試すことができますが、セキュリティ上の理由から、SMTPサーバーではこれが無効になっていることがよくあります。さらに読む: http://the-welters.com/professional/smtp.html これがお役に立てば幸いです。

1
Jaime Febres