Example #1
0
        /// <summary>
        /// Sends the specified rock message.
        /// </summary>
        /// <param name="rockMessage">The rock message.</param>
        /// <param name="mediumEntityTypeId">The medium entity type identifier.</param>
        /// <param name="mediumAttributes">The medium attributes.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public override bool Send(RockMessage rockMessage, int mediumEntityTypeId, Dictionary <string, string> mediumAttributes, out List <string> errorMessages)
        {
            errorMessages = new List <string>();

            var emailMessage = rockMessage as RockEmailMessage;

            if (emailMessage == null)
            {
                return(false);
            }

            var mergeFields      = GetAllMergeFields(rockMessage.CurrentPerson, rockMessage.AdditionalMergeFields);
            var globalAttributes = GlobalAttributesCache.Get();
            var fromAddress      = GetFromAddress(emailMessage, mergeFields, globalAttributes);

            if (fromAddress.IsNullOrWhiteSpace())
            {
                errorMessages.Add("A From address was not provided.");
                return(false);
            }

            var templateMailMessage = GetTemplateRockEmailMessage(emailMessage, mergeFields, globalAttributes);
            var organizationEmail   = globalAttributes.GetValue("OrganizationEmail");

            foreach (var rockMessageRecipient in rockMessage.GetRecipients())
            {
                try
                {
                    var recipientEmailMessage = GetRecipientRockEmailMessage(templateMailMessage, rockMessageRecipient, mergeFields, organizationEmail);

                    var result = SendEmail(recipientEmailMessage);

                    // Create the communication record
                    if (recipientEmailMessage.CreateCommunicationRecord)
                    {
                        var transaction = new SaveCommunicationTransaction(rockMessageRecipient, recipientEmailMessage.FromName, recipientEmailMessage.FromEmail, recipientEmailMessage.Subject, recipientEmailMessage.Message);
                        transaction.RecipientGuid = recipientEmailMessage.MessageMetaData["communication_recipient_guid"].AsGuidOrNull();
                        RockQueue.TransactionQueue.Enqueue(transaction);
                    }
                }
                catch (Exception ex)
                {
                    errorMessages.Add(ex.Message);
                    ExceptionLogService.LogException(ex);
                }
            }

            return(!errorMessages.Any());
        }
