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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/372742/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 00:58:19  来源:igfitidea点击:

Can I test SmtpClient before calling client.Send()?

c#emailsmtpclient

提问by adeena

This is related to a question I asked the other day on how to send email.

这与我前几天问的关于如何发送电子邮件的问题有关

My new, related question is this... what if the user of my application is behind a firewall or some other reason why the line client.Send(mail) won't work...

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

After the lines:

行后:

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

is there something I can do to test client before I try sending?

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

I thought about putting this in a try/catch loop, but I'd rather do a test and then pop up a dialog saying: can't access smtp or something like that.

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

(I'm presuming that neither I, nor potentially my application user, has the ability to adjust their firewall settings. For example... they install the app at work and don't have control over their internet at work)

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

-Adeena

-阿迪娜

采纳答案by Jon B

I think this is a case where exception handling would be the preferred solution. You really don't know that it will work until you try, and failure is an exception.

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

Edit:

编辑:

You'll want to handle SmtpException. This has a StatusCode property, which is an enum that will tell you why the Send() failed.

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

回答by Jaime Febres

You could try to send an HELO command to test if the server is active and running before to send the email. If you want to check if the user exists you could try with the VRFY command, but this is often disabled on SMTP servers due to security reasons. Further reading: http://the-welters.com/professional/smtp.htmlHope this helps.

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

回答by Darryl Braaten

Catch the SmtpException exception, it will tell you if it failed because you couldn't connect to the server.

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

If you want to check if you can open a connection to the server before any attempt, Use TcpClient and catch SocketExceptions. Though I don't see any benefit to doing this vs just catching problems from Smtp.Send.

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

回答by Four

I think that if you are looking to test the SMTP it's that you are looking for a way to validate your configuration and network availability without actually sending an email. Any way that's what I needed since there were no dummy email that would of made sense.

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

With the suggestion of my fellow developer I came up with this solution. A small helper class with the usage below. I used it at the OnStart event of a service that sends out emails.

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

Note: the credit for the TCP socket stuff goes to Peter A. Bromberg at http://www.eggheadcafe.com/articles/20030316.aspand the config read stuff to the guys here: Access system.net settings from app.config programmatically in C#

注意:TCP 套接字的功劳归功于http://www.eggheadcafe.com/articles/20030316.asp上的 Peter A. Bromberg和这里的配置读取内容:从 app.config 访问 system.net 设置在 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;
    }
}

Usage:

用法:

if (!SmtpHelper.TestConnection(ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)))
{
    throw new ApplicationException("The smtp connection test failed");
}

回答by talles

I also had this need.

我也有这个需求。

Here's the library I made(it send a HELOand checks for a 200, 220 or 250):

这是我制作的库(它发送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
}

回答by Eshan Chinchorkar

    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;
    }