/// <summary>
        ///     Sends the acceptance.
        /// </summary>
        /// <param name="calendar">The calendar.</param>
        /// <param name="iCalMessage">The i cal message.</param>
        /// <param name="eventEmail">The event email.</param>
        private static void SendAcceptance(IICalendar calendar, ReceivedICalEmailMessage iCalMessage, EventEmail eventEmail)
        {
            Inbox inbox = iCalMessage.FromInbox;

            string subject = string.Format("{0}: {1}", GlobalStrings.Accepted, iCalMessage.EmSubject ?? GlobalStrings.MeetingInvitation);

            /////
            // Create the new mail message.
            /////
            var sentMessage = new SentICalEmailMessage
            {
                Name            = subject,
                EmFrom          = inbox.InboxEmailAddress,
                EmTo            = iCalMessage.EmFrom,
                EmSubject       = subject,
                EmBody          = iCalMessage.EmBody ?? string.Empty,
                EmIsHtml        = iCalMessage.EmIsHtml ?? true,
                OwnerEventEmail = eventEmail
            };

            sentMessage.Save( );

            var emailServerSettings = Entity.Get <TenantEmailSetting>("core:tenantEmailSettingsInstance");

            iCalEmailHelper.SendICalEmail(calendar, sentMessage.As <SentEmailMessage>( ).ToMailMessage( ), emailServerSettings);
        }
        /// <summary>
        ///     Executed before the message is saved
        /// </summary>
        /// <param name="message"></param>
        /// <param name="postSaveAction">if not null an action run after the save. This happens even if the save is cancelled.</param>
        /// <returns>
        ///     True if the save is to be cancelled
        /// </returns>
        public bool BeforeSave(ReceivedEmailMessage message, out Action postSaveAction)
        {
            postSaveAction = null;

            /////
            // Check the message.
            /////
            if (message == null)
            {
                return(false);
            }

            var iCalMessage = message.As <ReceivedICalEmailMessage>( );

            /////
            // Ensure the message is a received iCal email message.
            /////
            if (iCalMessage == null)
            {
                return(false);
            }

            /////
            // The iCalUpdate field was set by the iCalMailMesssageFormatter that was called as part
            // of the ProcessInboxes action.
            /////
            if (string.IsNullOrEmpty(iCalMessage.ICalUpdate))
            {
                return(false);
            }

            /////
            // Read the iCal update.
            /////
            using (var sr = new StringReader(iCalMessage.ICalUpdate))
            {
                /////
                // Deserialize the string into the iCal object model.
                /////
                IICalendarCollection iCalendarCollection = iCalendar.LoadFromStream(sr);

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

                /////
                // Get the first calendar.
                /////
                IICalendar calendar = iCalendarCollection.FirstOrDefault( );

                if (calendar == null || calendar.Events == null)
                {
                    return(false);
                }

                /////
                // Get the first calendar event.
                /////
                IEvent calendarEvent = calendar.Events.FirstOrDefault( );

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

                /////
                // Make sure the calendar events UID is set.
                /////
                if (string.IsNullOrEmpty(calendarEvent.Uid))
                {
                    return(false);
                }

                EventEmail  eventEntity = null;
                Appointment appointment = null;

                /////
                // Find all sent iCal UID containers that correlate to the received calendar events UID.
                /////
                IEnumerable <ICalUidContainer> iCalUidContainers = Entity.GetByField <ICalUidContainer>(calendarEvent.Uid, ICalUidContainer.ICalUid_Field);

                if (iCalUidContainers != null)
                {
                    /////
                    // Get the first sent message.
                    /////
                    ICalUidContainer iCalUidContainer = iCalUidContainers.FirstOrDefault( );

                    if (iCalUidContainer != null && iCalUidContainer.CalendarEventEmail != null)
                    {
                        /////
                        // Get the original event email object that was used to create the sent iCal Email Message.
                        /////
                        eventEntity = iCalUidContainer.CalendarEventEmail.AsWritable <EventEmail>( );
                    }
                }

                bool modificationsMade = false;

                if (eventEntity == null)
                {
                    /////
                    // No existing event email so this is a new request.
                    /////
                    EntityRef type = GetEventCreationType(message);

                    eventEntity = type != null?Entity.Create(type).As <EventEmail>( ) : new EventEmail( );

                    appointment = Entity.Create <Appointment>();
                    eventEntity.EventEmailAppt = appointment;

                    modificationsMade = true;

                    eventEntity.Name = calendarEvent.Summary;

                    var calUidContainer = new ICalUidContainer
                    {
                        ICalUid = calendarEvent.Uid
                    };

                    eventEntity.CalendarId = calUidContainer;

                    string creatorEmailAddress = GetEmailAddress(message.EmFrom);

                    if (creatorEmailAddress != null)
                    {
                        EmailContact creatorEmailContact = FindEmailContact(creatorEmailAddress);

                        if (creatorEmailContact == null)
                        {
                            var mailAddress = new MailAddress(message.EmFrom);

                            creatorEmailContact = CreateEmailContact(creatorEmailAddress, mailAddress.DisplayName ?? creatorEmailAddress);
                        }

                        eventEntity.EventEmailCreator = creatorEmailContact;
                    }

                    foreach (IAttendee attendee in calendarEvent.Attendees)
                    {
                        string emailAddress = GetEmailAddress(attendee.Value.ToString( ));

                        if (emailAddress != null)
                        {
                            EmailContact emailContact = FindEmailContact(emailAddress);

                            if (emailContact == null)
                            {
                                CreateEmailContact(emailAddress, attendee.CommonName);
                            }

                            appointment.EventEmailAttendees.Add(emailContact.EmailContactOwner);
                        }
                    }

                    CreateAndSendAcceptance(calendar, iCalMessage, eventEntity);
                }
                else
                {
                    appointment = eventEntity.EventEmailAppt;

                    if (calendar.Method == Methods.Publish || calendar.Method == Methods.Request)
                    {
                        /////
                        // A REQUEST or PUBLISH means a new event arriving in the system.
                        /////
                        CreateAndSendAcceptance(calendar, iCalMessage, eventEntity);
                    }
                }


                eventEntity.ReceivedEmailMessages.Add(iCalMessage);


                /////
                // Start time.
                /////
                if (calendarEvent.Start != null)
                {
                    DateTime utcTime = calendarEvent.Start.Utc;

                    if (!Equals(utcTime, appointment.EventStart))
                    {
                        appointment.EventStart = utcTime;
                        modificationsMade      = true;
                    }
                }

                /////
                // End time.
                /////
                if (calendarEvent.End != null)
                {
                    DateTime utcTime = calendarEvent.End.Utc;

                    if (!Equals(utcTime, appointment.EventEnd))
                    {
                        appointment.EventEnd = utcTime;
                        modificationsMade    = true;
                    }
                }

                /////
                // All Day Event.
                /////
                if (appointment.EventIsAllDay == null || !Equals(calendarEvent.IsAllDay, appointment.EventIsAllDay.Value))
                {
                    appointment.EventIsAllDay = calendarEvent.IsAllDay;
                    modificationsMade         = true;
                }

                /////
                // Location.
                /////
                if (calendarEvent.Location != null)
                {
                    if (!Equals(calendarEvent.Location, appointment.EventLocation))
                    {
                        appointment.EventLocation = calendarEvent.Location;
                        modificationsMade         = true;
                    }
                }

                /////
                // Location.
                /////
                if (eventEntity.EventEmailAppt.EventEmailPriority == null || !Equals(calendarEvent.Priority, eventEntity.EventEmailAppt.EventEmailPriority))
                {
                    string priorityAlias;

                    if (calendarEvent.Priority <= 0)
                    {
                        /////
                        // Undefined.
                        /////
                        priorityAlias = null;
                    }
                    else if (calendarEvent.Priority <= 4)
                    {
                        /////
                        // High priority.
                        /////
                        priorityAlias = "core:highPriority";
                    }
                    else if (calendarEvent.Priority == 5)
                    {
                        /////
                        // Normal priority.
                        /////
                        priorityAlias = "core:normalPriority";
                    }
                    else if (calendarEvent.Priority <= 9)
                    {
                        /////
                        // Low priority.
                        /////
                        priorityAlias = "core:lowPriority";
                    }
                    else
                    {
                        /////
                        // Invalid priority.
                        /////
                        priorityAlias = null;
                    }

                    eventEntity.EventEmailAppt.EventEmailPriority = priorityAlias != null?Entity.Get <EventEmailPriorityEnum>(priorityAlias) : null;

                    modificationsMade = true;
                }

                /////
                // Status.
                /////
                string statusAlias = null;

                switch (calendarEvent.Status)
                {
                case EventStatus.Cancelled:
                    statusAlias = "core:eventStatusCancelled";
                    break;

                case EventStatus.Confirmed:
                    statusAlias = "core:eventStatusConfirmed";
                    break;

                case EventStatus.Tentative:
                    statusAlias = "core:eventStatusTentative";
                    break;
                }

                if (!string.IsNullOrEmpty(statusAlias))
                {
                    if (appointment.EventStatus == null || appointment.EventStatus.Alias != statusAlias)
                    {
                        appointment.EventStatus = Entity.Get <EventStatusEnum>(statusAlias);
                        modificationsMade       = true;
                    }
                }

                if (modificationsMade)
                {
                    CustomContext cc = null;

                    try
                    {
                        string timeZone = null;

                        if (eventEntity != null)
                        {
                            /////
                            // Find all sent iCal Email Messages that correlate to the received calendar events UID.
                            /////
                            IEnumerable <SentICalEmailMessage> sentICalEmailMessages = eventEntity.SentEmailMessages;

                            if (sentICalEmailMessages != null)
                            {
                                SentICalEmailMessage sentICalEmailMessage = sentICalEmailMessages.FirstOrDefault(sent => sent.ICalTimeZone != null);

                                if (sentICalEmailMessage != null)
                                {
                                    timeZone = sentICalEmailMessage.ICalTimeZone;
                                }
                            }
                        }

                        if (string.IsNullOrEmpty(timeZone))
                        {
                            if (calendar.TimeZones != null)
                            {
                                ITimeZone calendarTimeZone = calendar.TimeZones.FirstOrDefault( );

                                if (calendarTimeZone != null)
                                {
                                    timeZone = calendarTimeZone.TzId;
                                }
                            }
                        }

                        if (!string.IsNullOrEmpty(timeZone))
                        {
                            /////
                            // Set up a custom context just for the duration of this call.
                            /////
                            RequestContext currentRequestContext = RequestContext.GetContext( );

                            var data = new RequestContextData(currentRequestContext)
                            {
                                TimeZone = timeZone
                            };

                            cc = new CustomContext(data);
                        }

                        eventEntity.Save( );
                    }
                    finally
                    {
                        /////
                        // Ensure the custom context is disposed.
                        /////
                        if (cc != null)
                        {
                            cc.Dispose( );
                        }
                    }
                }
            }

            return(false);
        }