Example #2
0
        /// <summary>
        /// Sends the specified rock message.
        /// </summary>
        /// <param name="rockMessage">The rock message.</param>
        /// <param name="mediumEntityTypeId">The medium entity type identifier.</param>
        /// <param name="mediumAttributes">The medium attributes.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public override bool Send(RockMessage rockMessage, int mediumEntityTypeId, Dictionary <string, string> mediumAttributes, out List <string> errorMessages)
        {
            errorMessages = new List <string>();

            var emailMessage = rockMessage as RockEmailMessage;

            if (emailMessage != null)
            {
                // Common Merge Field
                var mergeFields = Lava.LavaHelper.GetCommonMergeFields(null, rockMessage.CurrentPerson);
                foreach (var mergeField in rockMessage.AdditionalMergeFields)
                {
                    mergeFields.AddOrReplace(mergeField.Key, mergeField.Value);
                }

                string fromAddress = emailMessage.FromEmail;
                string fromName    = emailMessage.FromName;

                // Resolve any possible merge fields in the from address
                fromAddress = fromAddress.ResolveMergeFields(mergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands);
                fromName    = fromName.ResolveMergeFields(mergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands);

                // From - if none is set, use the one in the Organization's GlobalAttributes.
                var globalAttributes = GlobalAttributesCache.Get();
                if (string.IsNullOrWhiteSpace(fromAddress))
                {
                    fromAddress = globalAttributes.GetValue("OrganizationEmail");
                }

                if (string.IsNullOrWhiteSpace(fromName))
                {
                    fromName = globalAttributes.GetValue("OrganizationName");
                }

                if (fromAddress.IsNullOrWhiteSpace())
                {
                    errorMessages.Add("A From address was not provided and no Organization email address is configured.");
                    return(false);
                }

                MailMessage message = new MailMessage();

                // Reply To
                try
                {
                    if (emailMessage.ReplyToEmail.IsNotNullOrWhiteSpace())
                    {
                        // Resolve any possible merge fields in the replyTo address
                        message.ReplyToList.Add(new MailAddress(emailMessage.ReplyToEmail.ResolveMergeFields(mergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands)));
                    }
                }
                catch { }

                message.IsBodyHtml = true;
                message.Priority   = MailPriority.Normal;

                using (var smtpClient = GetSmtpClient())
                {
                    foreach (var messageRecipient in rockMessage.GetRecipients())
                    {
                        try
                        {
                            foreach (var mergeField in mergeFields)
                            {
                                messageRecipient.MergeFields.AddOrIgnore(mergeField.Key, mergeField.Value);
                            }

                            message.To.Clear();
                            message.CC.Clear();
                            message.Bcc.Clear();
                            message.Headers.Clear();

                            // Set From/To and check safe sender
                            message.From = new MailAddress(fromAddress, fromName);
                            message.To.Add(new MailAddress(
                                               messageRecipient.To.ResolveMergeFields(messageRecipient.MergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands),
                                               messageRecipient.Name.ResolveMergeFields(messageRecipient.MergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands)));
                            CheckSafeSender(message, globalAttributes);

                            // cc
                            foreach (string cc in emailMessage.CCEmails.Where(e => e != ""))
                            {
                                // Resolve any possible merge fields in the cc address
                                string ccRecipient = cc.ResolveMergeFields(messageRecipient.MergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands);
                                message.CC.Add(new MailAddress(ccRecipient));
                            }

                            // bcc
                            foreach (string bcc in emailMessage.BCCEmails.Where(e => e != ""))
                            {
                                // Resolve any possible merge fields in the cc address
                                string bccRecipient = bcc.ResolveMergeFields(messageRecipient.MergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands);
                                message.Bcc.Add(new MailAddress(bccRecipient));
                            }

                            // Subject
                            string subject = ResolveText(emailMessage.Subject, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands, messageRecipient.MergeFields, emailMessage.AppRoot, emailMessage.ThemeRoot);

                            // Body
                            string body = ResolveText(emailMessage.Message, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands, messageRecipient.MergeFields, emailMessage.AppRoot, emailMessage.ThemeRoot);
                            body = Regex.Replace(body, @"\[\[\s*UnsubscribeOption\s*\]\]", string.Empty);

                            message.Subject = subject.Left(998);
                            message.Body    = body;

                            var metaData = new Dictionary <string, string>(emailMessage.MessageMetaData);

                            // If a communication is going to get created, create a guid for tracking the opens/clicks
                            Guid?recipientGuid = null;
                            if (emailMessage.CreateCommunicationRecord)
                            {
                                recipientGuid = Guid.NewGuid();
                                metaData.Add("communication_recipient_guid", recipientGuid.Value.ToString());
                            }

                            using (var rockContext = new RockContext())
                            {
                                // Recreate the attachments
                                message.Attachments.Clear();
                                if (emailMessage.Attachments.Any())
                                {
                                    var binaryFileService = new BinaryFileService(rockContext);
                                    foreach (var binaryFileId in emailMessage.Attachments.Where(a => a != null).Select(a => a.Id))
                                    {
                                        var attachment = binaryFileService.Get(binaryFileId);
                                        if (attachment != null)
                                        {
                                            message.Attachments.Add(new Attachment(attachment.ContentStream, attachment.FileName));
                                        }
                                    }
                                }

                                AddAdditionalHeaders(message, metaData);

                                smtpClient.Send(message);
                            }

                            if (emailMessage.CreateCommunicationRecord)
                            {
                                var transaction = new SaveCommunicationTransaction(messageRecipient, emailMessage.FromName, emailMessage.FromEmail, subject, body);
                                transaction.RecipientGuid = recipientGuid;
                                RockQueue.TransactionQueue.Enqueue(transaction);
                            }
                        }
                        catch (Exception ex)
                        {
                            errorMessages.Add(ex.Message);
                            ExceptionLogService.LogException(ex);
                        }
                    }
                }
            }

            return(!errorMessages.Any());
        }
