/// <summary>
        /// Send mail to mailreceivers using System.Web.Mail
        /// </summary>
        /// <param name="mailInfo"></param>
        /// <param name="recipients"></param>
        /// <param name="testMode">No mails are sent, generating report for user</param>
        /// <returns>A SendMailLog object with information about the status of the job.</returns>
        public override SendMailLog SendEmail(MailInformation mailInfo, JobWorkItems recipients, bool testMode)
        {
            _log.Debug("900.10.11.1 Starting Send");
            // for logging
            SendMailLog log = new SendMailLog();

            log.StartJob();
            // Recipients util
            RecipientsUtility recipUtil = new RecipientsUtility();

            // We try to verify as many settings, variables etc. before
            // starting the sending loop, as we don't want to generate
            // lots of exceptions in a loop.

            // Need someone to send to
            if (recipients.Items.Count == 0)
            {
                _log.Error("900.10.11.2 Trying to send mail with an empty JobWorkItems collection. Please check the collection before attemting to send mail.");
                throw new ArgumentNullException("Recipient collection is empty, there is no recipients to send to.", "recepients");
            }

            // And, we need a sender address
            if (mailInfo.From == null || mailInfo.From == string.Empty)
            {
                _log.Error("900.10.11.3 Missing from address. SMTP servers do not allow sending without a sender.");
                throw new ArgumentNullException("Missing from address. SMTP servers do not allow sending without a sender.", "mailInfo.From");
            }

            // Load the license. This needs to be in the
            EmailMessage.LoadLicenseString(GetLicenseFileContents());

            // We'll reuse the mail object, so we create it outside of the loop
            EmailMessage mail = CreateMessage(mailInfo);

            // Set port and authentication details if found
            InitializeMailSettings(ref mail);

            // Send a warm-up message outside the loop. This
            // will help us catch any misconfigurations and other
            // things that prevents us from sending emails. By
            // doing this outside the loop, we won't kill the
            // application or log with uneccesary error messages.
            // TODO: Implement this

            // Loop through receivers collection, send email for each
            foreach (JobWorkItem workItem in recipients)
            {
                _log.Debug(string.Format("900.10.11.5 Job {0}, Email: {1}, Status: {2}",
                                         workItem.JobId.ToString(), workItem.EmailAddress, workItem.Status.ToString()));

                // Only attempt sending those that have been stamped as ready for sending
                // unless we're in a test case.
                if (workItem.Status == JobWorkStatus.Sending || testMode == true)
                {
                    try
                    {
                        // At this point we assume the address is formatted correctly
                        // and checked, but aspNetEmail checks the to address on set, may fail
                        mail.To = workItem.EmailAddress;

                        // Perform actual send, if testmail, then this will
                        // return false. We should not update the status on
                        // test sends
                        bool result = SendMail(mail, testMode);
                        if (result == true)
                        {
                            log.SuccessMessages.Add(workItem.EmailAddress);

                            // Update status and save it
                            // TODO: Improve performance by doing this in batch
                            workItem.Status = JobWorkStatus.Complete;
                            // Only save if real work item (could be a test item)
                            if (workItem.JobId > 0)
                            {
                                workItem.Save();
                            }
                        }
                        // else
                        // Could not send, it has been disabled by
                        // settings or parameters
                    }
                    catch (Exception ex)
                    {
                        _log.Error(string.Format("900.10.11.6 Error sending to email: {0}", workItem.EmailAddress), ex);
                        string exceptionMsg = string.Format("Email: {0}\r\nException: {1}\r\n\r\n", workItem.EmailAddress, ex.Message);
                        log.ErrorMessages.Add(exceptionMsg);

                        // Update work item
                        workItem.Status = JobWorkStatus.Failed;
                        if (exceptionMsg.Length >= 2000)
                        {
                            exceptionMsg = exceptionMsg.Substring(0, 1999);
                        }
                        workItem.Info = exceptionMsg;
                        if (workItem.JobId > 0)
                        {
                            workItem.Save();
                        }
                    }
                }
                else
                {
                    _log.Debug(string.Format("900.10.11.7 Skipping Recipient, wrong status. Job {0}, Email: {1}, Status: {2}",
                                             workItem.JobId.ToString(), workItem.EmailAddress, workItem.Status.ToString()));
                }
            }

            // Finished
            log.StopJob();

            // Warn user if logging is enabled
            if (Configuration.NewsLetterConfiguration.ExtendedLogFile != null)
            {
                log.WarningMessages.Add("Logging has been enabled. Only use during troubleshooting.");
            }

            _log.Debug("900.10.11.8 Ending Send");
            // return report
            return(log);
        }