在C#中调用send方法之前验证SMTP用户凭据

时间:2017-02-02 13:52:59

标签: c# smtp smtpclient

我正在尝试使用kazakov.nickolay在this post中建议的方法验证smtp用户。

首先,我尝试使用VRFY命令,它给出了错误响应

  

"命令无效"。

接下来,我直接尝试使用AUTH命令,在这种情况下,我得到了错误响应 -

  

"首先发出starttls命令。"

当我首先尝试STARTTLS命令然后AUTH时,线程进入无限循环。这可能发生,因为socket.Available计数为零,之后我无法做任何事情。

以下是示例代码 -

 public bool ValidateUser()
    {   
    bool isValid = true;

    string useremail = "user@mail.com";
    string password = "userPassword";
    string smtpserver = "smtp.server.name" 
    int port = 587;

        try
        {
            const string EOF = "\r\n";

            IPHostEntry hostEntry = Dns.GetHostEntry(smtpserver);
            IPEndPoint endPoint = new IPEndPoint(hostEntry.AddressList[0], port);
            using (Socket tcpSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
            {
                try
                {
                    tcpSocket.Connect(endPoint);
                    if (!CheckResponse(tcpSocket, 220))
                        isValid = false;

                    SendBytes(tcpSocket, $"EHLO {Dns.GetHostName()}{EOF}");
                    if (!CheckResponse(tcpSocket, 250))
                        isValid = false;

                    //SendBytes(tcpSocket, $"VRFY {useremail} {EOF}");
                    //if (!CheckResponse(tcpSocket, 250) || !CheckResponse(tcpSocket, 251))
                    //    isValid = false;

                    //SendBytes(tcpSocket, $"STARTTLS{EOF}");
                    //if (!CheckResponse(tcpSocket, 220))
                    //    isValid = false;

                    SendBytes(tcpSocket, $"AUTH {useremail} {EOF}");
                    if (!CheckResponse(tcpSocket, 334))
                        isValid = false;


                    SendBytes(tcpSocket, Convert.ToBase64String(Encoding.UTF8.GetBytes($"{useremail}")) + EOF);
                    if (!CheckResponse(tcpSocket, 334))
                    {
                        return false;
                    }

                    SendBytes(tcpSocket, Convert.ToBase64String(Encoding.UTF8.GetBytes($"{password}")) + EOF);
                    if (!CheckResponse(tcpSocket, 235))
                    {
                        return false;
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    tcpSocket.Dispose();
                }
            }
        }
        catch (Exception)
        {

            throw;
        }
        return isValid;
    }


    private bool CheckResponse(Socket socket, int expectedCode)
    {
        bool isResponse = true;
        try
        {
            if (socket == null)
                return false;
            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)
            {
                isResponse = false;
            }
        }
        catch (Exception ex) { throw ex; }

        return isResponse;
    }

    private void SendBytes(Socket socket, string data)
    {
        if (socket == null)
            return;
        byte[] bytes = Encoding.UTF8.GetBytes(data);
        socket.Send(bytes, 0, bytes.Length, SocketFlags.None);

    }

我还尝试了另一种启用SSL的方法。

在以下代码行_sslStream.AuthenticateAsClient(smtpserver);上,我得到了异常 -

  

"由于意外的数据包格式,握手失败。"

在调用发送方法之前,有人可以建议我验证用户的正确步骤吗?

请注意 - 如果用户不是有效用户,我不想调用send方法。此外,我不想发送虚拟邮件来检查相同的内容。

0 个答案:

没有答案