Example #3
0
        /// <summary>
        /// Sends the specified rock message.
        /// </summary>
        /// <param name="rockMessage">The rock message.</param>
        /// <param name="mediumEntityTypeId">The medium entity type identifier. Not used.</param>
        /// <param name="mediumAttributes">The medium attributes. Not used.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public override bool Send(RockMessage rockMessage, int mediumEntityTypeId, Dictionary <string, string> mediumAttributes, out List <string> errorMessages)
        {
            errorMessages = new List <string>();

            var emailMessage = rockMessage as RockEmailMessage;

            if (emailMessage == null)
            {
                return(!errorMessages.Any());
            }

            var globalAttributes = GlobalAttributesCache.Get();

            // Common Merge Field
            var mergeFields = Lava.LavaHelper.GetCommonMergeFields(null, rockMessage.CurrentPerson);

            foreach (var mergeField in rockMessage.AdditionalMergeFields)
            {
                mergeFields.AddOrReplace(mergeField.Key, mergeField.Value);
            }

            // Resolve any possible merge fields in the from address
            string fromAddress = emailMessage.FromEmail.ResolveMergeFields(mergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands);
            string fromName    = emailMessage.FromName.ResolveMergeFields(mergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands);

            // Replace blank values with organizational defaults
            fromAddress = fromAddress.IsNullOrWhiteSpace() ? globalAttributes.GetValue("OrganizationEmail") : fromAddress;
            fromName    = fromName.IsNullOrWhiteSpace() ? globalAttributes.GetValue("OrganizationName") : fromName;

            if (!fromAddress.IsValidEmail())
            {
                errorMessages.Add("A From address was not provided.");
                return(false);
            }

            RestRequest restRequest = null;

            foreach (var rockMessageRecipient in rockMessage.GetRecipients())
            {
                try
                {
                    restRequest = new RestRequest(GetAttributeValue("Resource"), Method.POST);
                    restRequest.AddParameter("domian", GetAttributeValue("Domain"), ParameterType.UrlSegment);

                    // Reply To
                    if (emailMessage.ReplyToEmail.IsNotNullOrWhiteSpace())
                    {
                        // Resolve any possible merge fields in the replyTo address
                        restRequest.AddParameter("h:Reply-To", emailMessage.ReplyToEmail.ResolveMergeFields(mergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands));
                    }

                    foreach (var mergeField in mergeFields)
                    {
                        rockMessageRecipient.MergeFields.AddOrIgnore(mergeField.Key, mergeField.Value);
                    }

                    // From
                    restRequest.AddParameter("from", new MailAddress(fromAddress, fromName).ToString());

                    // To
                    restRequest.AddParameter(
                        "to",
                        new MailAddress(
                            rockMessageRecipient.To.ResolveMergeFields(rockMessageRecipient.MergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands),
                            rockMessageRecipient.Name.ResolveMergeFields(rockMessageRecipient.MergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands)));

                    // Safe Sender checks
                    CheckSafeSender(restRequest, fromAddress, globalAttributes.GetValue("OrganizationEmail"));

                    // CC
                    foreach (string cc in emailMessage.CCEmails.Where(e => e != string.Empty))
                    {
                        string ccRecipient = cc.ResolveMergeFields(rockMessageRecipient.MergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands);
                        restRequest.AddParameter("cc", ccRecipient);
                    }

                    // BCC
                    foreach (string bcc in emailMessage.BCCEmails.Where(e => e != string.Empty))
                    {
                        string bccRecipient = bcc.ResolveMergeFields(rockMessageRecipient.MergeFields, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands);
                        restRequest.AddParameter("bcc", bccRecipient);
                    }

                    // Subject
                    string subject = ResolveText(emailMessage.Subject, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands, rockMessageRecipient.MergeFields, emailMessage.AppRoot, emailMessage.ThemeRoot).Left(998);
                    restRequest.AddParameter("subject", subject);

                    // Body (html)
                    string body = ResolveText(emailMessage.Message, emailMessage.CurrentPerson, emailMessage.EnabledLavaCommands, rockMessageRecipient.MergeFields, emailMessage.AppRoot, emailMessage.ThemeRoot);
                    body = Regex.Replace(body, @"\[\[\s*UnsubscribeOption\s*\]\]", string.Empty);
                    restRequest.AddParameter("html", body);

                    // Communication record for tracking opens & clicks
                    var  metaData      = new Dictionary <string, string>(emailMessage.MessageMetaData);
                    Guid?recipientGuid = null;

                    if (emailMessage.CreateCommunicationRecord)
                    {
                        recipientGuid = Guid.NewGuid();
                        metaData.Add("communication_recipient_guid", recipientGuid.Value.ToString());
                    }

                    // Additional headers
                    AddAdditionalHeaders(restRequest, metaData);

                    // Attachments
                    if (emailMessage.Attachments.Any())
                    {
                        using (var rockContext = new RockContext())
                        {
                            var binaryFileService = new BinaryFileService(rockContext);
                            foreach (var binaryFileId in emailMessage.Attachments.Where(a => a != null).Select(a => a.Id))
                            {
                                var attachment = binaryFileService.Get(binaryFileId);
                                if (attachment != null)
                                {
                                    MemoryStream ms = new MemoryStream();
                                    attachment.ContentStream.CopyTo(ms);
                                    restRequest.AddFile("attachment", ms.ToArray(), attachment.FileName);
                                }
                            }
                        }
                    }

                    // Send it
                    RestClient restClient = new RestClient
                    {
                        BaseUrl       = new Uri(GetAttributeValue("BaseURL")),
                        Authenticator = new HttpBasicAuthenticator("api", GetAttributeValue("APIKey"))
                    };

                    // Call the API and get the response
                    Response = restClient.Execute(restRequest);

                    // Create the communication record
                    if (emailMessage.CreateCommunicationRecord)
                    {
                        var transaction = new SaveCommunicationTransaction(rockMessageRecipient, emailMessage.FromName, emailMessage.FromEmail, subject, body);
                        transaction.RecipientGuid = recipientGuid;
                        RockQueue.TransactionQueue.Enqueue(transaction);
                    }
                }
                catch (Exception ex)
                {
                    errorMessages.Add(ex.Message);
                    ExceptionLogService.LogException(ex);
                }
            }

            return(!errorMessages.Any());
        }
