Esempio n. 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 pushMessage = rockMessage as RockPushMessage;

            if (pushMessage != null)
            {
                // Get server key
                string serverKey = GetAttributeValue("ServerKey");
                var    sender    = new Sender(serverKey);

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

                var recipients = rockMessage.GetRecipients();

                if (pushMessage.SendSeperatelyToEachRecipient)
                {
                    foreach (var recipient in recipients)
                    {
                        try
                        {
                            foreach (var mergeField in mergeFields)
                            {
                                recipient.MergeFields.AddOrIgnore(mergeField.Key, mergeField.Value);
                            }

                            PushMessage(sender, new List <string> {
                                recipient.To
                            }, pushMessage, recipient.MergeFields);
                        }
                        catch (Exception ex)
                        {
                            errorMessages.Add(ex.Message);
                            ExceptionLogService.LogException(ex, null);
                        }
                    }
                }
                else
                {
                    try
                    {
                        PushMessage(sender, recipients.Select(r => r.To).ToList(), pushMessage, mergeFields);
                    }
                    catch (Exception ex)
                    {
                        errorMessages.Add(ex.Message);
                        ExceptionLogService.LogException(ex, null);
                    }
                }
            }

            return(!errorMessages.Any());
        }
Esempio n. 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());
        }
Esempio n. 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());
        }
Esempio n. 4
0
        /// <summary>
        /// Sends the asynchronous.
        /// </summary>
        /// <param name="rockMessage">The rock message.</param>
        /// <param name="mediumEntityTypeId">The medium entity type identifier.</param>
        /// <param name="mediumAttributes">The medium attributes.</param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public async Task <SendMessageResult> SendAsync(RockMessage rockMessage, int mediumEntityTypeId, Dictionary <string, string> mediumAttributes)
        {
            var sendMessageResult = new SendMessageResult();

            var smsMessage = rockMessage as RockSMSMessage;

            if (smsMessage != null)
            {
                // Validate From Number
                if (smsMessage.FromNumber == null)
                {
                    sendMessageResult.Errors.Add("A From Number was not provided.");
                    return(sendMessageResult);
                }

                string accountSid = GetAttributeValue(TwilioAttributeKey.Sid);
                string authToken  = GetAttributeValue(TwilioAttributeKey.AuthToken);
                TwilioClient.Init(accountSid, authToken);

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

                int?throttlingWaitTimeMS = null;
                if (this.IsLongCodePhoneNumber(smsMessage.FromNumber.Value))
                {
                    throttlingWaitTimeMS = this.GetAttributeValue(TwilioAttributeKey.LongCodeThrottling).AsIntegerOrNull();
                }

                List <Uri> attachmentMediaUrls = GetAttachmentMediaUrls(rockMessage.Attachments.AsQueryable());

                if (throttlingWaitTimeMS.HasValue)
                {
                    foreach (var recipient in rockMessage.GetRecipients())
                    {
                        var result = await SendToRecipientAsync(recipient, mergeFields, smsMessage, attachmentMediaUrls, mediumEntityTypeId, mediumAttributes).ConfigureAwait(false);

                        sendMessageResult.Errors.AddRange(result.Errors);
                        sendMessageResult.Errors.AddRange(result.Warnings);
                        sendMessageResult.MessagesSent += result.MessagesSent;

                        await Task.Delay(throttlingWaitTimeMS.Value).ConfigureAwait(false);
                    }
                }
                else
                {
                    var sendingTask = new List <Task <SendMessageResult> >();

                    using (var mutex = new SemaphoreSlim(MaxParallelization))
                    {
                        foreach (var recipient in rockMessage.GetRecipients())
                        {
                            var startMutexWait = System.Diagnostics.Stopwatch.StartNew();
                            await mutex.WaitAsync().ConfigureAwait(false);

                            sendingTask.Add(ThrottleHelper.ThrottledExecute(() => SendToRecipientAsync(recipient, mergeFields, smsMessage, attachmentMediaUrls, mediumEntityTypeId, mediumAttributes), mutex));
                        }

                        /*
                         * Now that we have fired off all of the task, we need to wait for them to complete, get their results,
                         * and then process that result. Once all of the task have been completed we can continue.
                         */
                        while (sendingTask.Count > 0)
                        {
                            var completedTask = await Task.WhenAny(sendingTask).ConfigureAwait(false);

                            sendingTask.Remove(completedTask);

                            var result = await completedTask.ConfigureAwait(false);

                            sendMessageResult.Errors.AddRange(result.Errors);
                            sendMessageResult.Errors.AddRange(result.Warnings);
                            sendMessageResult.MessagesSent += result.MessagesSent;
                        }
                    }
                }
            }

            return(sendMessageResult);
        }
