1

I am trying to validate smtp user as method suggested in this post by kazakov.nickolay.

First, I tried to use VRFY command, It gives me error response as

"Invalid command".

Next, I tried with AUTH command directly, In this case I got error response as-

"Issue starttls command first."

When I tried STARTTLS command first and then AUTH, then thread went into infinite loop. This may be happens because socket.Available count was zero and I was not able to do anything afterwards.

Below is the sample code-

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

    }

I also tried the another approach that is with SSL enabled.

On following line of code _sslStream.AuthenticateAsClient(smtpserver);, I got the exception-

"The handshake failed due to an unexpected packet format."

Can anybody please suggest me proper steps to validate user before calling send method?

Please note - I do not want to call send method if user is not a valid user. Also I do not want to send the dummy mail to check the same.

Community
  • 1
  • 1
S P
  • 75
  • 6
  • Use a sniffer like wireshark or fiddler. The error message are much better in the sniffer than Net Library. – jdweng Feb 02 '17 at 14:03

0 Answers0