Могу ли я протестировать SmtpClient перед вызовом client.Send ()?

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

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

После строк:

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

Могу ли я что-нибудь сделать для тестирования клиента перед отправкой?

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

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

-Адина

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
22
0
34 528
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

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

Редактировать:

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

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

adeena 17.12.2008 00:18

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

Jan Zahradník 09.03.2015 15:39

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

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

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

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

vapcguy 05.05.2017 01:08

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

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

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

Помощник:

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");
}

Отличное решение. Работает как шарм и позволяет мне легко переключаться между SMTP-серверами, если первый по какой-то причине недоступен.

Catch22 01.08.2012 17:37

Отлично. Я изменил Dns.GetHostEntry на Dns.GetHostAddresses, который должен быть быстрее и не даст сбой, если IP-адрес передан и обратная запись DNS не найдена.

Jan Zahradník 09.03.2015 15:36

Обратите внимание, что этот код случайно не сработает из-за использования socket.Available.

usr 27.06.2016 11:58

Есть ли еще код, не показанный здесь? Компилятор C# не знает, что такое Конфигурация. Я предполагаю, что это часть класса конфигурации в приложении. Что мне нужно сделать, чтобы исправить ошибку компиляции? Я использую Visual Studio 2015.

octopusgrabbus 18.04.2017 20:46

@octopusgrabbus Вам необходимо добавить в свой класс ссылочный System.Configuration и оператор using System.Configuration;. Также необходимы статусы using для System, System.Net, System.Net.Configuration, System.Net.Sockets, System.Text.

vapcguy 05.05.2017 17:30

Как указал @Jan Zahradník в моем случае, я использую IPAddress.TryParse(), чтобы определить, является ли данная строка IP-адресом или именем хоста, и, следуя случаю, я использую Dns.GetHostEntry или Dns.GetHostAddresses в функции.

bau 10.05.2019 13:09

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

Вот созданная мной библиотека (он отправляет 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
}

ссылка больше не существует

Robert Koch 11.04.2019 21:04
    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;
    }

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