public void UpdateLastSyncDate(string token, BulkEmailPublication publication)
 {
     var publicationDictionary = new Dictionary<string, object>
     {
         {"Publication_ID", publication.PublicationId},
         {"Last_Successful_Sync", publication.LastSuccessfulSync}
     };
     _ministryPlatformService.UpdateRecord(Convert.ToInt32(AppSettings("Publications")), publicationDictionary, token);
 }
        public string SendBatch(BulkEmailPublication publication, List<BulkEmailSubscriber> subscribers)
        {
            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.Error(string.Format("Failed sending batch for publication {0} with StatusCode = {1}", publication.PublicationId, response.StatusCode));
                return null;
            }

            var responseValues = DeserializeToDictionary(response.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.Error(string.Format("Bulk email sync failed for publication {0} Response detail: {1}", publication.PublicationId, response.Content));
                return null;
            }
        }
        private void PullSubscriptionStatusChangesFromThirdParty(BulkEmailPublication 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.Error(string.Format("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());
                List<BulkEmailSubscriberOpt> subscribers = new List<BulkEmailSubscriberOpt>();

                foreach (var subscriberDTO in subscribersDTOs)
                {
                    subscriberDTO.PublicationID = publication.PublicationId;
                    subscribers.Add(Mapper.Map<BulkEmailSubscriberOpt>(subscriberDTO));

                    _logger.InfoFormat("Changing subscription status for {0} to {1}", subscriberDTO.EmailAddress, subscriberDTO.Status);
                }

                _bulkEmailRepository.SetSubscriberSyncs(_token, subscribers);
            }
            catch (Exception ex)
            {
                _logger.Error(string.Format("Opt-in sync code failed for publication {0} Detail: {1}", publication.PublicationId, ex));
            }
        }
        private SubscriberOperationDTO GetOperation(BulkEmailPublication publication, BulkEmailSubscriber 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;
        }
 private SubscriberOperationDTO UnsubscribeOldEmailAddress(BulkEmailPublication publication, BulkEmailSubscriber subscriber)
 {
     var updatedSubcriber = subscriber.Clone();
     updatedSubcriber.Subscribed = false;
     var updateOperation = GetOperation(publication, updatedSubcriber);
     return updateOperation;
 }
        private SubscriberBatchDTO AddSubscribersToBatch(BulkEmailPublication publication, List<BulkEmailSubscriber> 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;
        }