Validate SMTP user credentials before calling send method in C# - c#

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.

Related

C# Test if proxies are working before using them

I want to check if the the proxies in my list are working before using them, is it possible?
It's easy for HTTP/HTTPS since you only have to use the webclient but for socks?
I tough this could work for all
public static bool SoketConnect(string addresse)
{
string[] proxy = addresse.Split(':');
if (proxy.Count() == 2)
{
string host = proxy[0];
int port = Convert.ToInt32(proxy[1]);
var is_success = false;
try
{
var connsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
connsock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 200);
System.Threading.Thread.Sleep(500);
var hip = IPAddress.Parse(host);
var ipep = new IPEndPoint(hip, port);
connsock.Connect(ipep);
try
{
byte[] outStream = System.Text.Encoding.ASCII.GetBytes("ping");
byte[] inStream = new byte[100];
connsock.Send(outStream);
connsock.ReceiveTimeout = 500;
connsock.Receive(inStream);
string message = System.Text.Encoding.ASCII.GetString(inStream);
foreach (var bytes in inStream)
{
if (bytes != 0)
{
is_success = true;
break;
}
}
connsock.Disconnect(false);
}
catch(Exception ex)
{
is_success = false;
}
connsock.Close();
}
catch (Exception ex)
{
is_success = false;
}
return is_success;
}
else
return false;
}
but i always get the exception
"The underlying connection was closed: The connection was closed
unexpectedly." System.Net.WebException
tldr; How to check if my socks proxies are working ( Which comes back to how to use a socks proxy)
EDIT: still doesn't help,need an answer
EDIT2 : Only pinging the proxy isn't the right thing to do
As far as I know you have to use them to see if they are working. I suggeset one of the following:
ping - With Ping class in:
using System.Net.NetworkInformation;
private static bool CanPing(string address)
{
Ping myping = new Ping();
try
{
PingReply reply = myping.Send(address, 2000);
if (reply == null)
return false;
return (reply.Status == IPStatus.Success);
}
catch (PingException e)
{
return false;
}
}
Do a "Whats my IP?" through a proxy:
public static void TestProxies()
{
var lowp = new List<WebProxy> { new WebProxy("1.2.3.4", 8080), new WebProxy("5.6.7.8", 80) };
Parallel.ForEach(lowp, wp => {
var success = false;
var errorMsg = "";
var sw = new Stopwatch();
try
{
sw.Start();
var response = new RestClient
{
BaseUrl = "https://webapi.theproxisright.com/",
Proxy = wp
}.Execute(new RestRequest { Resource = "api/ip", Method = Method.GET, Timeout = 10000, RequestFormat = DataFormat.Json });
if (response.ErrorException != null)
throw response.ErrorException;
success = (response.Content == wp.Address.Host);
}
catch (Exception ex)
{
errorMsg = ex.Message;
}
finally
{
sw.Stop();
}
});
}

How to read and send data to client from server?