Example #4
0
        /// <summary>
        /// Sends the specified recipients.
        /// </summary>
        /// <param name="recipients">The recipients.</param>
        /// <param name="from">From.</param>
        /// <param name="fromName">From name.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="body">The body.</param>
        /// <param name="appRoot">The application root.</param>
        /// <param name="themeRoot">The theme root.</param>
        /// <param name="attachments">Attachments.</param>
        /// <param name="createCommunicationHistory">if set to <c>true</c> [create communication history].</param>
        public void Send(List <string> recipients, string from, string fromName, string subject, string body, string appRoot, string themeRoot, List <Attachment> attachments, bool createCommunicationHistory)
        {
            try
            {
                var globalAttributes = GlobalAttributesCache.Read();

                if (string.IsNullOrWhiteSpace(from))
                {
                    from = globalAttributes.GetValue("OrganizationEmail");
                }

                if (!string.IsNullOrWhiteSpace(from))
                {
                    // Resolve any possible merge fields in the from address
                    var    mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(null);
                    string msgFrom     = from.ResolveMergeFields(mergeFields);

                    string msgSubject = subject;
                    string msgBody    = body;
                    if (!string.IsNullOrWhiteSpace(themeRoot))
                    {
                        msgSubject = msgSubject.Replace("~~/", themeRoot);
                        msgBody    = msgBody.Replace("~~/", themeRoot);
                    }

                    if (!string.IsNullOrWhiteSpace(appRoot))
                    {
                        msgSubject = msgSubject.Replace("~/", appRoot);
                        msgBody    = msgBody.Replace("~/", appRoot);
                        msgBody    = msgBody.Replace(@" src=""/", @" src=""" + appRoot);
                        msgBody    = msgBody.Replace(@" href=""/", @" href=""" + appRoot);
                    }

                    MailMessage message = new MailMessage();

                    // set from
                    if (!string.IsNullOrWhiteSpace(fromName))
                    {
                        message.From = new MailAddress(msgFrom, fromName);
                    }
                    else
                    {
                        message.From = new MailAddress(msgFrom);
                    }

                    CheckSafeSender(message, globalAttributes);

                    message.IsBodyHtml = true;
                    message.Priority   = MailPriority.Normal;

                    message.To.Clear();
                    recipients.ForEach(r => message.To.Add(r));

                    message.Subject = msgSubject;

                    // strip out any unsubscribe links since we don't know the person
                    msgBody = Regex.Replace(msgBody, @"\[\[\s*UnsubscribeOption\s*\]\]", string.Empty);

                    message.Body = msgBody;

                    // add attachments
                    if (attachments != null)
                    {
                        foreach (var attachment in attachments)
                        {
                            message.Attachments.Add(attachment);
                        }
                    }

                    AddAdditionalHeaders(message, null);

                    using (var smtpClient = GetSmtpClient())
                    {
                        smtpClient.Send(message);
                    }

                    if (createCommunicationHistory)
                    {
                        var transaction = new SaveCommunicationTransaction(
                            recipients, fromName, from, subject, body);
                        RockQueue.TransactionQueue.Enqueue(transaction);
                    }
                }
            }
            catch (Exception ex)
            {
                ExceptionLogService.LogException(ex, null);
            }
        }
