private void SendEmailToContact(ContactData contact, MessageItem messageItem)
        {
            var customValues = new ExmCustomValues
            {
                DispatchType    = DispatchType.Normal,
                Email           = contact.PreferredEmail,
                MessageLanguage = messageItem.TargetLanguage.ToString(),
                ManagerRootId   = messageItem.ManagerRoot.InnerItem.ID.ToGuid(),
                MessageId       = messageItem.InnerItem.ID.ToGuid()
            };

            EcmFactory.GetDefaultFactory()
            .Bl.DispatchManager.EnrollOrUpdateContact(contact.ContactId, new DispatchQueueItem(),
                                                      messageItem.PlanId.ToGuid(), Sitecore.Modules.EmailCampaign.Core.Constants.SendCompletedStateName,
                                                      customValues);

            ExmEventsGenerator.GenerateSent(_managerRoot.Settings.BaseURL, new ID(contact.ContactId), messageItem.InnerItem.ID,
                                            messageItem.StartTime);
            _specification.Job.CompletedEmails++;
        }
        private async void GenerateEvents(MessageItem email, Funnel funnelDefinition, List <ContactData> contactsForThisEmail)
        {
            if (funnelDefinition == null)
            {
                return;
            }

            var contactIndex = 1;

            foreach (var contactId in contactsForThisEmail)
            {
                _specification.Job.Status = $"Generating events for contact {contactIndex++} of {contactsForThisEmail.Count}";

                var contact = _contactService.GetContact(contactId.ContactId);
                if (contact == null)
                {
                    continue;
                }

                if (_random.NextDouble() < funnelDefinition.Bounced / 100d)
                {
                    ExmEventsGenerator.GenerateBounce(_managerRoot.Settings.BaseURL, contact.ContactId.ToID(),
                                                      email.MessageId.ToID(), email.StartTime.AddMinutes(1));
                }
                else
                {
                    var userAgent = _userAgent();
                    var geoData   = _geoData();
                    var eventDay  = _eventDay();
                    var seconds   = _random.Next(60, 86400);
                    var eventDate = email.StartTime.AddDays(eventDay).AddSeconds(seconds);

                    var spamPercentage = funnelDefinition.SpamComplaints / 100d;

                    if (_random.NextDouble() < funnelDefinition.OpenRate / 100d)
                    {
                        if (_random.NextDouble() < funnelDefinition.ClickRate / 100d)
                        {
                            spamPercentage = Math.Min(spamPercentage, 0.01);

                            var link = "/";
                            if (_goalId != null)
                            {
                                var goal = _goalId();
                                ID  goalId;
                                if (ID.TryParse(goal, out goalId) && !ID.IsNullOrEmpty(goalId))
                                {
                                    var goalItem = _db.GetItem(goalId);
                                    if (goalItem != null)
                                    {
                                        link = LinkManager.GetItemUrl(goalItem);
                                    }
                                }
                            }

                            ExmEventsGenerator.GenerateHandlerEvent(_managerRoot.Settings.BaseURL, contact.ContactId, email,
                                                                    ExmEvents.Click, eventDate, userAgent, geoData, link);
                            eventDate = eventDate.AddSeconds(_random.Next(10, 300));
                        }
                        else
                        {
                            ExmEventsGenerator.GenerateHandlerEvent(_managerRoot.Settings.BaseURL, contact.ContactId, email,
                                                                    ExmEvents.Open, eventDate, userAgent, geoData);

                            eventDate = eventDate.AddSeconds(_random.Next(10, 300));
                        }
                    }

                    if (_random.NextDouble() < spamPercentage)
                    {
                        await ExmEventsGenerator.GenerateSpamComplaint(_managerRoot.Settings.BaseURL, contact.ContactId.ToID(), email.MessageId.ToID(), "email", eventDate);

                        eventDate = eventDate.AddSeconds(_random.Next(10, 300));
                    }

                    var unsubscribePercentage = funnelDefinition.Unsubscribed / 100d;
                    if (_random.NextDouble() < unsubscribePercentage)
                    {
                        //TODO - Warning: UnsubscribeFromAll not supported
                        var       unsubscribeFromAllPercentage = 0.5;
                        ExmEvents unsubscribeEvent;

                        if (_random.NextDouble() < unsubscribeFromAllPercentage)
                        {
                            unsubscribeEvent = ExmEvents.UnsubscribeFromAll;
                            _unsubscribeFromAllContacts.Add(contact.ContactId);
                        }
                        else
                        {
                            unsubscribeEvent = ExmEvents.Unsubscribe;
                        }

                        ExmEventsGenerator.GenerateHandlerEvent(_managerRoot.Settings.BaseURL, contact.ContactId, email,
                                                                unsubscribeEvent, eventDate, userAgent, geoData);
                    }
                }
                _specification.Job.CompletedEvents++;
            }
        }