/** <summary>
         * Given a URI/URL, we call iCalendar's LoadFromURI, select the first element in the return, then return true.
         * </summary>
         */
        public bool Load(Uri path)
        {
            iCalc = iCalendar.LoadFromUri(path);

            iCal = iCalc.FirstOrDefault();
            this.Uri = path;
            return true;
        }
        /// <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);
        }
Example #3
0
        /// <summary>
        ///     Gets the Ical update.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="receivedICalEmailMessage">The received I cal email message.</param>
        /// <param name="iCal">The i cal.</param>
        /// <returns></returns>
        private static MailMessageFormatterResult GetICalUpdate(MailMessage message, ReceivedICalEmailMessage receivedICalEmailMessage, out string iCal)
        {
            iCal = null;

            if (message == null)
            {
                return(MailMessageFormatterResult.Skip);
            }

            try
            {
                var attachableItems = new List <AttachmentBase>( );

                attachableItems.AddRange(message.AlternateViews);
                attachableItems.AddRange(message.Attachments);

                /////
                // Locate a view that contains a calendar attachment.
                /////
                foreach (AttachmentBase attachment in attachableItems)
                {
                    if (attachment.ContentType.MediaType == "text/calendar")
                    {
                        /////
                        // Deserialize the iCalendar attachment.
                        /////
                        IICalendarCollection iCalendarCollection = iCalendar.LoadFromStream(attachment.ContentStream);

                        if (iCalendarCollection != null)
                        {
                            IICalendar calendar = iCalendarCollection.FirstOrDefault( );

                            if (calendar != null)
                            {
                                if (calendar.Method == Methods.Reply)
                                {
                                    IEvent calendarEvent = calendar.Events.FirstOrDefault( );

                                    if (calendarEvent != null && !string.IsNullOrEmpty(calendarEvent.Uid))
                                    {
                                        /////
                                        // Find all 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 iCal UID container.
                                            /////
                                            ICalUidContainer iCalUidContainer = iCalUidContainers.FirstOrDefault( );

                                            if (iCalUidContainer != null && iCalUidContainer.CalendarEventEmail != null)
                                            {
                                                /////
                                                // Get the original event email object that was used to calendar UID container.
                                                /////
                                                EventEmail eventEntity = iCalUidContainer.CalendarEventEmail;

                                                if (eventEntity != null)
                                                {
                                                    // ***************
                                                    // This needs to be fixed as part of dealing with replies from ical requests. The rel on a rel needs to be turned into something else.
                                                    // ***************
                                                    //IEntityRelationship<EventEmailAttendees, EmailContact> attendeeRelationshipInstance = FindAttendeeRelationshipInstance( eventEntity, message.From.Address.ToLowerInvariant( ) );

                                                    //if ( attendeeRelationshipInstance != null )
                                                    //{
                                                    //    Attendee attendee = FindICalAttendee( calendarEvent, message.From.Address.ToLowerInvariant( ) );

                                                    //    if ( attendee != null )
                                                    //    {
                                                    //        var eventEmailAttendees = attendeeRelationshipInstance.Instance.AsWritable<EventEmailAttendees>( );

                                                    //        switch ( attendee.ParticipationStatus )
                                                    //        {
                                                    //            case ParticipationStatus.Accepted:
                                                    //                eventEmailAttendees.AttendeeStatus_Enum = AttendeeStatusEnum_Enumeration.AttendeeStatusAccepted;
                                                    //                break;
                                                    //            case ParticipationStatus.Declined:
                                                    //                eventEmailAttendees.AttendeeStatus_Enum = AttendeeStatusEnum_Enumeration.AttendeeStatusDeclined;
                                                    //                break;
                                                    //            case ParticipationStatus.Delegated:
                                                    //                eventEmailAttendees.AttendeeStatus_Enum = AttendeeStatusEnum_Enumeration.AttendeeStatusDelegated;
                                                    //                break;
                                                    //            case ParticipationStatus.NeedsAction:
                                                    //                eventEmailAttendees.AttendeeStatus_Enum = AttendeeStatusEnum_Enumeration.AttendeeStatusNeedsAction;
                                                    //                break;
                                                    //            case ParticipationStatus.Tentative:
                                                    //                eventEmailAttendees.AttendeeStatus_Enum = AttendeeStatusEnum_Enumeration.AttendeeStatusTentative;
                                                    //                break;
                                                    //        }

                                                    //        eventEmailAttendees.Save( );
                                                    //    }
                                                    //}

                                                    //*************

                                                    receivedICalEmailMessage.CreatedEventEmail = eventEntity;

                                                    /////
                                                    // Save the message since the process inbox action will discard it.
                                                    /////
                                                    receivedICalEmailMessage.Save( );
                                                }
                                            }
                                        }
                                    }

                                    return(MailMessageFormatterResult.Reject);
                                }

                                /////
                                // Serialize the iCalendar to a string for storage.
                                /////
                                var serializer = new iCalendarSerializer( );

                                iCal = serializer.SerializeToString(calendar);

                                return(MailMessageFormatterResult.Ok);
                            }
                        }

                        break;
                    }
                }
            }
            catch (Exception exc)
            {
                EventLog.Application.WriteError("Failed to process email iCal attachment. " + exc);

                return(MailMessageFormatterResult.Error);
            }

            return(MailMessageFormatterResult.Skip);
        }