Example #1
0
        private SubscriberBatchDTO AddSubscribersToBatch(MpBulkEmailPublication publication, List <MpBulkEmailSubscriber> subscribers)
        {
            var batch = new SubscriberBatchDTO();

            batch.Operations = new List <SubscriberOperationDTO>();

            foreach (var subscriber in subscribers)
            {
                if (subscriber.EmailAddress != subscriber.ThirdPartyContactId)
                {
                    if (!string.IsNullOrEmpty(subscriber.ThirdPartyContactId))
                    {
                        var unsubscribeOperation = UnsubscribeOldEmailAddress(publication, subscriber);
                        batch.Operations.Add(unsubscribeOperation);
                    }

                    //Assuming success here, update the ID to match the emailaddress
                    //TODO: US2782 - need to also recongnize this is an email change and handle this acordingly
                    subscriber.ThirdPartyContactId = subscriber.EmailAddress;
                    _bulkEmailRepository.UpdateSubscriber(_token, subscriber);
                }

                var operation = GetOperation(publication, subscriber);
                batch.Operations.Add(operation);
            }

            return(batch);
        }
Example #2
0
        private void PullSubscriptionStatusChangesFromThirdParty(MpBulkEmailPublication publication)
        {
            var client = GetBulkEmailClient();

            // query mailchimp to get list activity
            var lastSuccessfulSync = publication.LastSuccessfulSync.ToUniversalTime().ToString("u");
            var request            = new RestRequest("lists/" + publication.ThirdPartyPublicationId + "/members?since_last_changed=" + lastSuccessfulSync +
                                                     "&fields=members.id,members.email_address,members.status&activity=status&count=" + MAX_SYNC_RECORDS,
                                                     Method.GET);

            request.AddHeader("Content-Type", "application/json");

            try
            {
                var response = client.Execute(request);

                if (response.StatusCode != HttpStatusCode.OK)
                {
                    // This will be addressed in US2861: MP/MailChimp Synch Error Handling
                    // TODO: Should these be exceptions?
                    _logger.ErrorFormat("Http failed syncing opts for publication {0} with StatusCode = {1}", publication.PublicationId, response.StatusCode);
                    return;
                }

                var responseContent     = response.Content;
                var responseContentJson = JObject.Parse(responseContent);
                List <BulkEmailSubscriberOptDTO> subscribersDTOs = JsonConvert.DeserializeObject <List <BulkEmailSubscriberOptDTO> >(responseContentJson["members"].ToString());

                SetStatuses(publication, subscribersDTOs);
            }
            catch (Exception ex)
            {
                _logger.ErrorFormat("Opt-in sync code failed for publication {0} Detail: {1}", publication.PublicationId, ex);
            }
        }
Example #3
0
        private SubscriberOperationDTO UnsubscribeOldEmailAddress(MpBulkEmailPublication publication, MpBulkEmailSubscriber subscriber)
        {
            var updatedSubcriber = subscriber.Clone();

            updatedSubcriber.Subscribed = false;
            var updateOperation = GetOperation(publication, updatedSubcriber);

            return(updateOperation);
        }
Example #4
0
        public void UpdateLastSyncDate(string token, MpBulkEmailPublication publication)
        {
            var publicationDictionary = new Dictionary <string, object>
            {
                { "Publication_ID", publication.PublicationId },
                { "Last_Successful_Sync", publication.LastSuccessfulSync }
            };

            _ministryPlatformService.UpdateRecord(Convert.ToInt32(AppSettings("Publications")), publicationDictionary, token);
        }
Example #5
0
        public string SendBatch(MpBulkEmailPublication publication, List <MpBulkEmailSubscriber> subscribers, int batchIndex)
        {
            var client = GetBulkEmailClient();

            var request = new RestRequest("batches", Method.POST);

            request.AddHeader("Content-Type", "application/json");

            var batch = AddSubscribersToBatch(publication, subscribers);

            request.JsonSerializer = new RestsharpJsonNetSerializer();
            request.RequestFormat  = DataFormat.Json;
            request.AddBody(batch);

            var response = client.Execute(request);

            if (response.StatusCode != HttpStatusCode.OK)
            {
                // This will be addressed is US2861: MP/MailChimp Synch Error Handling
                // TODO: Should these be exceptions?
                _logger.ErrorFormat("Failed sending batch {0} for publication {1} with StatusCode = {2}", batchIndex, publication.PublicationId, response.StatusCode);
                return(null);
            }

            var content = response.Content;

            if (String.IsNullOrEmpty(content))
            {
                // This will be addressed is US2861: MP/MailChimp Synch Error Handling
                // TODO: Should these be exceptions?
                // TODO: Add logging code here for failure
                _logger.ErrorFormat("Bulk email sync failed for batch {0} for publication {1} empty response", batchIndex, publication.PublicationId);
                return(null);
            }

            var responseValues = DeserializeToDictionary(content);

            // this needs to be returned, because we can't guarantee that the operation won't fail after it begins
            if (responseValues["status"].ToString() == "started" ||
                responseValues["status"].ToString() == "pending" ||
                responseValues["status"].ToString() == "finished")
            {
                return(responseValues["id"].ToString());
            }
            else
            {
                // This will be addressed is US2861: MP/MailChimp Synch Error Handling
                // TODO: Should these be exceptions?
                // TODO: Add logging code here for failure
                _logger.ErrorFormat("Bulk email sync failed for batch {0} publication {1} Response detail: {2}", batchIndex, publication.PublicationId, content);
                return(null);
            }
        }
