Могу ли я проверить SmtpClient перед вызовом client.Send ()? - PullRequest
20 голосов
/ 17 декабря 2008

Это связано с вопросом, который я задал на днях на как отправить электронное письмо .

Мой новый, связанный с этим вопрос заключается в следующем ... что, если пользователь моего приложения находится за брандмауэром или по какой-то другой причине, по которой линия client.Send (mail) не будет работать ...

После строк:

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

Есть ли что-то, что я могу сделать, чтобы проверить клиента, прежде чем пытаться отправить?

Я думал о том, чтобы поместить это в цикл try / catch, но я бы лучше сделал тест, а затем открыл диалоговое окно, в котором говорилось: не могу получить доступ к smtp или что-то в этом роде.

(Я предполагаю, что ни я, ни потенциальный пользователь приложения не имеют возможности настраивать параметры своего брандмауэра. Например ... они устанавливают приложение на работе и не имеют контроля над своим интернетом на работе)

-Adeena

Ответы [ 6 ]

39 голосов
/ 19 мая 2010

Я думаю, что если вы хотите протестировать SMTP, то вы ищете способ проверить свою конфигурацию и доступность сети без фактической отправки электронного письма. В любом случае это то, что мне было нужно, поскольку не было фиктивного электронного письма, которое имело бы смысл.

С предложением моего коллеги-разработчика я придумал это решение. Небольшой вспомогательный класс с использованием ниже. Я использовал его на событии OnStart службы, которая отправляет электронные письма.

Примечание: заслуга материала TCP-сокета принадлежит Питеру А. Бромбергу по адресу http://www.eggheadcafe.com/articles/20030316.asp, а конфиг читает материал для парней здесь: Программный доступ к настройкам system.net из app.config в C #

Helper:

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");
}
9 голосов
/ 17 декабря 2008

Я думаю, что это тот случай, когда обработка исключений будет предпочтительным решением. Вы действительно не знаете, что это сработает, пока не попробуете, и неудача - исключение.

Edit:

Вы захотите обработать SmtpException. У него есть свойство StatusCode, которое представляет собой перечисление, которое сообщит вам, почему не удалось выполнить Send ().

2 голосов
/ 17 декабря 2008

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

Если вы хотите проверить, можете ли вы открыть соединение с сервером перед любой попыткой, используйте TcpClient и перехватите SocketExceptions. Хотя я не вижу в этом никакой пользы по сравнению с простыми попытками решить проблему с Smtp.Send.

1 голос
/ 17 декабря 2008

Вы можете попытаться отправить команду HELO, чтобы проверить, если сервер активен и работает до отправки электронной почты. Если вы хотите проверить, существует ли пользователь, вы можете попробовать использовать команду VRFY, но это часто отключается на SMTP-серверах из-за соображений безопасности. Дальнейшее чтение: http://the -welters.com / профессиональный / smtp.html Надеюсь, это поможет.

0 голосов
/ 14 ноября 2017
    private bool isValidSMTP(string hostName)
    {
        bool hostAvailable= false;
        try
        {
            TcpClient smtpTestClient = new TcpClient();
            smtpTestClient.Connect(hostName, 25);
            if (smtpTestClient.Connected)//connection is established
            {
                NetworkStream netStream = smtpTestClient.GetStream();
                StreamReader sReader = new StreamReader(netStream);
                if (sReader.ReadLine().Contains("220"))//host is available for communication
                {
                    hostAvailable= true;
                }
                smtpTestClient.Close();
            }
        }
        catch
        {
          //some action like writing to error log
        }
        return hostAvailable;
    }
0 голосов
/ 30 июня 2015

У меня тоже была эта потребность.

Вот библиотека, которую я сделал (она отправляет HELO и проверяет 200, 220 или 250):

using SMTPConnectionTest;

if (SMTPConnection.Ok("myhost", 25))
{
   // Ready to go
}

if (SMTPConnectionTester.Ok()) // Reads settings from <smtp> in .config
{
    // Ready to go
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...