1

I am writing a program that sends email through class SmtpClient. I use this code:

        try
        {
            MailMessage mail = new MailMessage();
            SmtpClient SmtpServer = new SmtpClient("mailSMTP.it");

            mail.From = new MailAddress("address.it");

            mail.Subject = "oggetto";

            mail.IsBodyHtml = true;
            string htmlBody = "someHTML";

            mail.Body = htmlBody;

            SmtpServer.Port = 25;

            SmtpServer.EnableSsl = false;

            foreach (string indirizzo in indirizzi)
            {
                mail.To.Clear();
                mail.To.Add(indirizzo);
                SmtpServer.Send(mail);
                System.Threading.Thread.Sleep(3000);
            }

            MessageBox.Show("e-mail spedite!");

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }

but it only works if I cut the "Sleep" line. Why? I thought it was a good idea to make a rest during that process.

John Källén
  • 7,551
  • 31
  • 64

5 Answers5

2

Given that there's an exception, assuming it's at the call to Send, I would suggest not re-using the MailMessage object and creating a new one on each iteration of the loop. for example:

        //...
        foreach (string indirizzo in indirizzi)
        {
            string htmlBody = "someHTML";
            MailMessage mail = new MailMessage 
            {
                From = new MailAddress("address.it"),
                Subject = "oggetto",
                IsBodyHtml = true,
                Body = htmlBody,
            };

            mail.To.Clear();
            mail.To.Add(indirizzo);
            SmtpServer.Send(mail);
        }

If by "works" you mean your MessageBox shows up in a reasonable amount of time... then the reason is because Sleep is blocking the UI thread until all the messages are sent. e.g. if you try to send 10 messages, the UI will halt for 30 seconds (3000 milliseconds X 10).

Peter Ritchie
  • 35,463
  • 9
  • 80
  • 98
  • Yes, I know, but the problem is different: I'm testing the program with a List that contains 3 email addresses. With the "Sleep" line it only sends the message to the first address, and then throw and exception. Without the sleep line, it sends all the emails. But i don't know why... – Stefano Castelli Sep 22 '12 at 16:10
0

I think you define new thread for this process because if you write System.Threading.Thread.Sleep(3000); means the main thread going to sleep for 3000ms.

So,Create a nested thread for this process and after this you can stop/sleep your thread .

Anant Dabhi
  • 10,864
  • 3
  • 31
  • 49
  • I think the question is more about a way to do this without using `Sleep`, creating a new thread to avoid blocking the main thread doesn't address the root of the problem. – Peter Ritchie Sep 22 '12 at 17:32
0

In my opinion (and others) you should try to avoid Sleep at almost any cost, more often than not you end up with an application that behaves strange (like the behavior you describe).

I would solve it with a timer that uses an index to determine which is the next mail to send. Something like this:

    try
    {
        MailMessage mail = new MailMessage();
        SmtpClient SmtpServer = new SmtpClient("mailSMTP.it");

        mail.From = new MailAddress("address.it");

        mail.Subject = "oggetto";

        mail.IsBodyHtml = true;
        string htmlBody = "someHTML";

        mail.Body = htmlBody;

        SmtpServer.Port = 25;

        SmtpServer.EnableSsl = false;

        var index = 0;

        var timer = new System.Threading.Timer((callbackState) =>
            {
                mail.To.Clear();
                mail.To.Add(indirizzi[index]);
                SmtpServer.Send(mail);

                index++;

                if (index < indirizzi.Count)
                  timer.Change(3000, Timeout.Infinite);
                else {
                    timer.Dispose();
                    Invoke(new Action(DisplayAllEmailsSentMessage));
                }
            }, timer, 3000, Timeout.Infinite);

    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }

Note that you would have to use Invoke to interact with Windows Forms in any way, for instance to show a message box. This is because the Threading.Timer callback executes on a thread of its own.

It may also be possible for you to use the Windows.Forms.Timer, but I rarely use it myself since it's in the Windows.Forms namespace and thus only suitable for UI's written in Windows Forms.

Community
  • 1
  • 1
Daniel Persson
  • 2,171
  • 1
  • 17
  • 24
0

The Smtp server is dropping your connection due to inactivity. This is most likely to free up resources on the server.

From the SmtpClient documentation:

The connection established by the current instance of the SmtpClient class to the SMTP server may be re-used if an application wishes to send multiple messages to the same SMTP server. This is particularly useful when authentication or encryption are used establish a connection to the SMTP server. The process of authenticating and establishing a TLS session can be expensive operations. A requirement to re-establish a connection for each message when sending a large quantity of email to the same SMTP server could have a significant impact on performance.

In general, the other responders are correct in saying that you shouldn't be sleeping between sending. The Smtp server should be robust enough to handle all the emails you can throw at it sequentially.

Mufaka
  • 2,333
  • 1
  • 18
  • 25
  • After a lot of tests, I think this is the real problem: If I set a shorter sleep time (e.g. 100 ms) it sends all the emails, so I guess the problem is caused by SMTP server inactivity. I'm still testing with other solutions proposed (many thanks to all!!!), I'll let you know... – Stefano Castelli Sep 24 '12 at 09:01
0
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

 class MailSender
    {
        public static int CreateMessageMdp(String destination,String mdp)
        {
            try
            {
                var client = new SmtpClient("smtp.domain.com", 587)
                {
                    Credentials = new NetworkCredential("appgestionali@domain.com", "password"),
                    EnableSsl = true
                };
                DateTime localDate = DateTime.Now;
                string body = "Suite à votre demande de mot de passe le " + localDate.ToString("F") + "\n on vous envoi votre mot de passe est :" + mdp;
                client.Send("appgestionali@domain.com", destination, "Information", body);
            }
            catch (Exception ex)
            {
                MessageBox.Show(""+ ex.GetBaseException());
                return -1;
            }
            return 0;
        }
    }
}
Tariq.dbi
  • 1
  • 1