Example #6
0
        public void SetStatuses(MpBulkEmailPublication publication, List <BulkEmailSubscriberOptDTO> subscribersDTOs)
        {
            List <MpBulkEmailSubscriberOpt> subscriberOpts = new List <MpBulkEmailSubscriberOpt>();

            foreach (var subscriberDTO in subscribersDTOs)
            {
                subscriberDTO.PublicationID = publication.PublicationId;
                subscriberOpts.Add(Mapper.Map <MpBulkEmailSubscriberOpt>(subscriberDTO));
            }

            foreach (var subscriberOpt in subscriberOpts)
            {
                _logger.InfoFormat("Changing subscription status for {0} to {1}", subscriberOpt.EmailAddress, subscriberOpt.Status);
                _bulkEmailRepository.SetSubscriberStatus(_token, subscriberOpt);
            }
        }
Example #7
0
        private List <string> CreateAndSendBatches(MpBulkEmailPublication publication, List <MpBulkEmailSubscriber> subscribers)
        {
            var batchSize    = 10000;
            var batches      = Math.Ceiling(subscribers.Count / (decimal)batchSize);
            var operationIds = new List <string>();

            for (var batchIndex = 0; batchIndex < batches; batchIndex++)
            {
                var currentBatch = subscribers.Skip(batchIndex * batchSize).Take(batchSize);
                var operationId  = SendBatch(publication, currentBatch.ToList(), batchIndex);

                if (!string.IsNullOrEmpty(operationId))
                {
                    operationIds.Add(operationId);
                }
            }

            return(operationIds);
        }
Example #8
0
        private SubscriberOperationDTO GetOperation(MpBulkEmailPublication publication, MpBulkEmailSubscriber subscriber)
        {
            var mailChimpSubscriber = new SubscriberDTO();

            mailChimpSubscriber.Subscribed   = subscriber.Subscribed;
            mailChimpSubscriber.EmailAddress = subscriber.ThirdPartyContactId;
            mailChimpSubscriber.MergeFields  = subscriber.MergeFields;

            var hashedEmail = CalculateMD5Hash(mailChimpSubscriber.EmailAddress.ToLower());

            var operation = new SubscriberOperationDTO();

            operation.Method = "PUT";
            operation.Path   = string.Format("lists/{0}/members/{1}", publication.ThirdPartyPublicationId, hashedEmail);

            // TODO: Do we need to store this somewhere to verify subscriber processed successfully
            operation.OperationId = Guid.NewGuid().ToString();
            operation.Body        = JsonConvert.SerializeObject(mailChimpSubscriber);

            return(operation);
        }
Example #9
0
        private void ProcessSynchronizationResultsForPublication(List <string> operations, RestClient client, MpBulkEmailPublication publication)
        {
            for (var operationIndex = operations.Count - 1; operationIndex >= 0; operationIndex--)
            {
                var operationId = operations[operationIndex];
                var request     = new RestRequest("batches/" + operationId, Method.GET);
                request.AddHeader("Content-Type", "application/json");

                var response = client.Execute(request);
                if (response.StatusCode != HttpStatusCode.OK)
                {
                    // This will be addressed is US2861: MP/MailChimp Synch Error Handling
                    _logger.WarnFormat("Received StatusCode = {0} when querying for status of publication {1} for operation {2}",
                                       response.StatusCode,
                                       publication.PublicationId,
                                       operationId);
                    continue;
                }

                var responseValues = DeserializeToDictionary(response.Content);

                if (responseValues["status"].ToString() == "started" || responseValues["status"].ToString() == "pending")
                {
                    continue;
                }

                if (responseValues["status"].ToString() == "finished")
                {
                    var total  = responseValues["total_operations"];
                    var errors = responseValues["errored_operations"];

                    if (errors.ToString() == "0")
                    {
                        _logger.InfoFormat("Processed {0} total records for publication {1} and operation {2}", total, publication.PublicationId, operationId);
                    }
                    else
                    {
                        _logger.ErrorFormat("Processed {0} total records with {1} errors for publication {2} and operation {3}", total, errors, publication.PublicationId, operationId);
                    }

                    _logger.Info(response.Content);

                    var completedAt = DateTime.Parse(responseValues["completed_at"].ToString());
                    if (publication.LastSuccessfulSync <= completedAt)
                    {
                        publication.LastSuccessfulSync = completedAt;
                    }
                }
                else
                {
                    // This will be addressed is US2861: MP/MailChimp Synch Error Handling
                    // TODO: Should these be exceptions?
                    // TODO: Add logging code here for failure
                    _logger.ErrorFormat("Bulk email sync failed for publication {0} and operation {1} Response detail: {2}", publication.PublicationId, operationId, response.Content);
                }

                operations.RemoveAt(operationIndex);
            }
        }