wim sturkenboom
Well-known member
I have the below class for sending emails asynchronously.
It does not work because disposing the client (as part of the using statement) cancels the sending. So I now basically need to dispose in the callback. But to be able to do so, the smtp client (cl) and probably the mail message (mm) need to be global. I'm happy to do so by adding the below two lines in the beginning of the class
But I'm very worried about the implications if the sendMailAsync method is called a number of times in quick succession.
Thanks for reading and advice.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net.Mail; using System.ComponentModel; namespace disney2sch { class Mailer { public static bool sendEmailAsync(Configuration.EmailSetup esSetup, string strSubject, string strBody, List<string> lstRecipients, ref string errmsg) { MailMessage mm = new MailMessage(); try { // setup mail message mm.IsBodyHtml = false; mm.From = new MailAddress(esSetup.mailfrom); if (!String.IsNullOrEmpty(esSetup.replyto)) mm.ReplyToList.Add(new MailAddress(esSetup.replyto)); for (int cnt = 0; cnt < lstRecipients.Count; cnt++) { mm.To.Add(lstRecipients[cnt]); } mm.Subject = strSubject; mm.Body = strBody; // send it using (SmtpClientEx cl = new SmtpClientEx(esSetup.ServerOrIP, esSetup.port)) { cl.LocalHostName = "localmachine"; if (!String.IsNullOrEmpty(esSetup.username)) { cl.Credentials = new System.Net.NetworkCredential(esSetup.username, esSetup.password); } cl.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); cl.SendAsync(mm, "xx"); } } catch (SmtpException ex) { errmsg = String.Format("Error sending mail"); Logging.LogWriter lw = Logging.LogWriter.Instance; lw.WriteToLog(errmsg); lw.WriteToLog(String.Format("{0}", ex.Message)); if (ex.InnerException != null && !String.IsNullOrEmpty(ex.InnerException.Message)) { lw.WriteToLog(String.Format("{0}", ex.InnerException.Message)); } errmsg = ex.Message; return false; } catch (Exception ex) { errmsg = String.Format("Error sending mail"); Logging.LogWriter lw = Logging.LogWriter.Instance; lw.WriteToLog(errmsg); lw.WriteToLog(String.Format("{0}", ex.Message)); if (ex.InnerException != null && !String.IsNullOrEmpty(ex.InnerException.Message)) { lw.WriteToLog(String.Format("{0}", ex.InnerException.Message)); } errmsg = ex.Message; return false; } finally { mm.Dispose(); } return true; } private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e) { // Get the unique identifier for this asynchronous operation. String token = (string)e.UserState; string msg; Logging.LogWriter lw = Logging.LogWriter.Instance; if (e.Cancelled) { msg = String.Format("[{0}] Sending email canceled.", token); lw.WriteToLog(msg); return; } if (e.Error != null) { msg = String.Format("[{0}] Error sending email: {1}", token, e.Error.ToString()); lw.WriteToLog(msg); } else { msg = String.Format("[{0}] Sending mail succeeded", token); lw.WriteToLog(msg); } } } }
It does not work because disposing the client (as part of the using statement) cancels the sending. So I now basically need to dispose in the callback. But to be able to do so, the smtp client (cl) and probably the mail message (mm) need to be global. I'm happy to do so by adding the below two lines in the beginning of the class
private static MailMessage mm; private static SmtpClientEx cl;
But I'm very worried about the implications if the sendMailAsync method is called a number of times in quick succession.
- Am I right in being worried? Or do I miss something about how it works?
- Is it possible to solve this using static methods? How?
- Or should I drop the idea of a static method and just instantiate a mailer class and use non-static methods?
Thanks for reading and advice.