Могу ли я тестировать 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 или что-то в этом роде.
(Я предполагаю, что ни я, ни потенциально пользователь моего приложения не могут настроить свои настройки брандмауэра. Например... они устанавливают приложение на работу и не контролируют свой Интернет на работе)
-Adeena
Ответы
Ответ 1
Я думаю, что это случай, когда обработка исключений будет предпочтительным решением. Вы действительно не знаете, что он будет работать до тех пор, пока вы не попробуете, а сбой - исключение.
Edit:
Вы хотите обработать SmtpException. Это свойство StatusCode, которое представляет собой перечисление, которое сообщит вам, почему сбой Send() не удалось.
Ответ 2
Я думаю, что если вы хотите проверить SMTP, это значит, что вы ищете способ проверить свою конфигурацию и доступность сети, не отправив электронное письмо. В любом случае, что мне было нужно, так как не было никакого фиктивного письма, которое имело бы смысл.
С предложением моего коллеги-разработчика я придумал это решение. Небольшой вспомогательный класс с использованием ниже. Я использовал его в событии OnStart службы, которая отправляет электронные письма.
Примечание: кредит на материал сокета TCP идет на Peter A. Bromberg по адресу http://www.eggheadcafe.com/articles/20030316.asp, а файл конфига для ребята здесь: Доступ к параметрам system.net.net из app.config программно в С#
Помощник:
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 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");
}
Ответ 3
Поймать исключение SmtpException, оно сообщит вам, было ли это неудачно, потому что вы не могли подключиться к серверу.
Если вы хотите проверить, можете ли вы открыть соединение с сервером перед любой попыткой, используйте TcpClient и уловите SocketExceptions. Хотя я не вижу никакой пользы для этого, а просто улавливаю проблемы с Smtp.Send.
Ответ 4
Вы можете попытаться отправить команду HELO, чтобы проверить, активен ли сервер и запускается до его отправки.
Если вы хотите проверить, существует ли пользователь, вы можете попробовать с помощью команды VRFY, но это часто отключается на SMTP-серверах из-за соображений безопасности.
Дальнейшее чтение:
http://the-welters.com/professional/smtp.html
Надеюсь, это поможет.
Ответ 5
У меня также была эта необходимость.
Здесь библиотека, которую я создал (она отправляет 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
}
Ответ 6
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;
}