【问题标题】:Can I test SmtpClient before calling client.Send()?我可以在调用 client.Send() 之前测试 SmtpClient 吗?
【发布时间】:2010-09-27 05:29:52
【问题描述】:

这与我前几天在how to send email 上提出的问题有关。

我的新相关问题是...如果我的应用程序的用户位于防火墙后面或其他原因导致线路 client.Send(mail) 不起作用...

行后:

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

在我尝试发送之前,我可以做些什么来测试客户端吗?

我想过把它放在一个 try/catch 循环中,但我宁愿做一个测试,然后弹出一个对话框说:无法访问 smtp 或类似的东西。

(我假设我和潜在的我的应用程序用户都没有能力调整他们的防火墙设置。例如......他们在工作中安装应用程序并且无法控制他们在工作中的互联网)

-阿迪娜

【问题讨论】:

    标签: c# email smtpclient


    【解决方案1】:
        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;
        }
    

    【讨论】:

      【解决方案2】:

      我也有这个需求。

      Here's the library I made(它发送 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
      }
      

      【讨论】:

      • 链接不存在了
      【解决方案3】:

      我认为,如果您正在寻找测试 SMTP,那么您正在寻找一种无需实际发送电子邮件即可验证您的配置和网络可用性的方法。任何方式都是我需要的,因为没有有意义的虚拟电子邮件。

      在我的开发伙伴的建议下,我想出了这个解决方案。一个小的帮助类,用法如下。我在发送电子邮件的服务的 OnStart 事件中使用它。

      注意:TCP 套接字的功劳归功于 http://www.eggheadcafe.com/articles/20030316.asp 上的 Peter A. Bromberg,配置在这里向这些人读了一些东西:Access system.net settings from app.config programmatically in 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 服务器之间切换。
      • 太棒了。我将Dns.GetHostEntry 更改为Dns.GetHostAddresses,这应该会更快,并且如果IP 地址通过并且没有找到反向dns 条目,则不会失败。
      • 请注意,由于使用socket.Available,此代码将随机失败。
      • 这里没有显示更多代码吗? C# 编译器不知道配置是什么。我假设它是应用程序中配置类的一部分。我需要做什么来解决编译错误?我正在使用 Visual Studio 2015。
      • @octopusgrabbus 你需要在你的类中添加一个引用System.Configuration 和一个using System.Configuration; 语句。还需要usingSystemSystem.NetSystem.Net.ConfigurationSystem.Net.SocketsSystem.Text 的声明。
      【解决方案4】:

      我认为在这种情况下,异常处理将是首选解决方案。在你尝试之前你真的不知道它会起作用,失败是一个例外。

      编辑:

      您需要处理 SmtpException。这有一个 StatusCode 属性,它是一个枚举,它会告诉您 Send() 失败的原因。

      【讨论】:

      • 但不是真的可能有其他原因导致异常被捕获......而且我知道这是一种特定的可能性,并希望根据自己的情况处理它......这有意义吗?
      • 我正在尝试实现事务性电子邮件发件人,但不能使用异常,因为测试应该在事务流程的不同部分。
      【解决方案5】:

      捕获 SmtpException 异常,它会告诉你它是否因为无法连接到服务器而失败。

      如果您想在任何尝试之前检查是否可以打开与服务器的连接,请使用 TcpClient 并捕获 SocketExceptions。虽然我认为这样做与从 Smtp.Send 中捕获问题相比没有任何好处。

      【讨论】:

      • 呃,因为它可能是您的应用程序的加载,或者您需要在轮询的基础上验证与您的 SMTP 服务器的连接,并且您还没有要发送的电子邮件并且您想要测试/确保您发送的能力,当您发送时 - 这就是原因。
      【解决方案6】:

      在发送电子邮件之前,您可以尝试发送 HELO 命令来测试服务器是否处于活动状态并正在运行。 如果您想检查用户是否存在,您可以尝试使用 VRFY 命令,但由于安全原因,这通常在 SMTP 服务器上被禁用。 进一步阅读: http://the-welters.com/professional/smtp.html 希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-05
        相关资源
        最近更新 更多