Example #5
0
        /// <summary>
        /// Sends the specified medium data to the specified list of recipients.
        /// </summary>
        /// <param name="mediumData">The medium data.</param>
        /// <param name="recipients">The recipients.</param>
        /// <param name="appRoot">The application root.</param>
        /// <param name="themeRoot">The theme root.</param>
        /// <param name="createCommunicationHistory">if set to <c>true</c> [create communication history].</param>
        /// <param name="metaData">The meta data.</param>
        public void Send(Dictionary <string, string> mediumData, List <string> recipients, string appRoot, string themeRoot, bool createCommunicationHistory, Dictionary <string, string> metaData)
        {
            try
            {
                var globalAttributes = GlobalAttributesCache.Read();

                string from     = string.Empty;
                string fromName = string.Empty;
                mediumData.TryGetValue("From", out from);

                if (string.IsNullOrWhiteSpace(from))
                {
                    from     = globalAttributes.GetValue("OrganizationEmail");
                    fromName = globalAttributes.GetValue("OrganizationName");
                }

                if (!string.IsNullOrWhiteSpace(from))
                {
                    // Resolve any possible merge fields in the from address
                    var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(null);
                    from     = from.ResolveMergeFields(mergeFields);
                    fromName = fromName.ResolveMergeFields(mergeFields);

                    string subject = string.Empty;
                    mediumData.TryGetValue("Subject", out subject);

                    string body = string.Empty;
                    mediumData.TryGetValue("Body", out body);

                    if (!string.IsNullOrWhiteSpace(themeRoot))
                    {
                        subject = subject.Replace("~~/", themeRoot);
                        body    = body.Replace("~~/", themeRoot);
                    }

                    if (!string.IsNullOrWhiteSpace(appRoot))
                    {
                        subject = subject.Replace("~/", appRoot);
                        body    = body.Replace("~/", appRoot);
                        body    = body.Replace(@" src=""/", @" src=""" + appRoot);
                        body    = body.Replace(@" href=""/", @" href=""" + appRoot);
                    }

                    MailMessage message = new MailMessage();

                    if (string.IsNullOrWhiteSpace(fromName))
                    {
                        message.From = new MailAddress(from);
                    }
                    else
                    {
                        message.From = new MailAddress(from, fromName);
                    }

                    // Reply To
                    try
                    {
                        string replyTo = string.Empty;
                        mediumData.TryGetValue("ReplyTo", out replyTo);

                        if (!string.IsNullOrWhiteSpace(replyTo))
                        {
                            message.ReplyToList.Add(new MailAddress(replyTo));
                        }
                    }
                    catch { }

                    CheckSafeSender(message, globalAttributes);

                    message.IsBodyHtml = true;
                    message.Priority   = MailPriority.Normal;

                    message.To.Clear();
                    recipients.ForEach(r => message.To.Add(r));
                    message.Subject = subject;
                    message.Body    = body;

                    AddAdditionalHeaders(message, metaData);

                    using (var smtpClient = GetSmtpClient())
                    {
                        smtpClient.Send(message);
                    }

                    if (createCommunicationHistory)
                    {
                        var transaction = new SaveCommunicationTransaction(
                            recipients, fromName, from, subject, body);
                        RockQueue.TransactionQueue.Enqueue(transaction);
                    }
                }
            }
            catch (Exception ex)
            {
                ExceptionLogService.LogException(ex, null);
            }
        }
