Posso testare SmtpClient prima di chiamare client.Send ()?

Questo è legato a una domanda che ho chiesto l’altro giorno su come inviare e-mail .

La mia nuova domanda correlata è questa … cosa succede se l’utente della mia applicazione è dietro un firewall o qualche altro motivo per cui il client line.Invia (mail) non funzionerà …

Dopo le linee:

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

c’è qualcosa che posso fare per testare il client prima di provare a inviare?

Ho pensato di metterlo in un ciclo try / catch, ma preferirei fare un test e poi aprire una finestra di dialogo che diceva: non posso accedere a smtp o qualcosa del genere.

(Presumo che né io né il mio utente dell’applicazione possano modificare le impostazioni del firewall, ad esempio … installano l’app al lavoro e non hanno il controllo su Internet al lavoro)

-Adeena

Penso che questo sia un caso in cui la gestione delle eccezioni sarebbe la soluzione preferita. Davvero non sai che funzionerà finché non proverai, e il fallimento è un’eccezione.

Modificare:

Dovrai gestire SmtpException. Questo ha una proprietà StatusCode, che è un enum che ti spiegherà perché Send () non è riuscito.

Penso che se stai cercando di testare l’SMTP è che stai cercando un modo per convalidare la tua configurazione e la disponibilità della rete senza effettivamente inviare una email. Qualsiasi modo fosse quello di cui avevo bisogno, dal momento che non c’erano email fittizie che avrebbero avuto senso.

Con il suggerimento del mio collega sviluppatore, mi è venuta in mente questa soluzione. Una piccola class di supporto con l’utilizzo di seguito. L’ho usato nell’evento OnStart di un servizio che invia email.

Nota: il credito per le risorse del socket TCP va a Peter A. Bromberg all’indirizzo http://www.eggheadcafe.com/articles/20030316.asp e le informazioni di config per i ragazzi qui: Accedi alle impostazioni di system.net da app.config programmaticamente in C #

helper:

 public static class SmtpHelper { ///  /// test the smtp connection by sending a HELO command ///  ///  ///  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); } ///  /// test the smtp connection by sending a HELO command ///  ///  ///  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"); } 

Catch l’eccezione SmtpException, ti dirà se non è riuscita perché non è ansible connettersi al server.

Se si desidera verificare se è ansible aprire una connessione al server prima di qualsiasi tentativo, utilizzare TcpClient e catturare SocketExceptions. Anche se non vedo alcun vantaggio nel fare questo vs solo problemi di cattura da Smtp.Send.

Si potrebbe provare a inviare un comando HELO per verificare se il server è attivo e in esecuzione prima di inviare l’e-mail. Se si desidera verificare se l’utente esiste, è ansible provare con il comando VRFY, ma questo è spesso disabilitato sui server SMTP a causa di motivi di sicurezza. Ulteriori letture: http://the-welters.com/professional/smtp.html Spero che questo aiuti.

Anch’io ho avuto questa necessità.

Ecco la libreria che ho creato (invia un HELO e controlla un 200, 220 o 250):

 using SMTPConnectionTest; if (SMTPConnection.Ok("myhost", 25)) { // Ready to go } if (SMTPConnectionTester.Ok()) // Reads settings from  in .config { // Ready to go } 
  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; }