SmtpClient hangs with no exception thrown if wrong port was specified - c#

I was trying to send emails in my Asp.Net C# application using port 465 with host "smtp.gmail.com" but the whole application hangs (keeps loading). When debugging it's stuck at SmtpClient.Send(msg).
Regardless of the credentials specified, it doesn't throw any exceptions to catch or any timeout errors. I have to close or refresh the page to regain access to the page.
If I put port 587 instead then every thing works fine and the SmtpClient.Send responds and sends the email or returns a proper exception such as operation timeout or failure sending email based on the credentials.
I simplified the code below for demonstration:
var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 465,
EnableSsl = true,
Timeout = 200, // or any value it doesn't solve the problem
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential("name#gmail.com", "password")
};
var msg = new MailMessage("name#gmail.com", "name#gmail.com", "Any subject", "Any body");
smtp.Send(msg); // stuck here
smtp.Dispose(); // never reached
msg.Dispose();
I tried SendAsync and reduced the timeout interval but this did not solve the problem. I think the problem is that smtp.gmail.com was reached but did not respond properly to port 465 and that's why the method was stuck.
I need to avoid such behavior since my application allows dynamic settings of the smtp server details and I don't want the whole application to hang in case of wrong details were entered.
Thank you,

Found this answer in case anyone gets here
SmtpClient Timeout doesn't work
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = socket.BeginConnect("192.168.1.180", 25, null, null);
// Two second timeout
bool success = result.AsyncWaitHandle.WaitOne(2000, true);
if (!success) {
socket.Close();
throw new ApplicationException("Failed to connect server.");
}

Wrap your SmptClient in a using statement, to ensure that Dispose is called.
I'm not sure if this is the cause or your problem or not, but I was having the same issues (sent correctly the 1st time, and often fails afterwards) at this has rectified it for me.

Related

MailKit: The handshake failed due to an unexpected packet format

I got exception when I try to connect to my SMTP server using MailKit SmtpClient. BUT my mails have been sent successfully if I use System.Net.Mail.SmtpClient with the same parameters!
The exception message: An error occurred while attempting to establish an SSL or TLS connection.
The inner exception message: The handshake failed due to an unexpected packet format.
Questions
Why does MailKit.Net.Smtp.SmtpClient throw exception but System.Net.Mail.SmtpClient doesn't? What is the difference between them?
How to fix it?
Code
Initialize the parameters required for mail sending:
var host = "myhost.com";
var port = 2525;
var from = "from#mydomain.com";
var to = "to#mydomain.com";
var username = "from#mydomain.com";
var password = "myPassword";
var enableSsl = true;
Sending mail using System.Net.Mail.SmtpClient:
var client = new System.Net.Mail.SmtpClient
{
Host = host,
Port = port,
EnableSsl = enableSsl,
Credentials = new NetworkCredential(username, password)
};
client.Send(from, to, "subject", "body"); // success.
But when I try to connect to the host using MailKit with the same host and port, I got the exception:
var mailKitClient = new MailKit.Net.Smtp.SmtpClient();
mailKitClient.Connect(host, port, enableSsl); // it throws the exception.
The problem is that you are connecting to a plain-text port and expecting SSL.
In MailKit, the true/false useSsl parameter is used to decide whether or not to connect in SSL mode or plain-text mode.
In System.Net.Mail, they don't support connecting in SSL mode, they only support upgrading a plain-text connection to SSL mode using the STARTTLS command once the connection has been established.
To overcome this, MailKit has a different Connect() method that takes an enum value SecureSocketOptions.
What you want is SecureSocketOptions.StartTls:
var mailKitClient = new MailKit.Net.Smtp.SmtpClient();
mailKitClient.Connect(host, port, SecureSOcketOptions.StartTls);

Trying to send a mail from a .NET 5 console application using SMTP