Example #6
0
        /// <summary>
        /// Sends the specified template.
        /// </summary>
        /// <param name="template">The template.</param>
        /// <param name="recipients">The recipients.</param>
        /// <param name="appRoot">The application root.</param>
        /// <param name="themeRoot">The theme root.</param>
        /// <param name="createCommunicationHistory">if set to <c>true</c> [create communication history].</param>
        public void Send(SystemEmail template, List <RecipientData> recipients, string appRoot, string themeRoot, bool createCommunicationHistory)
        {
            var globalAttributes = GlobalAttributesCache.Read();

            string from = template.From;

            if (string.IsNullOrWhiteSpace(from))
            {
                from = globalAttributes.GetValue("OrganizationEmail");
            }

            string fromName = template.FromName;

            if (string.IsNullOrWhiteSpace(fromName))
            {
                fromName = globalAttributes.GetValue("OrganizationName");
            }

            if (!string.IsNullOrWhiteSpace(from))
            {
                // Resolve any possible merge fields in the from address
                var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(null);
                from     = from.ResolveMergeFields(mergeFields);
                fromName = fromName.ResolveMergeFields(mergeFields);

                MailMessage message = new MailMessage();
                if (string.IsNullOrWhiteSpace(fromName))
                {
                    message.From = new MailAddress(from);
                }
                else
                {
                    message.From = new MailAddress(from, fromName);
                }

                CheckSafeSender(message, globalAttributes);

                if (!string.IsNullOrWhiteSpace(template.Cc))
                {
                    foreach (string ccRecipient in template.Cc.SplitDelimitedValues())
                    {
                        message.CC.Add(new MailAddress(ccRecipient));
                    }
                }

                if (!string.IsNullOrWhiteSpace(template.Bcc))
                {
                    foreach (string ccRecipient in template.Bcc.SplitDelimitedValues())
                    {
                        message.Bcc.Add(new MailAddress(ccRecipient));
                    }
                }

                message.IsBodyHtml = true;
                message.Priority   = MailPriority.Normal;

                using (var smtpClient = GetSmtpClient())
                {
                    foreach (var recipientData in recipients)
                    {
                        foreach (var g in mergeFields)
                        {
                            if (recipientData.MergeFields.ContainsKey(g.Key))
                            {
                                recipientData.MergeFields[g.Key] = g.Value;
                            }
                        }

                        // Add the recipients from the template
                        List <string> sendTo = SplitRecipient(template.To);

                        // Add the recipient from merge data ( if it's not null and not already added )
                        if (!string.IsNullOrWhiteSpace(recipientData.To) && !sendTo.Contains(recipientData.To, StringComparer.OrdinalIgnoreCase))
                        {
                            sendTo.Add(recipientData.To);
                        }

                        foreach (string to in sendTo)
                        {
                            message.To.Clear();
                            message.To.Add(to);

                            message.Headers.Clear();

                            string subject = template.Subject.ResolveMergeFields(recipientData.MergeFields);
                            string body    = Regex.Replace(template.Body.ResolveMergeFields(recipientData.MergeFields), @"\[\[\s*UnsubscribeOption\s*\]\]", string.Empty);

                            if (!string.IsNullOrWhiteSpace(themeRoot))
                            {
                                subject = subject.Replace("~~/", themeRoot);
                                body    = body.Replace("~~/", themeRoot);
                            }

                            if (!string.IsNullOrWhiteSpace(appRoot))
                            {
                                subject = subject.Replace("~/", appRoot);
                                body    = body.Replace("~/", appRoot);
                                body    = body.Replace(@" src=""/", @" src=""" + appRoot);
                                body    = body.Replace(@" src='/", @" src='" + appRoot);
                                body    = body.Replace(@" href=""/", @" href=""" + appRoot);
                                body    = body.Replace(@" href='/", @" href='" + appRoot);
                            }

                            message.Subject = subject;
                            message.Body    = body;

                            AddAdditionalHeaders(message, null);

                            smtpClient.Send(message);

                            if (createCommunicationHistory)
                            {
                                var transaction = new SaveCommunicationTransaction(
                                    to, fromName, from, subject, body);
                                RockQueue.TransactionQueue.Enqueue(transaction);
                            }
                        }
                    }
                }
            }
        }