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

前端 未结 6 774
夕颜
夕颜 2020-11-28 10:58

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 firew

6条回答
  •  执念已碎
    2020-11-28 11:47

    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.

    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.

    Note: the credit for the TCP socket stuff goes to Peter A. Bromberg at http://www.eggheadcafe.com/articles/20030316.asp and the config read stuff to the guys here: Access system.net settings from app.config programmatically 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;
        }
    }
    

    Usage:

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

提交回复
热议问题