Context
I'm developing an application using WPF and .NET 5 for a research institute. The client would like to receive an email when something goes wrong during an experience because it can last several days.
Before adding this feature to the software, I made a simple test program to send an email from a console application and it worked... mostly.
Disclaimer : I know there are tons of threads about this subject, and I have read nearly a hundred. The code itself doesn't seem to be the problem and I did setup the google account with two factor authentication (I also tried the "Less secure app" option).
The problem
I said the problem doesn't seem to be the code because I actually managed to send emails that way, using my personal gmail address. Problem is, I don't want to use my own address to send mail to the client... So I created an new gmail address and enabled 2FA. And when I try to send an email with the new address I get this in the emitter inbox :
What I already tried
I've tried various recipient and port with the same result. I've looked for this issue on google support, on forums and on youtube but I didn't find anything similar to my problem. I even waited 2 weeks to make sure it wasn't because the address was too recent and judged as "untrustworthy" or something like that.
The code I used
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
MailAddress to = new MailAddress("recipient#gmail.com");
MailAddress from = new MailAddress("emitter#gmail.com");
MailMessage message = new MailMessage(from, to);
message.Subject = "Using the new SMTP client.";
message.Body = "Using this new feature, you can send an e-mail message from an application very easily.";
message.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;
SmtpClient client = new SmtpClient
{
EnableSsl = true,
Port = 587,
Host = "smtp.gmail.com",
Timeout = 10000,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential("emitter#gmail.com", "app-specific-password")
};
try
{
client.Send(message);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in Main(): {0}",
ex.ToString());
}
message.Dispose();
}
What I would like
I just need to be able to send a few emails per day, to one or two contacts, from a WPF application. Nothing fancy. It seems that the two options I got are :
to find how to create a neutral email address that can use gmail smtp
or
to find another (easy and free) solution to send emails.
Can you help me with that, please ?

Mailkit SMTP - StartTLS & TLS flags

I am trying to connect to iCloud via SmtpClient
The settings I am using are as follows:
Server name: smtp.mail.me.com
SSL Required: Yes
If you see an error message when using SSL, try using TLS or STARTTLS instead.
Port: 587
SMTP Authentication Required: Yes - with relevant username and password
If I use SSL I get "Handshake failed due to unexpected packet format"
If I don't use SSL visual studio debugger hangs on connect.
I think the problem is I am not telling the SmtpClient to use tls but I cant find documentation on how to do this.
The code is as follows:
using (var client = new SmtpClient()) {
client.Timeout = 1000 * 20;
//client.Capabilities.
client.AuthenticationMechanisms.Remove ("XOAUTH2");
client.Connect("SMTP.mail.me.com", 587, false); //dies here
//client.Connect(servername, port, useSsl);
//can I set tls or starttls here??
client.Authenticate(username, password);
client.Send(FormatOptions.Default, message);
}
Am I able to set TLS or StartTLS manually. One thing I did try is the following but it did not seem to work
client.Connect(new Uri("smtp://" + servername + ":" + port + "/?starttls=true"));
Thanks for any help with this.
The Connect() method that you are using only allows enabling/disabling SSL-wrapped connections which is not the same thing as StartTLS.
Due to the confusion, I've implemented a separate Connect() method that makes this more obvious what is going on:
using (var client = new SmtpClient()) {
// Note: don't set a timeout unless you REALLY know what you are doing.
//client.Timeout = 1000 * 20;
client.Connect ("smtp.mail.me.com", 587, SecureSocketOptions.StartTls);
client.Authenticate (username, password);
client.Send (message);
}
Try that.
You can set your options to "SecureSocketOptions.Auto"
something like this
await client.ConnectAsync(mailService.Host, mailService.Port, SecureSocketOptions.Auto);
MailKit will automatically decide to use SSL or TLS.
According to MailKit Doc
Connect(string host,int port,bool useSsl,CancellationToken cancellationToken = null)
The useSsl argument only controls whether or not the client makes an SSL-wrapped connection. In other words, even if the useSsl parameter is false, SSL/TLS may still be used if the mail server supports the STARTTLS extension.
This worked for me over the SecureSocketOptions.Auto option mentioned previously:
client.Connect(host, port, SecureSocketOptions.None);

Cannot connect to remote server while sending mail

