I am making an SMTP mail application with C#.Net. It is working ok for Gmail settings, but I have to work it for a connection to VSNL. I am getting an exception: "Failure sending mail"
My settings seem perfect. What is the problem? Why am I getting the exception?
MailMessage mailMsg = new MailMessage();
MailAddress mailAddress = new MailAddress("mail#vsnl.net");
mailMsg.To.Add(textboxsecondry.Text);
mailMsg.From = mailAddress;
// Subject and Body
mailMsg.Subject = "Testing mail..";
mailMsg.Body = "connection testing..";
SmtpClient smtpClient = new SmtpClient("smtp.vsnl.net", 25);
var credentials = new System.Net.NetworkCredential("mail#vsnl.net", "password");
smtpClient.EnableSsl = true;
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = credentials;
smtpClient.Send(mailMsg);
I am getting an exception following...
System.IO.IOException: Unable to read data from the transport connection: net_io_connectionclosed.
at System.Net.Mail.SmtpReplyReaderFactory.ProcessRead(Byte[] buffer, Int32 offset, Int32 read, Boolean readLine)
at System.Net.Mail.SmtpReplyReaderFactory.ReadLines(SmtpReplyReader caller, Boolean oneLine)
at System.Net.Mail.SmtpReplyReaderFactory.ReadLine(SmtpReplyReader caller)
at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port)
at System.Net.Mail.SmtpClient.GetConnection()
at System.Net.Mail.SmtpClient.Send(MailMessage message)
Check the InnerException of the exception, should tell you why it failed.
Try wrapping the Send call in a try catch block to help identify the underlying problem.
e.g.
try
{
smtpClient.Send(mailMsg);
}
catch (Exception ex)
{
Console.WriteLine(ex); //Should print stacktrace + details of inner exception
if (ex.InnerException != null)
{
Console.WriteLine("InnerException is: {0}",ex.InnerException);
}
}
This information will help identify what the problem is...
Make sure your Anti Virus is blocking sending mails. In my case McAfee Access protection Rules were blocking sending mails, untick blocks and reports.
I used some but i am checking only this if send mail fails:
default value is false;
but it can't be change to true;
smtpClient.Port = smtpServerPort;
smtpClient.UseDefaultCredentials = false;
smtpClient.Timeout = 100000;
smtpClient.Credentials = new System.Net.NetworkCredential(mailerEmailAddress, mailerPassword);
smtpClient.EnableSsl = EnableSsl;
All function must be surround by a try catch;
Try by removing
smtpClient.EnableSsl = true;
I am not sure whether vsnl supports SSL and the port number you are using
Without seeing your code, it is difficult to find the reason for exception. Following are assumptions:
The serverHost of VSNL is smtp.vsnl.net
Exception:
Unable to read data from the transport connection: net_io_connectionclosed
Usually this exception occurs only when there is mismatch in username or password.
Check to see if the machine is being referred to by an IPv6 address. In my case using machine name gave me the same error. Using the ip4 address it did work (i.e. 10.0.0.4). I got rid of ipv6 and it started to work.
Not the solution i was looking for but given my limited understanding of ipv6 I did not know of other choices.
Related
Edit: Things I have tried
On the server running smtp in smpt virtual server I have set IP
address to specific IP and to "all unassigned", in the Access tab of
SMTP Virtual Service, under relay tab, I have added all the IPs to
grant list along with 127.0.0.1
client.ServicePoint.MaxIdleTime = 100;
moved the using (creating of client) to inside of the for loop
Still same problem, 300 seems to be the magic number before it craps out
I have a very extremely weird problem that I have been trying to solve for past week. My task is simple, "send bulk mail", so I created a very simple exe that will send bunch of emails to a gmail account.
After about sending 280, the sending fails with the following error: I have tried both port 587 and 25 and the problem happens on both ports
System.Net.Mail.SmtpException: Failure sending mail. --->
System.IO.IOException: Unable to read data from the transport connection:
net_io_connectionclosed.
at System.Net.Mail.SmtpReplyReaderFactory.ProcessRead(Byte[] buffer, Int32
offset, Int32 read, Boolean readLine)
at System.Net.Mail.SmtpReplyReaderFactory.ReadLines(SmtpReplyReader caller,
Boolean oneLine)
at System.Net.Mail.SmtpReplyReaderFactory.ReadLine(SmtpReplyReader caller)
at System.Net.Mail.SmtpConnection.GetConnection(ServicePoint servicePoint)
at System.Net.Mail.SmtpTransport.GetConnection(ServicePoint servicePoint)
at System.Net.Mail.SmtpClient.GetConnection()
at System.Net.Mail.SmtpClient.Send(MailMessage message)
--- End of inner exception stack trace ---
at System.Net.Mail.SmtpClient.Send(MailMessage message)
Now I will note that if i run the exe again RIGHT after it fails and i try to send ONE email, i get the same error so the issue does not seem to be a coding issue. This is being sent on VPS running windows 2016 and SmarterMail 16 smtp server.
If i wait about an hour and try to send again, i can successfully send another 280. It seems there is some sort of throttling happening somewhere (I already turned off all the throttlings in SmarterMail).
What is weird is, right after it fails, if i use a service like https://www.smtper.net/ and use the same exact settings as i am using in my exe, then the email goes through with out any errors. I am not sure if this is a smtp error, some setting on windows 2016 that wont allow more than x an hour etc.
Below is my actual exe code, as you can see its extremely simple example
static void Main(string[] args)
{
Console.WriteLine("How many emails do you want to send?");
var emailCount = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("How many seconds do you want to delay between each send");
var delay = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("What email address do you want to send to");
var toEmailAddress = Console.ReadLine();
Console.WriteLine($"Sending out {emailCount} with {delay} second delay to {toEmailAddress}");
using (var client = new SmtpClient(ConfigurationManager.AppSettings["SmtpServer"]))
{
for (int i = 1; i <= emailCount; i++)
{
try
{
var body = "this is a test message";
var userName = ConfigurationManager.AppSettings["Username"];
var password = ConfigurationManager.AppSettings["Password"];
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential(userName, password);
client.Port = Convert.ToInt32(ConfigurationManager.AppSettings["Port"]);
//client.EnableSsl = true;
MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress(ConfigurationManager.AppSettings["FromEmail"]);
mailMessage.To.Add(toEmailAddress);
mailMessage.Body = body;
mailMessage.IsBodyHtml = true;
mailMessage.Subject = ConfigurationManager.AppSettings["Subject"];
client.Send(mailMessage);
if (delay > 0)
{
Console.WriteLine("Sleeping...");
Thread.Sleep(delay * 1000);
}
Console.WriteLine($"Email number {i} was sent successfully.");
}
catch (Exception ex)
{
Console.WriteLine($"Failed to send {i} of {emailCount}");
Console.WriteLine(ex.ToString());
}
}
}
Console.WriteLine("Done...press any key to exit");
Console.ReadKey();
}
My code sends e-mails like this:
private void DispatchMail(MailMessage mailMessage)
{
using (var smtpClient = new SmtpClient())
{
smtpClient.Send(mailMessage);
}
}
The MailMessage instances are very simple with a HTML body and no attachments.
The configuration of the SmtpClient is in web.config like this:
<system.net>
<mailSettings>
<smtp from="yourmail#gmail.com">
<network host="mailprovider.org" port="587" enableSsl="true" userName="username#host" password="secret" />
</smtp>
</mailSettings>
</system.net>
Whenever the method DispatchMail is called, the mail is actually sent to the recipient, however I get an exception in the implicitly called SmtpClient.Dispose method.
Exception: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
at System.Net.Security._SslStream.StartFrameBody(Int32 readBytes, Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security._SslStream.StartFrameHeader(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security._SslStream.StartReading(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security._SslStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.TlsStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.Mail.SmtpPooledStream.Dispose(Boolean disposing)
at System.IO.Stream.Close()
at System.IO.Stream.Dispose()
at System.Net.ConnectionPool.Destroy(PooledStream pooledStream)
at System.Net.ConnectionPool.ForceCleanup()
at System.Net.ConnectionPoolManager.CleanupConnectionPool(ServicePoint servicePoint, String groupName)
at System.Net.Mail.SmtpClient.Dispose(Boolean disposing)
at System.Net.Mail.SmtpClient.Dispose()
at QueuedMailDispatcherService.DispatchMail(MailMessage mailMessage)
Inner exception: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
Is this a bug in the .NET Framework 4.5.2 or am I mismanaging the life-cycle of the SMTP client?
The SMTP server in question responds as "Microsoft ESMTP MAIL Service".
Update
First I dismissed this problem since it only happened on my machine, but then it happened on the production machine running same code but with release configuration.
Since this error happens intermittently I have decided to modify the method to use a two-level exception handling strategy where any exception occurring when Dispose is called is ignored.
When I was able to catch this error and step through the framework source it seemed like the offset parameter was corrupted (it was several MB higher than the buffer.Length) somewhere between System.Net.Sockets.NetworkStream.Read and System.Net.Sockets.Socket.Receive. However further inspection of the source does not imply that the offset would be changed. In fact System.Net.Security._SslStream.StartFrameHeader sets offset to 5 higher up in the call stack. This leads me to believe that one of the following things happened:
The debugged machine level code was not matching the source I stepped through in Visual Studio
Some kind of memory corruption (however the problem has persisted through one reboot and on two different machines both in debug and release configuration)
I was actually debugging two different threads without realizing it
There is some kind of difficult rare race condition going on
There is some kind of optimization going wrong, maybe in combination with the race condition
The SMTP server implementation or the network transmission is not reliable during SMTP Quit, however it is a well known SMTP server software and I cannot see why this problem would be intermittent also it does not explain the out of bound offset value.
Try the below sample:
using System.Net.Mail;
private void DispatchMail(string to)
{
var mail = new MailMessage
{
Subject = "subject",
From = new MailAddress(#"sender email", #"sender name")
};
mail.To.Add(to);
mail.Body = "your message body";
var smtp = new SmtpClient(#"smtp mail server address");
smtp.Port = 587;
smtp.Credentials = new System.Net.NetworkCredential("username", "password");
smtp.EnableSsl = true;
smtp.Send(mail);
mail.Dispose();
smtp.Dispose();
}
you can do something like this
var fromAddress = new MailAddress("fromAddress", "My Name");
var toAddress = new MailAddress("gtoAddress ", "Mr Test");
const string fromPassword = "fromPassword";
string subject = "hello";
string body = "how are you doing?";
var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword),
Timeout = 20000
};
using (var message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body
})
{
smtp.Send(message);
}
and enable less secure apps on your Gmail account here
So here is my code which is used to send emails from Unity using a C# script:
public void SendMail() // Mail send function
{
string emailAddress; // variable to store user inputted email
emailAddress = emailInput.text; // variable becomes the email the user types in
mail.From = new MailAddress("hiddenfornow");
mail.To.Add(emailAddress);
SmtpClient smtpServer = new SmtpClient("smtp.gmail.com");
smtpServer.Port = 587;
mail.Subject = "Test Subject" + currentDate;
mail.IsBodyHtml = true; // allows for html
mail.Body = "Testing testing";
smtpServer.Credentials = new System.Net.NetworkCredential("hiddenfornow", "hiddenfornow") as ICredentialsByHost;
smtpServer.EnableSsl = true;
SceneManager.LoadScene("TestScene"); // reloads the scene after user clicks button
ServicePointManager.ServerCertificateValidationCallback =
delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{ return true; };
smtpServer.Send(mail);
Debug.Log("success");
}
This code is working fine to send emails. However, if i enter an incorrect email i will recieve an "smtpfailedrecipientsexception" message.
After this, even entering a correct email address will not work. The smtpfailedrecipientsexception will continue to occur unless you type it correct the first time.
I would like to add some kind of If statement such as this which i've written in pseudocode:
If smtpserver.send(mail)returns smtp error
{
Exit this function
}
else
{
success message
}
I am just not sure how to implement this.
Use exception handling approach to dealing with runtime exception :
try
{
if (smtpserver.send(mail))
return "successful";
}
catch (SmtpFailedRecipientException ex)
{
// log your error
return ex.StatusCode; // return status code as you will know actual error code
}
finally
{
mail.Dispose(); // Dispose your mailmessage as it will clears any stream associated with your mail message such as attachment
}
Available Status Codes
The SmtpClient uses pooling to reduce the overhead of creating new connections to the server. (see: https://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient(v=vs.110).aspx#Remarks)
My assumption is that the SmtpFailedRecientsException is putting the connection into a bad state, so you need to force the connection to close by disposing the client:
public void SendMail() // Mail send function
{
//your code...
SmtpClient smtpServer = new SmtpClient("smtp.gmail.com");
try {
//.... your code continues.....
smtpServer.Send(mail);
Debug.Log("success");
} catch (SmtpFailedRecipientsException) { //or, perhaps any Exception
smtpServer.Dispose();
throw; //rethrow the exception, assuming you're handling it in the calling code
}
}
For future reference, here is the code which worked:
Try
{
smtpServer.Send(mail); // Attempts to send the email
Debug.Log("success");
}
catch (SmtpFailedRecipientsException) // Catches send failure
{
mail.Dispose(); // ends the SMTP connection
SceneManager.LoadScene("SceneName"); //Reloads the scene to clear textboxes
}
When i program with C# to send a mail by batch,my code is like this:
public static bool Send(MailAddress Messagefrom,
string MessageTo,
string MessageSubject,
string MessageBody)
{
MailMessage message = new MailMessage();
message.From = Messagefrom;
message.To.Add(MessageTo);
message.Subject = MessageSubject;
message.Body = MessageBody;
message.BodyEncoding = System.Text.Encoding.UTF8;
//message.SubjectEncoding = Encoding.BigEndianUnicode;
message.IsBodyHtml = true;
message.Priority = MailPriority.High;
MailHelper mh = new MailHelper();
SmtpClient sc = mh.setSmtpClient("smtp.qq.com", 25);
sc.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
try
{
sc.SendAsync(message, message);
}
catch (Exception e)
{
LogHelper.WriteLog("Main send failed....\t the detail info:" +
e.ToString());
return false;
}
return true;
}
This is a problem!When the first mail send failed(for example the mail address is null),the next mail can't be send!
Because i have so much mail wait to send,if this situation,how to fix it?For example the failed mail may still on this table and Administator to deal it by hand.
But this situation probably in Send function,Why this happen?
You have to catch errors in the foreach loop that calls your Send() function and log the errors somewhere:
foreach (var mail in mailsToSend)
{
try
{
// Call your send function
Send(...)
}
catch (Exception ex)
{
// Log the error somewhere (console, file, ...)
Console.WriteLine("Error sending mail {0}", mail);
}
}
This ensures that the application won't crash when one email fails to send and continue sending the other mails.
Also you should use Send() instead of SendAsync() in your Send() function. This is because the SendAsync function starts a new thread for sending the mail, while Send will stop your programs execution until the mail has been sent. One more reason you shouldn't use the SendAsync function is because according to microsoft only 1 mail can be send at a time. That means using the SendAsync function for more then 1 mail will cause it to throw an exception.
I've developed my own delivery extension for Reporting Services 2005, to integrate this with our SaaS marketing solution.
It takes the subscription, and takes a snapshot of the report with a custom set of parameters. It then renders the report, sends an e-mail with a link and the report attached as XLS.
Everything works fine, until mail delivery...
Here's my code for sending e-mail:
public static List<string> SendMail(SubscriptionData data, Stream reportStream, string reportName, string smptServerHostname, int smtpServerPort)
{
List<string> failedRecipients = new List<string>();
MailMessage emailMessage = new MailMessage(data.ReplyTo, data.To);
emailMessage.Priority = data.Priority;
emailMessage.Subject = data.Subject;
emailMessage.IsBodyHtml = false;
emailMessage.Body = data.Comment;
if (reportStream != null)
{
Attachment reportAttachment = new Attachment(reportStream, reportName);
emailMessage.Attachments.Add(reportAttachment);
reportStream.Dispose();
}
try
{
SmtpClient smtp = new SmtpClient(smptServerHostname, smtpServerPort);
// Send the MailMessage
smtp.Send(emailMessage);
}
catch (SmtpFailedRecipientsException ex)
{
// Delivery failed for the recipient. Add the e-mail address to the failedRecipients List
failedRecipients.Add(ex.FailedRecipient);
}
catch (SmtpFailedRecipientException ex)
{
// Delivery failed for the recipient. Add the e-mail address to the failedRecipients List
failedRecipients.Add(ex.FailedRecipient);
}
catch (SmtpException ex)
{
throw ex;
}
catch (Exception ex)
{
throw ex;
}
// Return the List of failed recipient e-mail addresses, so the client can maintain its list.
return failedRecipients;
}
Values for SmtpServerHostname is localhost, and port is 25.
I veryfied that I can actually send mail, by using Telnet. And it works.
Here's the error message I get from SSRS:
ReportingServicesService!notification!4!08/28/2008-11:26:17:: Notification 6ab32b8d-296e-47a2-8d96-09e81222985c completed. Success: False, Status: Exception Message: Failure sending mail. Stacktrace: at MyDeliveryExtension.MailDelivery.SendMail(SubscriptionData data, Stream reportStream, String reportName, String smptServerHostname, Int32 smtpServerPort) in C:\inetpub\wwwroot\CustomReporting\MyDeliveryExtension\MailDelivery.cs:line 48
at MyDeliveryExtension.MyDelivery.Deliver(Notification notification) in C:\inetpub\wwwroot\CustomReporting\MyDeliveryExtension\MyDelivery.cs:line 153, DeliveryExtension: My Delivery, Report: Clicks Development, Attempt 1
ReportingServicesService!dbpolling!4!08/28/2008-11:26:17:: NotificationPolling finished processing item 6ab32b8d-296e-47a2-8d96-09e81222985c
Could this have something to do with Trust/Code Access Security?
My delivery extension is granted full trust in rssrvpolicy.config:
<CodeGroup
class="UnionCodeGroup"
version="1"
PermissionSetName="FullTrust"
Name="MyDelivery_CodeGroup"
Description="Code group for MyDelivery extension">
<IMembershipCondition class="UrlMembershipCondition" version="1" Url="C:\Program Files\Microsoft SQL Server\MSSQL.2\Reporting Services\ReportServer\bin\MyDeliveryExtension.dll" />
</CodeGroup>
Could trust be an issue here?
Another theory: SQL Server and SSRS was installed in the security context of Local System. Am I right, or is this service account restricted access to any network resource? Even its own SMTP Server?
I tried changing all SQL Server Services logons to Administrator - but still without any success.
I also tried logging onto the SMTP server in my code, by proviiding: NetworkCredential("Administrator", "password") and also NetworkCredential("Administrator", "password", "MyRepServer")
Can anyone help here, please?
What's at:
at MyDeliveryExtension.MailDelivery.SendMail(SubscriptionData data, Stream reportStream, String reportName, String smptServerHostname, Int32 smtpServerPort)
in C:\inetpub\wwwroot\CustomReporting\MyDeliveryExtension\MailDelivery.cs:line 48
at MyDeliveryExtension.MyDelivery.Deliver(Notification notification)
in C:\inetpub\wwwroot\CustomReporting\MyDeliveryExtension\MyDelivery.cs:line 153
Also you seem to be disposing the report stream, but that should be done by whatever opened that stream, not your method (it won't be obvious that attaching a stream disposes it).
You're losing part of your stack trace due to how you re-throw exceptions. Don't throw the ex variable, just throw is enough.
Try this tweak:
public static List<string> SendMail(SubscriptionData data, Stream reportStream, string reportName, string smptServerHostname, int smtpServerPort)
{
List<string> failedRecipients = new List<string>();
MailMessage emailMessage = new MailMessage(data.ReplyTo, data.To) {
Priority = data.Priority,
Subject = data.Subject,
IsBodyHtml = false,
Body = data.Comment
};
if (reportStream != null)
emailMessage.Attachments.Add(new Attachment(reportStream, reportName));
try
{
SmtpClient smtp = new SmtpClient(smptServerHostname, smtpServerPort);
// Send the MailMessage
smtp.Send(emailMessage);
}
catch (SmtpFailedRecipientsException ex)
{
// Delivery failed for the recipient. Add the e-mail address to the failedRecipients List
failedRecipients.Add(ex.FailedRecipient);
//are you missing a loop here? only one failed address will ever be returned
}
catch (SmtpFailedRecipientException ex)
{
// Delivery failed for the recipient. Add the e-mail address to the failedRecipients List
failedRecipients.Add(ex.FailedRecipient);
}
// Return the List of failed recipient e-mail addresses, so the client can maintain its list.
return failedRecipients;
}
I tried to remove the reportStream Attachment:
//if (reportStream != null)
//emailMessage.Attachments.Add(new Attachment(reportStream, reportName));
And now it works fine.
So it is something to do with the reportStream.
After fooling around with the tunctionallity that gets the reportStream, I was able to fix the mail sending problem.
The error wasn't in the SendMail method, but somewehere else. The exception was thrown in the context, of SendMail though. Buggered!
That's why you have to avoid:
catch (Exception ex)
{
throw ex;
}
As that basically cloaks your exception in a new one.
If you use:
catch (Exception ex)
{
throw; //note: no ex
}
It keeps the original exception and stack trace.
FileStream m_fileStream = null;
m_files = notification.Report.Render(format, null);
RenderedOutputFile m_renderedOutputFile = m_files[0];
m_fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write);
m_renderedOutputFile.Data.Seek((long)0, SeekOrigin.Begin);
byte[] arr = new byte[(int)m_renderedOutputFile.Data.Length + 1];
m_renderedOutputFile.Data.Read(arr, 0, (int)m_renderedOutputFile.Data.Length);
m_fileStream.Write(arr, 0, (int)m_renderedOutputFile.Data.Length);
m_fileStream.Close();