I'm trying to make a server client using a local console server on my pc and a client on windows phone 8.1. The problem that I have is that I don't know how to read the incoming data from the client. I've searched the internet and read serveral microsoft tutorials but they do not explain how to read the incoming data in the server. Here's what I have.
Client on windows phone 8.1:
private async void tryConnect()
{
if (connected)
{
StatusLabel.Text = "Already connected";
return;
}
try
{
// serverHostnameString = "127.0.0.1"
// serverPort = "1330"
StatusLabel.Text = "Trying to connect ...";
serverHost = new HostName(serverHostnameString);
// Try to connect to the
await clientSocket.ConnectAsync(serverHost, serverPort);
connected = true;
StatusLabel.Text = "Connection established" + Environment.NewLine;
}
catch (Exception exception)
{
// If this is an unknown status,
// it means that the error is fatal and retry will likely fail.
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
{
throw;
}
StatusLabel.Text = "Connect failed with error: " + exception.Message;
// Could retry the connection, but for this simple example
// just close the socket.
closing = true;
// the Close method is mapped to the C# Dispose
clientSocket.Dispose();
clientSocket = null;
}
}
private async void sendData(string data)
{
if (!connected)
{
StatusLabel.Text = "Must be connected to send!";
return;
}
UInt32 len = 0; // Gets the UTF-8 string length.
try
{
StatusLabel.Text = "Trying to send data ...";
// add a newline to the text to send
string sendData = "jo";
DataWriter writer = new DataWriter(clientSocket.OutputStream);
len = writer.MeasureString(sendData); // Gets the UTF-8 string length.
// Call StoreAsync method to store the data to a backing stream
await writer.StoreAsync();
StatusLabel.Text = "Data was sent" + Environment.NewLine;
// detach the stream and close it
writer.DetachStream();
writer.Dispose();
}
catch (Exception exception)
{
// If this is an unknown status,
// it means that the error is fatal and retry will likely fail.
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
{
throw;
}
StatusLabel.Text = "Send data or receive failed with error: " + exception.Message;
// Could retry the connection, but for this simple example
// just close the socket.
closing = true;
clientSocket.Dispose();
clientSocket = null;
connected = false;
}
}
(from http://msdn.microsoft.com/en-us/library/windows/apps/xaml/jj150599.aspx)
And the server:
public class Server
{
private TcpClient incomingClient;
public Server()
{
TcpListener listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1330);
listener.Start();
Console.WriteLine("Waiting for connection...");
while (true)
{
//AcceptTcpClient waits for a connection from the client
incomingClient = listener.AcceptTcpClient();
//start a new thread to handle this connection so we can go back to waiting for another client
Thread thread = new Thread(HandleClientThread);
thread.IsBackground = true;
thread.Start(incomingClient);
}
}
private void HandleClientThread(object obj)
{
TcpClient client = obj as TcpClient;
Console.WriteLine("Connection found!");
while (true)
{
//how to read and send data back?
}
}
}
It comes to the point where the server prints 'Connection found!', but I don't know how to go further.
Any help is appreciated!
EDIT:
Now my handleclientthread method looks like this:
private void HandleClientThread(object obj)
{
TcpClient client = obj as TcpClient;
netStream = client.GetStream();
byte[] rcvBuffer = new byte[500]; // Receive buffer
int bytesRcvd; // Received byte count
int totalBytesEchoed = 0;
Console.WriteLine("Connection found!");
while (true)
{
while ((bytesRcvd = netStream.Read(rcvBuffer, 0, rcvBuffer.Length)) > 0)
{
netStream.Write(rcvBuffer, 0, bytesRcvd);
totalBytesEchoed += bytesRcvd;
}
Console.WriteLine(totalBytesEchoed);
}
}
But it still doesn't write the bytes to the console
So... after a lot of searching the internet I have found a solution...
Server: to read from the server and send data back to the phone:
// method in a new thread, for each connection
private void HandleClientThread(object obj)
{
TcpClient client = obj as TcpClient;
netStream = client.GetStream();
Console.WriteLine("Connection found!");
while (true)
{
// read data
byte[] buffer = new byte[1024];
int totalRead = 0;
do
{
int read = client.GetStream().Read(buffer, totalRead, buffer.Length - totalRead);
totalRead += read;
} while (client.GetStream().DataAvailable);
string received = Encoding.ASCII.GetString(buffer, 0, totalRead);
Console.WriteLine("\nResponse from client: {0}", received);
// do some actions
byte[] bytes = Encoding.ASCII.GetBytes(received);
// send data back
client.GetStream().WriteAsync(bytes, 0, bytes.Length);
}
}
Phone(client): to send messages from the phone and read the messages from server:
private async void sendData(string dataToSend)
// import for AsBuffer(): using System.Runtime.InteropServices.WindowsRuntime;
{
if (!connected)
{
StatusLabel.Text = "Status: Must be connected to send!";
return;
}
try
{
byte[] data = GetBytes(dataToSend);
IBuffer buffer = data.AsBuffer();
StatusLabel.Text = "Status: Trying to send data ...";
await clientSocket.OutputStream.WriteAsync(buffer);
StatusLabel.Text = "Status: Data was sent" + Environment.NewLine;
}
catch (Exception exception)
{
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
{
throw;
}
StatusLabel.Text = "Status: Send data or receive failed with error: " + exception.Message;
closing = true;
clientSocket.Dispose();
clientSocket = null;
connected = false;
}
readData();
}
private async void readData()
{
StatusLabel.Text = "Trying to receive data ...";
try
{
IBuffer buffer = new byte[1024].AsBuffer();
await clientSocket.InputStream.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.Partial);
byte[] result = buffer.ToArray();
StatusLabel.Text = GetString(result);
}
catch (Exception exception)
{
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
{
throw;
}
StatusLabel.Text = "Receive failed with error: " + exception.Message;
closing = true;
clientSocket.Dispose();
clientSocket = null;
connected = false;
}
}
The 'await clientSocket.InputStream.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.Partial)' command in the readData method was very unclear for me. I didn't know you had to make a new buffer, and the ReadAsync-method fills it(as i inderstand it). Found it here: StreamSocket.InputStreamOptions.ReadAsync hangs when using Wait()