Esempio n. 5
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 smsMessage = rockMessage as RockSMSMessage;

            if (smsMessage != null)
            {
                // Validate From Number
                if (smsMessage.FromNumber == null)
                {
                    errorMessages.Add("A From Number was not provided.");
                    return(false);
                }

                string accountSid = GetAttributeValue("SID");
                string authToken  = GetAttributeValue("Token");
                TwilioClient.Init(accountSid, authToken);

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

                int?throttlingWaitTimeMS = null;
                if (this.IsLongCodePhoneNumber(smsMessage.FromNumber.Value))
                {
                    throttlingWaitTimeMS = this.GetAttributeValue("Long-CodeThrottling").AsIntegerOrNull();
                }

                List <Uri> attachmentMediaUrls = GetAttachmentMediaUrls(rockMessage.Attachments.AsQueryable());

                foreach (var recipient in rockMessage.GetRecipients())
                {
                    try
                    {
                        foreach (var mergeField in mergeFields)
                        {
                            recipient.MergeFields.AddOrIgnore(mergeField.Key, mergeField.Value);
                        }

                        CommunicationRecipient communicationRecipient = null;

                        using (var rockContext = new RockContext())
                        {
                            CommunicationRecipientService communicationRecipientService = new CommunicationRecipientService(rockContext);
                            int?recipientId = recipient.CommunicationRecipientId;
                            if (recipientId != null)
                            {
                                communicationRecipient = communicationRecipientService.Get(recipientId.Value);
                            }

                            string message         = ResolveText(smsMessage.Message, smsMessage.CurrentPerson, communicationRecipient, smsMessage.EnabledLavaCommands, recipient.MergeFields, smsMessage.AppRoot, smsMessage.ThemeRoot);
                            Person recipientPerson = ( Person )recipient.MergeFields.GetValueOrNull("Person");

                            // Create the communication record and send using that if we have a person since a communication record requires a valid person. Otherwise just send without creating a communication record.
                            if (rockMessage.CreateCommunicationRecord && recipientPerson != null)
                            {
                                var communicationService = new CommunicationService(rockContext);

                                Rock.Model.Communication communication = communicationService.CreateSMSCommunication(smsMessage.CurrentPerson, recipientPerson?.PrimaryAliasId, message, smsMessage.FromNumber, string.Empty, smsMessage.communicationName);

                                // Since we just created a new communication record, we need to move any attachments from the rockMessage
                                // to the communication's attachments since the Send method below will be handling the delivery.
                                if (attachmentMediaUrls.Any())
                                {
                                    foreach (var attachment in rockMessage.Attachments.AsQueryable())
                                    {
                                        communication.AddAttachment(new CommunicationAttachment {
                                            BinaryFileId = attachment.Id
                                        }, CommunicationType.SMS);
                                    }
                                }

                                rockContext.SaveChanges();
                                Send(communication, mediumEntityTypeId, mediumAttributes);
                                continue;
                            }
                            else
                            {
                                MessageResource response = SendToTwilio(smsMessage.FromNumber.Value, null, attachmentMediaUrls, message, recipient.To);

                                if (response.ErrorMessage.IsNotNullOrWhiteSpace())
                                {
                                    errorMessages.Add(response.ErrorMessage);
                                }

                                if (communicationRecipient != null)
                                {
                                    rockContext.SaveChanges();
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        errorMessages.Add(ex.Message);
                        ExceptionLogService.LogException(ex);
                    }

                    if (throttlingWaitTimeMS.HasValue)
                    {
                        System.Threading.Tasks.Task.Delay(throttlingWaitTimeMS.Value).Wait();
                    }
                }
            }

            return(!errorMessages.Any());
        }
Esempio n. 6
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 pushMessage = rockMessage as RockPushMessage;

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

                var         recipients  = rockMessage.GetRecipients();
                RockContext rockContext = new RockContext();

                if (pushMessage.SendSeperatelyToEachRecipient)
                {
                    foreach (var recipient in recipients)
                    {
                        try
                        {
                            foreach (var mergeField in mergeFields)
                            {
                                recipient.MergeFields.AddOrIgnore(mergeField.Key, mergeField.Value);
                            }
                            Person recipientPerson = ( Person )recipient.MergeFields.GetValueOrNull("Person");
                            string personAliasId   = recipientPerson.Aliases.FirstOrDefault().Id.ToString();
                            PushMessage(new List <string> {
                                personAliasId
                            }, pushMessage, recipient.MergeFields);
                        }
                        catch (Exception ex)
                        {
                            errorMessages.Add(ex.Message);
                            ExceptionLogService.LogException(ex, null);
                        }
                    }
                }
                else
                {
                    try
                    {
                        foreach (var recipient in recipients)
                        {
                            Person recipientPerson = (Person)mergeFields.GetValueOrNull("Person");
                            string personAliasId   = recipientPerson.Aliases.FirstOrDefault().Id.ToString();
                            recipient.MergeFields.Add("PersonAliasId", personAliasId);
                        }
                        PushMessage(recipients.Select(r => r.MergeFields.GetValueOrNull("PersonAliasId").ToString()).ToList(), pushMessage, mergeFields);
                    }
                    catch (Exception ex)
                    {
                        errorMessages.Add(ex.Message);
                        ExceptionLogService.LogException(ex, null);
                    }
                }
            }

            return(!errorMessages.Any());
        }