Posso testar SmtpClient antes de chamar client.Send ()?
-
21-08-2019 - |
Pergunta
Isso está relacionado a uma pergunta que fiz no outro dia em como enviar e-mail .
Meu, pergunta relacionada novo é este ... e se o usuário do meu aplicativo está atrás de um firewall ou algum outro motivo pelo qual o client.Send line (e-mail) não vai funcionar ...
Depois das linhas:
SmtpClient client = new SmtpClient("mysmtpserver.com", myportID);
client.Credentials = new System.Net.NetworkCredential("myusername.com", "mypassword");
Existe algo que eu possa fazer para cliente de teste antes de tentar enviar?
Eu pensei em colocar isso em um loop try / catch, mas eu prefiro fazer um teste e, em seguida, aparecer uma janela dizendo: não é possível o acesso SMTP ou algo parecido.
(estou presumindo que nem eu, nem potencialmente meu usuário do aplicativo, tem a capacidade de ajustar suas configurações de firewall. Por exemplo ... eles instalar o aplicativo no trabalho e não tem controle sobre sua internet no trabalho)
-Adeena
Solução
Eu acho que este é um caso em que a manipulação de exceção seria a solução preferida. Você realmente não sei o que ele vai trabalhar até que você tente, eo fracasso é uma exceção.
Editar:
Você vai querer lidar com SmtpException. Isto tem uma propriedade StatusCode, que é uma enumeração que irá dizer-lhe por que o Send () falhou.
Outras dicas
Eu acho que se você estiver olhando para testar o SMTP é que você está procurando uma forma de validar a sua configuração e disponibilidade de rede sem enviar um e-mail. Qualquer forma que é o que eu precisava desde que não havia nenhum e-mail fictício que faria sentido feito.
Com a sugestão do meu colega desenvolvedor eu vim com essa solução. A classe auxiliar pequena com o uso abaixo. Usei-o no evento OnStart de um serviço que envia e-mails.
Nota: o crédito para as coisas socket TCP vai para Peter A. Bromberg em http: / /www.eggheadcafe.com/articles/20030316.asp ea configuração ler coisas para os caras aqui: configurações de Acesso system.net de app.config programação em 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;
}
}
Uso:
if (!SmtpHelper.TestConnection(ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)))
{
throw new ApplicationException("The smtp connection test failed");
}
capturar a exceção SmtpException, ele vai dizer se ele falhou porque você não pôde se conectar ao servidor.
Se você quiser verificar se você pode abrir uma conexão com o servidor antes de qualquer tentativa, Use TcpClient e SocketExceptions captura. Embora eu não vejo nenhum benefício para fazer isso vs apenas recuperar problemas de Smtp.Send.
Você poderia tentar enviar um comando HELO para testar se o servidor está ativo e em execução antes de enviar o e-mail. Se você quiser verificar se o usuário existe, você pode tentar com o comando VRFY, mas isso muitas vezes é desativado em servidores SMTP devido a razões de segurança. Outras leituras: http://the-welters.com/professional/smtp.html Espero que isso ajude.
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;
}
Eu também tive essa necessidade.
Aqui está a biblioteca Eu fiz (é enviar um HELO
e verifica se há um 200, 220 ou 250) :
using SMTPConnectionTest;
if (SMTPConnection.Ok("myhost", 25))
{
// Ready to go
}
if (SMTPConnectionTester.Ok()) // Reads settings from <smtp> in .config
{
// Ready to go
}