I'm using code below to send an email and it just doesn't work and gives an exception:
MailDefinition md = new MailDefinition();
md.IsBodyHtml = true;
md.From = EMAIL_FROM;
md.Subject = "لینک تغییر رمز";
MailMessage mm = md.CreateMailMessage(to, null, new System.Web.UI.Control());
string body = link;
mm.Body = body;
SmtpClient smtp = new SmtpClient();
smtp.UseDefaultCredentials = false;
smtp.Host = EMAIL_SMTP;
smtp.Port = EMAIL_PORT;
smtp.Credentials = new System.Net.NetworkCredential(EMAIL_FROM, EMAIL_PASSWORD);
smtp.Send(mm);
where sender username & password are checked and correct, port is 25 and smtp is mail.kawp.co.ir, on send function it throws an exception with the below error message
{"Unable to connect to the remote server"}
{"A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond xx.xxx.xx.xx:25"}
I'm using the same method and function for my other domains which are hosted on the same server and they are working fine. What possibly could be causing the problem here?
p.s: I also can't handshake with the mail.kawp.co.ir 25 via telnet
Thanks in advance
Changing port 25 to 587 fixed my problem because my isp is blocking port 25 to prevent spamming.
If you cannot perform the handshake with Telnet, then you're not going to get it to connect programmatically. From what it sounds like, the server isn't configured to accept SMTP messages. You'll need to get that enabled before you can get your code to work.

Sending email through SMTP fails : MailBox name not allowed

I am trying to send an email through an SMTP server but it fails giving me the following error:
MailBox name not allowed. The server response was Senders must have
valid reverse DNS
Unfortunately I could not find meaningfull information to solve the problem
Here is my method:
public void SendSmtp()
{
try
{
using (MailMessage message = new MailMessage())
{
message.From = new MailAddress("some#email.com");
message.To.Add(new MailAddress("other#email.com"));
message.Subject = "subject";
message.Body = "body";
message.IsBodyHtml = true;
// NetworkCredential basicCredential = new NetworkCredential("test#test.com", "password");
try
{
using (SmtpClient client = new SmtpClient())
{
client.Host = "mail.host.com";
client.Port = 25;
client.UseDefaultCredentials = true;
// client.Credentials = basicCredential;
client.Send(message);
MessageBox.Show("Success!!");
}
}
finally
{
//dispose the client
message.Dispose();
}
}
}
catch (SmtpFailedRecipientsException ex)
{
for (int i = 0; i < ex.InnerExceptions.Length; i++)
{
SmtpStatusCode status = ex.InnerExceptions[i].StatusCode;
if (status == SmtpStatusCode.MailboxBusy ||
status == SmtpStatusCode.MailboxUnavailable)
{
Console.WriteLine("Delivery failed - retrying in 5 seconds.");
System.Threading.Thread.Sleep(5000);
//client.Send(message);
}
else
{
Console.WriteLine("Failed to deliver message to {0}",
ex.InnerExceptions[i].FailedRecipient);
}
}
}
}
This works well when I try it on a different server or my local machine not sure why.
I set up my SMTP grant access to my server.
Please advice.
The error's a direct response from the SMTP server that your code is attempting to connect to. Your client machine does not have a valid reverse DNS mapping (e.g. 127.0.0.1 -> localhost), so the SMTP server is rejecting the connection.
It could be something as simple as your client identifying itself as example.com, but when the SMTP server does a reverse lookup, the server's IP comes back as system-1-2-3.4.hostingprovider.com or similar.
Looking back at my question, I can tell you that if you face this issue, It is not an issue in the code really it is more of a network issue.
A quick way to test this is to do run your code in a less locked down environment. I was getting this error only on my production server. It worked fine in development.
So this means you need to close visual studio and investigate. The error could be misleading so don't rely on it 100% instead use tools to debug your issue. I used wireshark to examine the packets and I noticed an IP that being denied on my SMTP server.
I didn't realize because my server had multiple network cards in my case. Something that I could not easily guessed. So my advise is to use tools to watch traffic network and you will find the reason.
Don't guess, use tools* to give you the answers.
*tools: in addition to wireshark, sites like mxtoolbox could be very helpful
Old thread, but if anybody else has this issue, for me the issue was related to the "FROM" attribute. On the smtp server there is allowed "from" address which you have to request to your email server admins.

Categories