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.