Quick .Net Email Reference

I’ve done a bit of encapsulation here to abstract the concept into clearer functionality, IMO.

Make sure to add “using” reference directives for System.Threading and System.Net.Mail accordingly, when necessary.

Note usage of basic boolean “sync lock” style logic in place of static members for thread safety.

(This code is purely illustration of concept and functionality is not assured. Correctness of code is coincidental. 🙂 )

C#:

private Automailer mailer;

private void StartEmailAutomailer() {
      int interval = 100000;
                    System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient();
                    //set host, port, etc from your data layer
                    List<System.Net.Mail.MailAddress> recipients = DataAccess.MailInfo.recipients;

                    if (mailer == null)
                    {    
                        mailer = new Automailer(interval,client,recipients);
                    }
                    else
                    {
                        mailer.AccessMailInterval = interval;
                        mailer.AccessMailClient = client;
                        mailer.AccessMailRecipients = recipients;
                    }
                    mailer.Start();
}

//contain in job/agent type definitions
public class Automailer
    {
        private System.Timers.Timer mailerthread;

        public bool IsRunning { get; private set; }
        private bool sending { get; set; }

        public double AccessMailInterval
        {
            get
            {
                return mailerthread.Interval;
            }
            set
            {
                if (sending == false)
                {
                    mailerthread.Interval = AccessMailInterval;
                }
                else
                {
                    utils.cout("Cannot modify interval while mail cycle is processing.");
                }
            }
        }

        private SmtpClient MailClient;
        public SmtpClient AccessMailClient { 
            get {
                    return MailClient;
        }
            set
            {
                if (sending == false)
                {
                    MailClient = AccessMailClient;
                }
                else
                {
                    utils.cout("Cannot modify mail client while mail cycle is processing.");
                }
            }
        }

        private List<MailAddress> MailRecipients;
        public List<MailAddress> AccessMailRecipients { 
            get {
                    return MailRecipients;
        } 
            set {
                if (sending == false)
                {
                    MailRecipients = AccessMailRecipients;
                }
                else
                {
                    utils.cout("Cannot modify mail recipients while mail cycle is processing.");
                }

            } 
        }

        /// Must be manually started / stopped.
        public Automailer(double interval,SmtpClient client,List<MailAddress> recipients)
        {
            try
            {
                MailClient = client;
                MailRecipients = recipients;

                sending = false;
                mailerthread = new System.Timers.Timer(interval);
                mailerthread.Elapsed += new System.Timers.ElapsedEventHandler(SendMail);
            }
            catch (Exception ex)
            {
                utils.cout("Error sending email. Details:" + "\r\n" + ex.ToString());
            }
        }

        public void Start() {
            if (IsRunning)
            {
                utils.cout("Automailer agent already running.");
            }
            else
            {
                utils.cout("Starting automailer agent...");
                mailerthread.Start();
                IsRunning = true;
                utils.cout("Initialized.");
            }
        }
        
        public void Stop() {
            if (IsRunning)
            {
                utils.cout("Sending halt and exit command to automailer agent...");
                mailerthread.Stop();
                utils.cout("Stopped.");

                if (sending)
                {
                    utils.cout("Warning: automailer stopped during mail cycle.");
                }
            }
            else
            {
                utils.cout("Automailer agent is not running.");
            }
            
        }

        /// Fires on timer or can be called manually.
        public void SendMail(object source, System.Timers.ElapsedEventArgs e)
        {
            if (sending == false)
            {
                sending = true;
                int successcount = 0;
                try
                {
                    utils.cout("Starting mail cycle...");
                    int rollingcount = 0;
                    foreach (MailAddress address in MailRecipients)
                    {
                        rollingcount += 1;
                        utils.cout(String.Format("Sending email {0} of {1}.", rollingcount, MailRecipients.Count));

                        MailMessage message = new MailMessage();

                        try
                        {
                            message.Body = DataAccess.MailInfo.body;
                            message.IsBodyHtml = DataAccess.MailInfo.ishtml;
                        }
                        catch (Exception ex4)
                        {
                            utils.cout("Could not populate body from template. Message will be sent using defaults. Details:" + "\r\n" + ex4.ToString());
                            message.IsBodyHtml = true;
                            message.Body = String.Format("Thank-you! <br /><br /> \r\n \r\n - {0}",DataAccess.LicenseInfo.company);
                        }

                        try
                        {
                            message.To.Add(address);

                            try
                            {
                                MailClient.Send(message);
                                utils.cout(String.Format("Email sent to {0}.",address.Address));
                                successcount += 1;
                                //async can be used alternatively
                                //MailClient.SendAsync(message,)
                                //MailClient.SendCompleted += new SendCompletedEventHandler(SendMailComplete);
                            }
                            catch (Exception ex2)
                            {
                                utils.cout(String.Format("Could not send to {0}. Details:", address.Address) + "\r\n" + ex2.ToString());
                            }
                        }
                        catch (Exception ex3)
                        {
                            utils.cout(String.Format("Unable to add address {0} to the list. Details:", address.Address) + "\r\n" + ex3.ToString());
                        }

                        message.Dispose();
                    }
                   
                }
                catch (Exception ex)
                {
                    utils.cout("Error sending email. Details:" + "\r\n" + ex.ToString());
                }

                utils.cout(String.Format("Mail cycle complete. {0} sent successful, {1} failed to send.", successcount.ToString(), (MailRecipients.Count - successcount).ToString()));

                sending = false;
            }
        }

        //not used, can be used to engage on asyc calls
        private void SendMailComplete(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            
        }
    }

//data layer
public static class DataAccess {
public static class Mailinfo {
//contains static methods and properties for retrieving data from database or file, etc
}
}

//in a generic lib
public static class utils {
public static void cout(string outputtext) {
//output text to console, window, form, etc
}
}
Advertisement

About Ronnie Diaz

Ronnie Diaz is a software engineer and tech consultant. Ronnie started his career in front-end and back-end development for companies in ecommerce, service industries and remote education. This work transitioned from traditional desktop client-server applications through early cloud development. Software included human resource management and service technician workflows, online retail e-commerce and electronic ordering and fulfillment, IVR customer relational systems, and video streaming remote learning SCORM web applications. Hands on server experience and software performance optimization led to creation of a startup business focused on collocated data center services and continued experience with video streaming hardware and software. This led to a career in Amazon Prime Video where Ronnie is currently employed, building software and systems which stream live sports and events for millions of viewers around the world.

Posted on January 13, 2011, in Programming & Development and tagged , , , , , , , , , , , , , , , , , , , , , , . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: