Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronously sending Emails in C#?

I'm developing an application where a user clicks/presses enter on a certain button in a window, the application does some checks and determines whether to send out a couple of emails or not, then show another window with a message.

My issue is, sending out the 2 emails slows the process noticeably, and for some (~8) seconds the first window looks frozen while it's doing the sending.

Is there any way I can have these emails sent on the background and display the next window right away?

Please don't limit your answer with "use X class" or "just use X method" as I am not all too familiarized with the language yet and some more information would be highly appreciated.

Thanks.

like image 616
Eton B. Avatar asked Aug 04 '10 18:08

Eton B.


Video Answer


2 Answers

As of .NET 4.5 SmtpClient implements async awaitable method SendMailAsync. As a result, to send email asynchronously is as following:

public async Task SendEmail(string toEmailAddress, string emailSubject, string emailMessage) {     var message = new MailMessage();     message.To.Add(toEmailAddress);      message.Subject = emailSubject;     message.Body = emailMessage;      using (var smtpClient = new SmtpClient())     {         await smtpClient.SendMailAsync(message);     } }  
like image 92
Boris Lipschitz Avatar answered Oct 13 '22 03:10

Boris Lipschitz


As it's a small unit of work you should use ThreadPool.QueueUserWorkItem for the threading aspect of it. If you use the SmtpClient class to send your mail you could handle the SendCompleted event to give feedback to the user.

ThreadPool.QueueUserWorkItem(t => {     SmtpClient client = new SmtpClient("MyMailServer");     MailAddress from = new MailAddress("[email protected]", "My Name", System.Text.Encoding.UTF8);     MailAddress to = new MailAddress("[email protected]");     MailMessage message = new MailMessage(from, to);     message.Body = "The message I want to send.";     message.BodyEncoding =  System.Text.Encoding.UTF8;     message.Subject = "The subject of the email";     message.SubjectEncoding = System.Text.Encoding.UTF8;     // Set the method that is called back when the send operation ends.     client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);     // The userState can be any object that allows your callback      // method to identify this send operation.     // For this example, I am passing the message itself     client.SendAsync(message, message); });  private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e) {         // Get the message we sent         MailMessage msg = (MailMessage)e.UserState;          if (e.Cancelled)         {             // prompt user with "send cancelled" message          }         if (e.Error != null)         {             // prompt user with error message          }         else         {             // prompt user with message sent!             // as we have the message object we can also display who the message             // was sent to etc          }          // finally dispose of the message         if (msg != null)             msg.Dispose(); } 

By creating a fresh SMTP client each time this will allow you to send out emails simultaneously.

like image 41
James Avatar answered Oct 13 '22 01:10

James