我可以在调用client.Send()之前测试SmtpClient吗?

时间:2008-12-16 21:13:59

标签: c# email smtpclient

这与我前几天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或类似的东西。

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

-Adeena

6 个答案:

答案 0 :(得分:39)

我认为,如果您要测试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");
}

答案 1 :(得分:9)

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

编辑:

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

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

答案 4 :(得分:-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;
    }

答案 5 :(得分:-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
}