I created a New Event Emailer.this takes some fun events from a nice SQL query and creates a little HTML message and sends it to all the subscribers of events, when new event types are added we need to be able to tell them that they need to add the events to their subscription if they want to be notified of them.  One issue is that if we send too many emails to the same domain in a short period of time we will get black listed from that domain, and that's not good.so I coded this emailer to take the list of emails and email 10 at a time with a 6 second delay in the middle.Is there anything that is inefficient or some edge case that I am missing?class NewEventMailer //: IDisposable{#if DEBUG    private static string _messageHeader = Resources.NewEventsEmailer_Development.HeaderMessage;    private static string _logFileLocation = Resources.DebugStrings.LogFileLocation;    private static string _SmtpServer = Resources.DebugStrings.SmtpServer;    private static string _SmtpServerPort = Resources.DebugStrings.SmtpServerPort;    private static string _emailSender = Resources.DebugStrings.EmailSender;    private static string _newEventSubjectLine = Resources.NewEventsEmailer_Development.NewEventSubjectLine;    private static string _defaultRecipient = Resources.NewEventsEmailer_Development.DefaultRecipient;    private static string _NewEventSubjectLine = Resources.NewEventsEmailer_Development.NewEventSubjectLine;#else    private static string _messageHeader = Resources.NewEventsEmailer_Production.HeaderMessage;    private static string _logFileLocation = Resources.ProductionStrings.LogFileLocation;    private static string _SmtpServer = Resources.ProductionStrings.SmtpServer;    private static string _SmtpServerPort = Resources.ProductionStrings.SmtpServerPort;    private static string _emailSender = Resources.ProductionStrings.EmailSender;    private static string newEventSubjectLine = Resources.NewEventsEmailer_Production.NewEventSubjectLine;    private static string _NewEventSubjectLine = Resources.NewEventsEmailer_Production.NewEventSubjectLine;    //Default Email set in Development Resource.    private static string _defaultRecipient = Resources.NewEventsEmailer_Development.DefaultRecipient;#endif    private string _eventMailMessage;    private List<string> _addresses;    public NewEventMailer(DataTable newEventTable, List<string> addresses)    {        this._addresses = addresses;        _eventMailMessage = EventMessage(newEventTable);    }    public string EventMessage(DataTable eventTable)    {        StringBuilder newMessage = new StringBuilder();        newMessage.Append(<table style='text-align:left; width:750px'><tr><th colspan='2' style='text-align:left;'> + _messageHeader + </th></tr>);        newMessage.Append(<tr><td style='border-bottom:groove; border-bottom-color:silver; font-size:x-large'>Event Name</td><td style='border-bottom:groove; border-bottom-color:silver; font-size:x-large'>Event Group</td></tr>);        foreach (DataRow row in eventTable.Rows)        {            newMessage.Append(<tr><td> + row.Field<string>(EventName) + </td><td> + row.Field<string>(EventGroup) + </td></tr>);        }        newMessage.Append(</table>);        return newMessage.ToString();    }    public void SendNewEventEmail()    {        int emailCounter = 0;        MailMessage emailMessage = GetNewMailMessage(); //First Mail Message        bool emailSent = false;        foreach (var address in _addresses)        {            emailSent = false;            var bccAddress = new MailAddress(address);            emailMessage.Bcc.Add(bccAddress);            emailCounter++;            if (emailCounter % 10 == 0)            {                using (SmtpClient mailClient = new SmtpClient(_SmtpServer, Convert.ToInt32(_SmtpServerPort)))                {                    mailClient.Send(emailMessage);                    Thread.Sleep(6000);                    emailSent = true;                    emailMessage = GetNewMailMessage();                }            }        }        if (emailSent == false)        {            using (SmtpClient mailClient = new SmtpClient(_SmtpServer, Convert.ToInt32(_SmtpServerPort)))            {                mailClient.Send(emailMessage);            }        }    }    public MailMessage GetNewMailMessage()    {        MailMessage emailMessage = new MailMessage(_emailSender, _defaultRecipient);        emailMessage.IsBodyHtml = true;        emailMessage.Body = _eventMailMessage;        emailMessage.Subject = _NewEventSubjectLine;        return emailMessage;    }}And here is the Method in the main program class that calls everything into playpublic static void SendNewEventsEmails(){    List<string> Addresses = new List<string>();    //Get Email Addresses    using (SqlConnection emailConn = new SqlConnection(Resources.DebugStrings.AttorneyEventCS))    using (SqlCommand emails = new SqlCommand([SQL_SELECT_STATEMENT_FOR_EMAIL_ADDRESSES], emailConn))    using (SqlDataAdapter emailsToData = new SqlDataAdapter())    using (DataTable emailsTable = new DataTable())    {        emailConn.Open();        emailsTable.Load(emails.ExecuteReader());        foreach (DataRow email in emailsTable.Rows)        {            Addresses.Add(email.Field<string>(EmailTo));        }    }    //Send Email    using (SqlConnection conn = new SqlConnection(Resources.ProductionStrings.AttorneyEventCS))    using (SqlCommand newEventSproc = new SqlCommand()    {        CommandType = CommandType.StoredProcedure        , CommandText = [SPROC_Name]        , Connection = conn    })    {        conn.Open();        newEventSproc.Parameters.AddWithValue(@DaysPast, 30);        DataTable newEventsTable = new DataTable();        newEventsTable.Load(newEventSproc.ExecuteReader());        NewEventMailer newEventMailer = new NewEventMailer(newEventsTable, Addresses);        newEventMailer.SendNewEventEmail();    }}Production has new events in the last 30 days, hence the reason for the production connection string,  I still have some testing to do to get this to only email on the 1st of the month.  but it works the way I intended it to.
New event notification e-mailer
c#;email
Duplicated codeIn SendNewEventEmail, there is some duplication in the email sending part:// exhibit #1using (SmtpClient mailClient = new SmtpClient(_SmtpServer, Convert.ToInt32(_SmtpServerPort))){    mailClient.Send(emailMessage);    Thread.Sleep(6000);    emailSent = true;    emailMessage = GetNewMailMessage();}And then again:// exhibit #2using (SmtpClient mailClient = new SmtpClient(_SmtpServer, Convert.ToInt32(_SmtpServerPort))){    mailClient.Send(emailMessage);}It seems that it won't change your logic if you rewrite exhibit #1 like this:using (SmtpClient mailClient = new SmtpClient(_SmtpServer, Convert.ToInt32(_SmtpServerPort))){    mailClient.Send(emailMessage);}Thread.Sleep(6000);emailSent = true;emailMessage = GetNewMailMessage();This you have the using (...) { ... } block exactly duplicated twice,so you can extract that to a helper method.Odd emailSent variableI looked with suspicion at the emailSent variable that gets set multiple times.If I'm looking at it right,its purpose is to know after the loop whether there are still a bunch of messages not yet sent.It seems you could get this same information from the emailCounter variable.Suggested implementationPutting the above points together,I think this function would be simpler and better this way:public void SendNewEventEmail(){    int emailCounter = 0;    MailMessage emailMessage = GetNewMailMessage();  // First Mail Message    foreach (var address in _addresses)    {        var bccAddress = new MailAddress(address);        emailMessage.Bcc.Add(bccAddress);        emailCounter++;        if (emailCounter % 10 == 0)        {            SendEmail(emailMessage);  // the new helper method (TODO)            Thread.Sleep(6000);            emailMessage = GetNewMailMessage();        }    }    if (emailCounter % 10 > 0)    {        SendEmail(emailMessage);    }}Single responsibility principleThe SendNewEventsEmails is doing too much:Dig up email information from databasePrepare list of addresses and execute sendingIt would be better to split these up:A database accessor class should be in charge of loading data and returning it, and nothing elseAn email sending class should not have to work with a database table and should not be aware of table schemas, such as the EventName and EventGroup column names and their types.These two classes would be better to decouple from each other, they will become more generally reusable that way.There should be a third class that's driving the actions,using these two components.The result will be something where the components will be testable individually.