Rahul Paranjape
Rahul Paranjape

Reputation: 23

Sending mail with task parallel library throws error

CODE:-

List<Task> tasks = new List<Task>();
foreach (var item in arr)//arr contains 1000+ mailids
            {
                tasks.Add(Task.Factory.StartNew(() =>
                {
                    using (MailMessage msg = new MailMessage())
                        {
                            msg=getmsg();//p-shadow code no erorr here
                            SmtpClient smtp = new SmtpClient();
                            smtp.Host = smtpServer;
                            smtp.Port = smtpPort;
                            smtp.EnableSsl = isSmtpSsl != 0 ? true : false;
                            smtp.Credentials = new NetworkCredential(smtpUName,smtpPass);
                            smtp.Timeout = int.MaxValue;
                            smtp.Send(msg);//---throws error....
                            //sql code to insert db that mail is send
                        }
                }, TaskCreationOptions.LongRunning));
            }
            Task.WaitAll(tasks.ToArray<Task>());

ERROR-"Failure sending mail."

INTERNAL ERROR-"Unable to read data from the transport connection: net_io_connectionclosed."

Upvotes: 2

Views: 2707

Answers (2)

Ryan Gunn
Ryan Gunn

Reputation: 1169

Regarding the exception 'net_io_connectionclosed', please look at this link as it might point you in the right direction about why the connection is being closed. It could be authentication problems, firewall etc.

Enabling Tracing for System.Net

Please find below the code that I would use in your situation instead of spawning 1000 tasks which is not very efficient.

Sending bulk emails with Tasks Parallel.ForEach

Upvotes: 2

James Manning
James Manning

Reputation: 13589

As Jim mentions, you're likely just hitting a throttling/rejection situation. IMHO, you're likely to be more successful by 1) using a single SmtpClient rather than N of them (so the single client could internally serialize as/if necessary) and 2) using the built-in async call (SendMailAsync) instead of StartNew and calling the sync version.

Something like:

var messages = ... // get collection of MailMessage instances
var smtpClient = new SmtpClient { ... }; // construct a single SmtpClient
var tasks = messages.Select(smtpClient.SendMailAsync).ToArray();
Task.WaitAll(tasks);

I'm not sure if that's really going to help much, though - if it still fails, you might just need to make a single long-running Task that sends the emails serially.

Upvotes: 0

Related Questions