Socket.Receive() stuck

I'm practicing my C# after having missed out on it in about two years and writing a client for a server. Anyways, the problem is that Socket.Receive() seems to be stuck (my loop doesn't actually get through, tested it).. Here's my call in Program.cs: byte[] buffer = new byte[7];
hSocket.Receive(buffer, 0, buffer.Length, 500);And here's the snippet of my APISocket.cs public bool Connect(string ServerIP, int ServerPort, int Timeout)
{
TimeoutObject.Reset();
SocketException = null;
try
{
Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint IPEndPoint = new IPEndPoint(IPAddress.Parse(ServerIP), ServerPort);
object state = new object();
Socket.BeginConnect(IPEndPoint, new AsyncCallback(CallBackMethod), state);
if (TimeoutObject.WaitOne(Timeout, false))
{
if (IsConnected)
return true;
else
return false;
}
else
{
return false;
}
}
catch (Exception Ex)
{
SocketException = Ex;
}
return false;
}
private void CallBackMethod(IAsyncResult AsyncResult)
{
try
{
IsConnected = false;
if (Socket.Connected)
{
IsConnected = true;
}
}
catch (Exception Ex)
{
IsConnected = false;
SocketException = Ex;
}
finally
{
TimeoutObject.Set();
}
}
public void Receive(byte[] buffer, int offset, int size, int timeout)
{
SocketException = null;
int startTick = Environment.TickCount;
int received = 0;
do
{
if (Environment.TickCount > startTick + timeout)
{
SocketException = new Exception("Timeout.");
return;
}
try
{
received += Socket.Receive(buffer, offset + received, size - received, SocketFlags.None);
}
catch (SocketException Ex)
{
if (Ex.SocketErrorCode == SocketError.WouldBlock ||
Ex.SocketErrorCode == SocketError.IOPending ||
Ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
{
Thread.Sleep(30);
}
else
{
SocketException = Ex;
return;
}
}
} while (received < size);
}
I have no idea where I'm going wrong, any help would be appreciated..
Socket.Receive() is a blocking call. If there is no data available it will block until there is data available to read. See MSDN.
If no data is available for reading, the Receive method will block until data is available, unless a time-out value was set by using Socket.ReceiveTimeout. If the time-out value was exceeded, the Receive call will throw a SocketException.

Java Equivalent Method to Test TCP Connection

In C# to test if UltraVNC was up and running on a local machine I would do this
public static bool TestAvailablility(int port, string responseStartsWith)
{
bool toReturn = false;
try
{
using (TcpClient client1 = new TcpClient())
{
client1.ReceiveTimeout = 10000;
client1.SendTimeout = 10000;
client1.Connect("localhost", port);
using (NetworkStream stream = client1.GetStream())
{
Byte[] response = new Byte[4096];
Int32 bytes = 0;
string serverReturnString = null;
bytes = stream.Read(response, 0, response.Length);
serverReturnString = System.Text.Encoding.ASCII.GetString(response, 0, bytes);
Console.WriteLine("TestAvailablility: serverReturnString = {0}", serverReturnString);
if (serverReturnString.StartsWith(responseStartsWith, StringComparison.OrdinalIgnoreCase))
{
toReturn = true;
}
}
}
}
catch (Exception ex) // SocketException for connect, IOException for the read.
{
Console.WriteLine("TestAvailable - Could not connect to VNC server. Exception info: ", ex);
}
return toReturn;
}
I'm new to Java so I'm hoping someone can help me with an equivalent method to preform this action.
Here's what I came up with:
FYI using Autocomplete in Eclipse + Java API you can translate C# to Java pretty easily.
public static boolean testAvailablility(int port, String responseStartsWith) {
boolean toReturn = false;
try {
Socket client1 = new Socket();
client1.setSoTimeout(10000);
client1.bind(new InetSocketAddress("localhost", port));
InputStream stream = client1.getInputStream();
byte[] response = new byte[4096];
int bytes = 0;
String serverReturnString = null;
bytes = stream.read(response, 0, response.length);
serverReturnString = String.valueOf(bytes);
System.out.println("TestAvailablility: serverReturnString = {0} " + serverReturnString);
if (serverReturnString.toLowerCase().startsWith(responseStartsWith.toLowerCase()))
toReturn = true;
} catch (Exception ex) // SocketException for connect, IOException for
// the read.
{
System.out.println("TestAvailable - Could not connect to VNC server. Exception info: ");
ex.printStackTrace();
}
return toReturn;
}

Testing SMTP server is running via C#

How can I test SMTP is up and running via C# without sending a message.
I could of course try:
try{
// send email to "nonsense#example.com"
}
catch
{
// log "smtp is down"
}
There must be a more tidy way to do this.
You can try saying EHLO to your server and see if it responds with 250 OK. Of course this test doesn't guarantee you that you will succeed sending the mail later, but it is a good indication.
And here's a sample:
class Program
{
static void Main(string[] args)
{
using (var client = new TcpClient())
{
var server = "smtp.gmail.com";
var port = 465;
client.Connect(server, port);
// As GMail requires SSL we should use SslStream
// If your SMTP server doesn't support SSL you can
// work directly with the underlying stream
using (var stream = client.GetStream())
using (var sslStream = new SslStream(stream))
{
sslStream.AuthenticateAsClient(server);
using (var writer = new StreamWriter(sslStream))
using (var reader = new StreamReader(sslStream))
{
writer.WriteLine("EHLO " + server);
writer.Flush();
Console.WriteLine(reader.ReadLine());
// GMail responds with: 220 mx.google.com ESMTP
}
}
}
}
}
And here's the list of codes to expect.
I use this method and classes to validate the credentials (link to github):
public static bool ValidateCredentials(string login, string password, string server, int port, bool enableSsl) {
SmtpConnectorBase connector;
if (enableSsl) {
connector = new SmtpConnectorWithSsl(server, port);
} else {
connector = new SmtpConnectorWithoutSsl(server, port);
}
if (!connector.CheckResponse(220)) {
return false;
}
connector.SendData($"HELO {Dns.GetHostName()}{SmtpConnectorBase.EOF}");
if (!connector.CheckResponse(250)) {
return false;
}
connector.SendData($"AUTH LOGIN{SmtpConnectorBase.EOF}");
if (!connector.CheckResponse(334)) {
return false;
}
connector.SendData(Convert.ToBase64String(Encoding.UTF8.GetBytes($"{login}")) + SmtpConnectorBase.EOF);
if (!connector.CheckResponse(334)) {
return false;
}
connector.SendData(Convert.ToBase64String(Encoding.UTF8.GetBytes($"{password}")) + SmtpConnectorBase.EOF);
if (!connector.CheckResponse(235)) {
return false;
}
return true;
}
SmtpConnectorBase:
internal abstract class SmtpConnectorBase {
protected string SmtpServerAddress { get; set; }
protected int Port { get; set; }
public const string EOF = "\r\n";
protected SmtpConnectorBase(string smtpServerAddress, int port) {
SmtpServerAddress = smtpServerAddress;
Port = port;
}
public abstract bool CheckResponse(int expectedCode);
public abstract void SendData(string data);
}
SmtpConnectorWithoutSsl:
internal class SmtpConnectorWithoutSsl : SmtpConnectorBase {
private Socket _socket = null;
public SmtpConnectorWithoutSsl(string smtpServerAddress, int port) : base(smtpServerAddress, port) {
IPHostEntry hostEntry = Dns.GetHostEntry(smtpServerAddress);
IPEndPoint endPoint = new IPEndPoint(hostEntry.AddressList[0], port);
_socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
//try to connect and test the rsponse for code 220 = success
_socket.Connect(endPoint);
}
~SmtpConnectorWithoutSsl() {
try {
if (_socket != null) {
_socket.Close();
_socket.Dispose();
_socket = null;
}
} catch (Exception) {
;
}
}
public override bool CheckResponse(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.UTF8.GetString(responseArray);
int responseCode = Convert.ToInt32(responseData.Substring(0, 3));
if (responseCode == expectedCode) {
return true;
}
return false;
}
public override void SendData(string data) {
byte[] dataArray = Encoding.UTF8.GetBytes(data);
_socket.Send(dataArray, 0, dataArray.Length, SocketFlags.None);
}
}
SmtpConnectorWithSsl:
internal class SmtpConnectorWithSsl : SmtpConnectorBase {
private SslStream _sslStream = null;
private TcpClient _client = null;
public SmtpConnectorWithSsl(string smtpServerAddress, int port) : base(smtpServerAddress, port) {
TcpClient client = new TcpClient(smtpServerAddress, port);
_sslStream = new SslStream(
client.GetStream(),
false,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
// The server name must match the name on the server certificate.
try {
_sslStream.AuthenticateAsClient(smtpServerAddress);
} catch (AuthenticationException e) {
_sslStream = null;
Console.WriteLine("Exception: {0}", e.Message);
if (e.InnerException != null) {
Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
}
Console.WriteLine("Authentication failed - closing the connection.");
client.Close();
}
}
~SmtpConnectorWithSsl() {
try {
if (_sslStream != null) {
_sslStream.Close();
_sslStream.Dispose();
_sslStream = null;
}
} catch (Exception) {
;
}
try {
if (_client != null) {
_client.Close();
_client = null;
}
} catch (Exception) {
;
}
}
// The following method is invoked by the RemoteCertificateValidationDelegate.
private static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors) {
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
Console.WriteLine("Certificate error: {0}", sslPolicyErrors);
// Do not allow this client to communicate with unauthenticated servers.
return false;
}
public override bool CheckResponse(int expectedCode) {
if (_sslStream == null) {
return false;
}
var message = ReadMessageFromStream(_sslStream);
int responseCode = Convert.ToInt32(message.Substring(0, 3));
if (responseCode == expectedCode) {
return true;
}
return false;
}
public override void SendData(string data) {
byte[] messsage = Encoding.UTF8.GetBytes(data);
// Send hello message to the server.
_sslStream.Write(messsage);
_sslStream.Flush();
}
private string ReadMessageFromStream(SslStream stream) {
byte[] buffer = new byte[2048];
StringBuilder messageData = new StringBuilder();
int bytes = -1;
do {
bytes = stream.Read(buffer, 0, buffer.Length);
// Use Decoder class to convert from bytes to UTF8
// in case a character spans two buffers.
Decoder decoder = Encoding.UTF8.GetDecoder();
char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
decoder.GetChars(buffer, 0, bytes, chars, 0);
messageData.Append(chars);
// Check for EOF.
if (messageData.ToString().IndexOf(EOF) != -1) {
break;
}
} while (bytes != 0);
return messageData.ToString();
}
}
You could open up the port (25) with a socket or TcpClient and see if it responds.
Open a socket connection to the smtp server on port 25 and see if you get anything. If not, no smtp server.
Here is a nice open source tool (does more than MX):
http://www.codeproject.com/KB/IP/DNS_NET_Resolver.aspx

Categories

Resources