I'm trying to send a mail message using System.Net.Mail.SmtpClient with SSL enabled. While changing no external factors (i.e. hit F5, then hit F5 Again - or even in a loop) it works some times, but most of the times it fails.
Example code:
public void SendMail()
{
using (var client = new SmtpClient())
{
MailMessage mailMessage = new MailMessage();
client.EnableSsl = true;
client.Host = "smtp.example.com";
client.Timeout = 10000;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
mailMessage.From = new MailAddress("from#example.com");
mailMessage.To.Add(new MailAddress("to#example.com"));
mailMessage.Subject = "Test";
mailMessage.Body = "Message " + DateTime.Now.ToString();
try
{
client.Send(mailMessage);
}
catch (Exception ex)
{
// This being a Pokemon block is besides the point
}
}
}
In my catch block I just get a timeout, but if I set up a trace for System.Net and System.Net.Sockets I can see a number of different exceptions:
Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall
Unable to read data from the transport connection: An established connection was aborted by the software in your host machine
Cannot access a disposed object
Reading is not supported on this stream
Writing is not supported on this stream
All of which happen post EHLO, STARTTLS and authentication. The client and the server are chatting along in their cryptographic ways when the exceptions are thrown.
System.Net.Mail.SmtpClient.Send() is the the only frame all call stacks have in common.
Of course I've tried changing the code in a number of ways, such as setting client.UseDefaultCredentials, using client.SendAsync() and whatnot. But I suspect it's something entirely different knocking the connection over at different times - a configuration error on one of the machines involved perhaps?
So I've checked the Event Logs for signs of something messing with the connection, but I haven't found anything.
Any suggestions as to what I should be looking for here?
Sometimes a timeout is just a timeout ...
Digging further into this issue I used Wireshark to see what was going on at the network level.
When the failures happened, the client machine invariably sent a TCP [RST, ACK] packet around 10 seconds after EHLO. A timespan conspicuously close to my timeout value. When I doubled the timeout value the mails came through without failure every single time.
Of course if we were to spend more than 10 seconds sending each mail, we'd soon be queuing up mails for hours in our production system, so I needed to find out why it took so long.
One detail caught my attention:
The client was spending upwards of four seconds between two packets. And it was generally spending hundreds of milliseconds between packets whereas the server would respond within tens.
The next step was to build the code without debug symbols and measure again without a debugger attached. The time spent per e-mail sent immediately went sub-second. Now it's no news to me that code runs slower with a debugger attached, but seeing it run that much slower was a surprise.
So the lessons for me to learn were: Try not to overanalyze, and when timing is involved kill the debugger once in a while.
This should be a comment (I don't have reputation to make comments), but it could be a firewall issue, given you're getting an "Unable to read data from the transport connection: An established connection was aborted by the software in your host machine" error (basically, firewall or anti-virus cancelled your attempt to send a mail).
The error "Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall" happens when a stream is closed - see this question - and the other errors you've listed seem like they're related to trying to access a stream when it's closed, too.
All these error point to a common cause, a connection cancelled somewhere between you and the server and most likely on your machine/ network, and you get different errors depending at what point the effect propagates through to your application.
Another thing is, if you use
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
then you have to enable ssl afterwards, not before, otherwise it's cleared.
I suppose you have missed to set Credentials property of your host. However the another reason for exceptions may be wrong host name and port.Try something like :
public void SendMail()
{
try
{
var fromAddress = new MailAddress("from#example.com", "Some text");
var toAddress = new MailAddress("to#example.com");
const string fromPassword = "from account password";
var smtp = new SmtpClient
{
Host = "smtp.example.com",
Port = "your host port", //for gmail is 587
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
};
using (var message = new MailMessage(fromAddress, toAddress)
{
Subject = "Test",
Body = "Message " + DateTime.Now.ToString()
})
{
smtp.Send(message);
}
}
catch (Exception ex)
{
//do something
}
}
It is tested with gmail host which is smtp.gmail.com and it works correctly
Related
I am sending approximately 5000 emails to IIS smtp server Windows 2012 R2 (Server1) using aspose email client (using c#) in a loop. The emails fired queue up in smtp server queue. From that queue, they are all sent to the same destination (an oracle email filing server - Server2).
The problem is - approx 700-800 (randomly every time) emails are getting lost in transit.
Questions -
Is there any way that i can queue all the emails received on Server1 to ensure that it is receiving complete 5000 emails? Any setting, so it can receive emails but do not forward them?
Is smtp email delivery not guaranteed to the recipient? Since there is no throttling mechanism, i think i am choking the network by sending large number of emails, and then emails in lost in network. If it is so, is there a mechanism by which smtp server can be configured to process queue slowly. Send out a few and then wait and so on.
Aspose.Email also let you send the email in the form of bulks as well. Moreover, it is also dependent on server side that how much bulk email it may handle at any given time so as to avoid any bombardment of emails as well. There may be settings on server side. However, from Aspose.Email perspective, you may please consider using following sample code rather than sending via loops. You can divide big chunks of emails into small bulks and then send via Bulk email sending option provided by Aspose.Email.
SmtpClient client = new SmtpClient("mail.server.com", 25, "Username", "Password");
//Create instances of MailMessage class and Specify To, From, Subject and Message
MailMessage message1 = new MailMessage("msg1#from.com", "msg1#to.com", "Subject1", "message1, how are you?");
MailMessage message2 = new MailMessage("msg1#from.com", "msg2#to.com", "Subject2", "message2, how are you?");
MailMessage message3 = new MailMessage("msg1#from.com", "msg3#to.com", "Subject3", "message3, how are you?");
//Create an instance of MailMessageCollection class
MailMessageCollection manyMsg = new MailMessageCollection();
manyMsg.Add(message1);
manyMsg.Add(message2);
manyMsg.Add(message3);
//Use client.BulkSend function to complete the bulk send task
try
{
// Send Message using BulkSend method
client.Send(manyMsg);
Console.WriteLine("Message sent");
}
catch (Exception ex)
{
Trace.WriteLine(ex.ToString());
}
I can't seem to find the cause for this problem.
Sometimes I get SmtpException "4.7.0 timeout waiting for client input" being thrown on using the following c# code for .net-4.0:
using System;
using System.Net.Mail;
namespace SendMail
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
string html = "<h1>TEST</h1>";
using (MailMessage mail = new MailMessage("sender#domain.com", "receiver#domain.com"))
{
mail.Subject = "Test";
mail.IsBodyHtml = true;
mail.Body = html;
using (SmtpClient client = new SmtpClient("<internal ip address>"))
{
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential("<user name>", "<password>");
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Send(mail);
}
}
}
}
}
}
It usually crashes at the second attempt (i == 1).
I am aware I should create a single SmtpClient instance and reuse it in the loop but for the purpose of demonstration and in order to be as close as possible to the real code it has to be this way. While the above isn't quite like my production code it does suffer from the same random problem. I figured that if I could solve the problem with this code then I'd know what to do with my actual code, given that it really is a coding issue to begin with. I'm suspecting an obscure server configuration issue but I'm out of ideas on what it could possibly be.
Odd thing: despite being a timeout issue, the exception is thrown very quickly; there's no delay that would suggest an actual timing out problem.
The mail server is MS exchange-server-2007 running on windows-server-2008 SP2. There's no additional SMTP settings specified in app.config file.
I tried to put the code in a Do...While loop that tries five times to send the email back after putting the thread to sleep for one second. Unfortunately that doesn't help: when it fails, it will also fail at the very next attempts.
I also tried using Thread.Sleep(<delay>) before every calls to client.Send(message) but it made no appearant difference.
Our network admin is adamant on the network running without any issues (no packet drops caused by bad MTU setting or anything like that). He backs this up with the fact that there's only my code that seems to have problems (and he's right) and that it does not only happen on a segment of the network (also right).
It's unlikely that the firewall would be causing this either, as every mail my app sends is using internal addresses.
Anybody has a clue here? It would be much appreciated.
UPDATE:
I seem to be able to reproduce the problem every time when using default credentials instead:
using (SmtpClient client = new SmtpClient("<internal ip address>"))
{
client.UseDefaultCredentials = true;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Send(mail);
}
UPDATE 2:
Nope. Not every time. Everything now works again (until next time).
I really can't put my finger on it.
UPDATE 3:
Interesting new development today: I attempted to create a new account inside MS Outlook with the same address I use with Exchange. Only this time instead of adding it as an MS Exchange address I tried setting it up as a POP3/SMTP account. Here is what happened upon testing the connection:
It's in french but look at the last line: it is the exact same error message I got with my code. This is a clear indication to me that the issue is not within my code.
Of course, this also means that this whole thread shouldn't be on SO. Still, I hope this extra test can help fellow developers out there who are struggling with a similar issue.
This definitely sounds like a server or network issue. Reference this serverfault post for instance: https://serverfault.com/questions/344684/exchange-2007-email-error-451-4-7-0-timeout-waiting-for-client-input
It could be a firewall problem if there is a firewall between your machine and the exchange server. A firewall blocks ports between ip addresses, it doesn't matter where the email is going at all. Firewalls are the bane of my programming existence, so definitely ask your net admin if there is a firewall between the servers and have him check if it is working.
It could also be something like a bad NIC (network card) on the server or even a bad cable. Yes, your network admin said the network is rock solid... but never trust network admins. ;)
It could also be a problem with YOUR network card, network settings or ethernet cable, actually.
Have you tried running this from different computers?
You can fire if off async like by changing your code as follows. You will need to check the AggregateException to see if something bad happened on any of the executing threads.
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
string html = "<h1>TEST</h1>";
Task.Factory.StartNew(() =>
{
using (MailMessage mail = new MailMessage("sender#domain.com", "receiver#domain.com"))
{
mail.Subject = "Test";
mail.IsBodyHtml = true;
mail.Body = html;
using (SmtpClient client = new SmtpClient("<internal ip address>"))
{
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential("<user name>", "<password>");
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Send(mail);
}
}
}).ContinueWith(aex => {
if (aex.Exception != null)
{
//add some logic to deal with the exception
}
});
}
}
it is better to define SmtpClient before the loop, same problem happened with me and this solved it.
using System;
using System.Net.Mail;
namespace SendMail
{
class Program
{
SmtpClient client = new SmtpClient("<internal ip address>");
static void Main(string[] args)
{
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential("<user name>", "<password>");
//client.EnableSsl = true;
//client.Port = 25;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
for (int i = 0; i < 100; i++)
{
string html = "<h1>TEST</h1>";
using (MailMessage mail = new MailMessage("sender#domain.com", "receiver#domain.com"))
{
mail.Subject = "Test";
mail.IsBodyHtml = true;
mail.Body = html;
client.Send(mail);
}
}
}
}
}
I'm fairly new to this messaging issue. I have currently been working on a messaging application and occasionally this exception is thrown into the system.
So far the answers I have picked up on the internet point out that this is an error in the email sender's authentication. Perhaps the limitation of daily submissions and the hourly send limit may inhibit SMTP server authentication of the email. Example, in case smtps.bol.com.br has a limit of 50 emails per hour, having to have a 60 minute interval to send a new batch of messages.
I have done my tests here and I do not have a conclusive answer, but I believe that maybe the way is this. If they find the definitive solution, do not forget to post.
Make sure the objects call .Dispose() in all cases.
I saw this problem on a highly active production system that sends 5000+ emails a day, but the problem would only happen to about 5% of the emails. The code sending the email was written before .Net 4.0, which introduced the Dispose() call to SmtpClient and MailMessage. I made a very simple change to make sure both objects were disposed and have not seen the problem again in 5 days.
That same code that does NOT call Dispose() runs on less active systems without any problems. My theory is there is some kind of cumulative resource leak if you fail to call Dispose() and it only causes this error under heavy load.
I was getting similar error couple of years back on Amazon Aws server. It seems my security company "AllCovered.com" had to do a exception to my server ip address to allow send smtp emails.
I do get this error if anytime a new server created is forgotten to be put in exception.
I've been having this problem for months, and it's driving me nuts.
I have a windows service written in C# (.NET 4.5) which basically sends emails, using an outlook account (I think it's an office365 service). I'm aware of the "order of credentials" problem, which isn't affecting me (many emails send correctly).
The service starts correctly and begins sending emails. Sometimes when there's too many, I get a server error to wait, the service waits a few minutes and continues perfectly on its own.
In these cases I get Error A:
System.Net.Mail.SmtpException: The operation has timed out.
at System.Net.Mail.SmtpClient.Send(MailMessage message)
at Cobranzas.WinService.Email.SendEmail(String subject, String body, String mailTo, String attPath)
at Cobranzas.WinService.CobranzasEmailService.SendEmails(IEnumerable`1 toSend, RepositoryEf emailRepo)
The problem: sometimes, and I haven't been able to find a pattern, it happens every few days, it gets a timeout error, and never recovers (restarting the services fixes it immediately). All subsequent sending tries fail with the same error. In this case, I get a mix of Error A and:
System.Net.Mail.SmtpException: Failure sending mail. ---> System.Net.WebException: The operation has timed out.
at System.Net.ConnectionPool.Get(Object owningObject, Int32 result, Boolean& continueLoop, WaitHandle[]& waitHandles)
at System.Net.ConnectionPool.GetConnection(Object owningObject, GeneralAsyncDelegate asyncCallback, Int32 creationTimeout)
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)
at Cobranzas.WinService.Email.SendEmail(String subject, String body, String mailTo, String attPath)
at Cobranzas.WinService.CobranzasEmailService.SendEmails(IEnumerable`1 toSend, RepositoryEf emailRepo)
The logic of my service is as follows: I have a timer which every 5 minutes iterates over a lot of emails to be sent, and for each executes
Thread.Sleep(2000);
try
{
emailService.SendEmail(asunto, nuevoCuerpo, mail.Email, mail.AlertMessage.Attach);
}
catch (Exception ex)
{
if (ex is System.Net.Mail.SmtpException)
{
Thread.Sleep(20000); // Lo hacemos esperar 20 segundos
}
}
SendEmail method is:
var mailMessage = new MailMessage();
mailMessage.To.Add(mailTo);
mailMessage.Subject = subject;
mailMessage.Body = WebUtility.HtmlDecode(body);
mailMessage.IsBodyHtml = true;
mailMessage.From = new MailAddress(emailFromAddress, emailFromName);
mailMessage.Headers.Add("Content-type", "text/html; charset=iso-8859-1");
// Attachment
if (attPath != null)
{
var data = new Attachment(attPath, MediaTypeNames.Application.Octet);
mailMessage.Attachments.Add(data);
}
var cred =
new NetworkCredential(emailFromAddress, emailFromPassword);
using (var mailClient =
new SmtpClient(emailSmtpClient, emailSmtpPort)
{
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Timeout = 20000,
Credentials = cred
})
{
mailClient.Send(mailMessage);
}
foreach (Attachment attachment in mailMessage.Attachments)
{
attachment.Dispose();
}
The using SmtpClient, and attachment disposing are new, we added them trying to fix this. There was no behaviour change.
T̶h̶e̶ ̶T̶h̶r̶e̶a̶d̶.̶S̶l̶e̶e̶p̶ ̶a̶f̶t̶e̶r̶ ̶t̶h̶e̶ ̶t̶i̶m̶e̶o̶u̶t̶ ̶i̶s̶ ̶n̶e̶w̶ ̶a̶n̶d̶ ̶u̶n̶t̶e̶s̶t̶e̶d̶ ̶y̶e̶t̶.
Given that restarting the service fixes it, I'm suspecting something not being closed/cleaned appropriately, but I've checked and can't find what it could be. I found this link a while ago, but it looks pretty old.
Any help is much appreciated!
[PROGRESS]
I've tested the 20" wait after a timeout and nothing, it's still failing in the same way. Any ideas? We're really stumped with this.
I have the exact same problem. I found the solution here:
System.Net.WebException when issuing more than two concurrent WebRequests
http://www.wadewegner.com/2007/08/systemnetwebexception-when-issuing-more-than-two-concurrent-webrequests/
Basically, I changed the max number of connections allowed concurrently to a single external server. By default, according to that documentation it was 2. Although, it has a timeout (it waits sometime until one is released and then continues), at sometimes, it is not enough and it hangs.
<configuration>
<system.net>
<connectionManagement>
<add address="*" maxconnection="100" />
</connectionManagement>
</system.net>
</configuration>
I have not been able to find out how to recover after first timeout but hopefully this would get out "timeout" errors out of the way for some time.
Increasing the maximum number of connections may help, but I am not 100% sure if it won't postpone the issue until these number of connections have been reached. I decided to switch to MailKit instead. It has its own SMTP client implementation that is nearly a drop-in replacement and can work with the regular MailMessage object (if you depend on it). It doesn't use the connection pool at all, so it might be a more safe solution.
I get the following exception when a consumer is blocking to receive a message from the SharedQueue:
Unhandled Exception: System.IO.EndOfStreamException: SharedQueue closed
at RabbitMQ.Util.SharedQueue.EnsureIsOpen()
at RabbitMQ.Util.SharedQueue.Dequeue()
at Consumer.Program.Main(String[] args) in c:\Users\pdecker\Documents\Visual
Studio 2012\Projects\RabbitMQTest1\Consumer\Program.cs:line 33
Here is the line of code that is being executed when the exception is thrown:
BasicDeliverEventArgs e = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
So far I have seen the exception occuring when rabbitMQ is inactive. Our application needs to have the consumer always connected and listening for keystrokes. Does anyone know the cause of this problem? Does anyone know how to recover from this problem?
Thanks in advance.
The consumer is tied to the channel:
var consumer = new QueueingBasicConsumer(channel);
So if the channel has closed, then the consumer will not be able to fetch any additional events once the local Queue has been cleared.
Check for the channel to be open with
channel.IsOpen == true
and that the Queue has available events with
if( consumer.Queue.Count() > 0 )
before calling:
BasicDeliverEventArgs e = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
To be more specific, I would check the following before calling Dequeue()
if( !channel.IsOpen || !connection.IsOpen )
{
Your_Connection_Channel_Init_Function();
consumer = new QueueingBasicConsumer(channel); // consumer is tied to channel
}
if( consumer.Queue.Any() )
BasicDeliverEventArgs e = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
Don't worry this is just expected behavior, it means there is no message left in queue to process. Don't even try it is not gonna work...
consumer.Queue.Any()
Just catch the EndOfStreamException:
private void ConsumeMessages(string queueName)
{
using (IConnection conn = factory.CreateConnection())
{
using (IModel channel = conn.CreateModel())
{
var consumer = new QueueingBasicConsumer(channel);
channel.BasicConsume(queueName, false, consumer);
Trace.WriteLine(string.Format("Waiting for messages from: {0}", queueName));
while (true)
{
BasicDeliverEventArgs ea = null;
try
{
ea = consumer.Queue.Dequeue();
}
catch (EndOfStreamException endOfStreamException)
{
Trace.WriteLine(endOfStreamException);
// If you want to end listening end of queue call break;
break;
}
if (ea == null) break;
var body = ea.Body;
// Consume message how you want
Thread.Sleep(300);
channel.BasicAck(ea.DeliveryTag, false);
}
}
}
}
There is another possible source of trouble: your corporate firewall.
Thats because such firewall can drop your connection to RabbitMQ when the connection is idle for a certain amount of time.
Although RabbitMQ connection has a heartbeat feature to prevent this, if the heartbeat pulse happens after the firewall connection timeout, it is useless.
This is the default heartbeat interval configuration in seconds:
Default: 60 (580 prior to release 3.5.5)
From RabbitMQ:
Detecting Dead TCP Connections with Heartbeats
Introduction
Network can fail in many ways, sometimes pretty subtle (e.g. high
ratio packet loss). Disrupted TCP connections take a moderately long
time (about 11 minutes with default configuration on Linux, for
example) to be detected by the operating system. AMQP 0-9-1 offers a
heartbeat feature to ensure that the application layer promptly finds
out about disrupted connections (and also completely unresponsive
peers).
Heartbeats also defend against certain network equipment which
may terminate "idle" TCP connections.
That happened to us and we solved the problem by decreasing the Heartbeat Timeout Interval in the global configuration:
In your rabbitmq.config, find the heartbeat and set it to a value smaller than that of your firewall rule.
You can change the interval in your client, too:
Enabling Heartbeats with Java Client To configure the heartbeat
timeout in the Java client, set it with
ConnectionFactory#setRequestedHeartbeat before creating a connection:
ConnectionFactory cf = new ConnectionFactory();
// set the heartbeat timeout to 60 seconds
cf.setRequestedHeartbeat(60);
Enabling Heartbeats with the .NET Client To configure the heartbeat
timeout in the .NET client, set it with
ConnectionFactory.RequestedHeartbeat before creating a connection:
var cf = new ConnectionFactory();
//set the heartbeat timeout to 60 seconds
cf.RequestedHeartbeat = 60;
The answers here that say that this is the expected behavior are correct, however I would argue that it's bad to have it throw an exception by design like this.
from the documentation: "Callers of Dequeue() will block if no items are available until some other thread calls Enqueue() or the queue is closed. In the latter case this method will throw EndOfStreamException."
So, like GlenH7 said, you have to check that channel is open before calling Dequeue() (IModel.IsOpen).
However, what if the channel closes while Dequeue() is blocking? I think it's best to call Queue.DequeueNoWait(null), and block the thread yourself by waiting for it to return something that isn't null. So, something like:
while(channel.IsOpen)
{
var args = consumer.Queue.DequeueNoWait(null);
if(args == null) continue;
//...
}
This way, it won't throw that exception.
Here is my code:
SmtpClient client = new SmtpClient();
client.UseDefaultCredentials = true;
using (client as IDisposable)
{
foreach (MailAddress addr in Addresses)
{
if (addr != null)
{
try
{
message.To.Clear();
message.To.Add(addr);
client.Send(message);
}
catch (Exception ex)
{
Log(ex);
}
i++;
}
}
}
every 100 seconds, I log a message saying
The operation has timed out.
Is this a client side setting or on the actual mail server?
The problem happens when you are not able to connect to SMTP server and thats why this timeout message occur. So this message occurs on your client when your client is not able to connect to your SMTP Server:
100 second is default value as described below:
http://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.timeout.aspx
There could be several issue why this prblem could occur i.e. Wrong SMTP address, SMTP reject, Port setting, SSL configuration etc which you need to fix.
I was also expeiencing this timeout. The problem seemed to be that the email I was trying to send out had a single email address but repeated 30+ times (this was a dev environment where the real recipient email addresses were change to a dev one). Cutting this number (to about 20) resolved the issue. Obviously, this is an issue specific to my own SMTP server, but the recipient list is something to look at if all else fails.