async public Task <string> RetreiveInfo(object e) { // Get more info for the given item. This will run on it's own thread // so that the main program can continue as usual (we won't hold anything up) NotificationInfo n = (NotificationInfo)e; var token = await RetreiveToken(); var service = new EWService(token, true); service.SetImpersonation(ConnectingIdType.SmtpAddress, n.Mailbox); service.Current.Url = n.Service.Url; service.Current.TraceFlags = TraceFlags.All; var ewsMoreInfoService = service.Current; string sEvent = ""; if (n.Event is ItemEvent) { sEvent = n.Mailbox + ": Item " + (n.Event as ItemEvent).EventType.ToString() + ": " + MoreItemInfo(n.Event as ItemEvent, ewsMoreInfoService); } else { sEvent = n.Mailbox + ": Folder " + (n.Event as FolderEvent).EventType.ToString() + ": " + MoreFolderInfo(n.Event as FolderEvent, ewsMoreInfoService); } return(ShowEvent(sEvent)); }
/// <summary> /// Poll localDB events and push service bus events to the Queue /// </summary> /// <param name="queueConnection"></param> /// <returns></returns> public async System.Threading.Tasks.Task SendQueueDatabaseChangesAsync(string queueConnection) { var sender = new MessageSender(queueConnection, SBQueueSyncDb); var token = await RetreiveToken(); var EwsService = new EWService(token); EwsService.SetImpersonation(ConnectingIdType.SmtpAddress, MailboxOwner); // Poll the rooms to store locally var roomlisting = EwsService.GetRoomListing(); using (var EwsDatabase = new EWSDbContext(EWSConstants.Config.Database)) { foreach (var roomlist in roomlisting) { foreach (var room in roomlist.Value) { EntityRoomListRoom databaseRoom = null; if (EwsDatabase.RoomListRoomEntities.Any(s => s.SmtpAddress == room.Address)) { databaseRoom = await EwsDatabase.RoomListRoomEntities.FirstOrDefaultAsync(f => f.SmtpAddress == room.Address); } else { databaseRoom = new EntityRoomListRoom() { SmtpAddress = room.Address, Identity = room.Address, RoomList = roomlist.Key }; EwsDatabase.RoomListRoomEntities.Add(databaseRoom); } } } var roomchanges = await EwsDatabase.SaveChangesAsync(); Trace.WriteLine($"Rooms {roomchanges} saved to database."); } var waitTimer = new TimeSpan(0, 5, 0); while (!_cancel.IsCancellationRequested) { var milliseconds = (int)waitTimer.TotalMilliseconds; // whatever you want to happen every 5 minutes Trace.WriteLine($"SendQueueDatabaseChangesAsync({MailboxOwner}) starting at {DateTime.UtcNow.ToShortTimeString()}"); using (var EwsDatabase = new EWSDbContext(EWSConstants.Config.Database)) { var i = 0; var bookings = EwsDatabase.AppointmentEntities.Include(ictx => ictx.Room) .Where(w => !w.ExistsInExchange || !w.SyncedWithExchange || (w.DeletedLocally && !w.SyncedWithExchange)); foreach (var booking in bookings) { Microsoft.Exchange.WebServices.Data.EventType eventType = Microsoft.Exchange.WebServices.Data.EventType.Deleted; if (!booking.ExistsInExchange) { eventType = Microsoft.Exchange.WebServices.Data.EventType.Created; } else if (!booking.SyncedWithExchange) { eventType = Microsoft.Exchange.WebServices.Data.EventType.Modified; } if (string.IsNullOrEmpty(booking.BookingReference)) { booking.BookingReference = $"Ref{booking.Id.ToString().PadLeft(6, '0')}"; } var ewsbooking = new EWS.Common.Models.UpdatedBooking() { DatabaseId = booking.Id, MailBoxOwnerEmail = booking.OrganizerSmtpAddress, SiteMailBox = booking.Room.SmtpAddress, Subject = booking.Subject, Location = booking.Location, StartUTC = booking.StartUTC, EndUTC = booking.EndUTC, ExchangeId = booking.BookingId, ExchangeChangeKey = booking.BookingChangeKey, BookingReference = booking.BookingReference, ExchangeEvent = eventType }; var message = new Message(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(ewsbooking))) { ContentType = "application/json", Label = SBMessageSyncDb, MessageId = i.ToString() }; await sender.SendAsync(message); Trace.WriteLine($"{++i}. Sent: Id = {message.MessageId} w/ Subject:{booking.Subject}"); } Trace.WriteLine($"Sent {i} messages"); } Trace.WriteLine($"Sleeping at {DateTime.UtcNow} for {milliseconds} milliseconds..."); System.Threading.Thread.Sleep(milliseconds); } }
/// <summary> /// Read Queue for O365 Sync Folder events and write it to the database [preferably on a separate thread] /// </summary> /// <param name="queueConnection"></param> /// <returns></returns> public async System.Threading.Tasks.Task ReceiveQueueO365SyncFoldersAsync(string queueConnection) { Trace.WriteLine($"ReceiveQueueO365SyncFoldersAsync() starting"); var token = await RetreiveToken(); var EwsService = new EWService(token); var receiver = new MessageReceiver(queueConnection, SBQueueSyncO365, ReceiveMode.ReceiveAndDelete); _cancel.Token.Register(() => receiver.CloseAsync()); var filterPropertyList = new List <PropertyDefinitionBase>() { AppointmentSchema.Location, ItemSchema.Subject, AppointmentSchema.Start, AppointmentSchema.End, AppointmentSchema.IsMeeting, AppointmentSchema.IsOnlineMeeting, AppointmentSchema.IsAllDayEvent, AppointmentSchema.IsRecurring, AppointmentSchema.IsCancelled, ItemSchema.IsUnmodified, AppointmentSchema.TimeZone, AppointmentSchema.ICalUid, ItemSchema.ParentFolderId, ItemSchema.ConversationId, AppointmentSchema.ICalRecurrenceId, EWSConstants.RefIdPropertyDef, EWSConstants.DatabaseIdPropertyDef }; // With the receiver set up, we then enter into a simple receive loop that terminates using (var EwsDatabase = new EWSDbContext(EWSConstants.Config.Database)) { // when the cancellation token if triggered. while (!_cancel.Token.IsCancellationRequested) { try { // ask for the next message "forever" or until the cancellation token is triggered var message = await receiver.ReceiveAsync(); if (message != null) { if (message.Label != null && message.ContentType != null && message.Label.Equals(SBMessageSyncO365, StringComparison.InvariantCultureIgnoreCase) && message.ContentType.Equals("application/json", StringComparison.InvariantCultureIgnoreCase)) { // service bus // #TODO: Read bus events from O365 and write to Database var booking = JsonConvert.DeserializeObject <EWS.Common.Models.ChangeBooking>(Encoding.UTF8.GetString(message.Body)); Trace.WriteLine($"Msg received: {booking.SiteMailBox} status: {booking.EventType.ToString("f")}"); var eventType = booking.EventType; var itemId = booking.ExchangeId; var changeKey = booking.ExchangeChangeKey; var appointmentMailbox = booking.SiteMailBox; try { Appointment meeting = null; var dbroom = EwsDatabase.RoomListRoomEntities.Include(idxt => idxt.Appointments).FirstOrDefault(f => f.SmtpAddress == appointmentMailbox); if (eventType == ChangeType.Delete) { var entity = dbroom.Appointments.FirstOrDefault(f => f.BookingId == itemId); entity.IsDeleted = true; entity.ModifiedDate = DateTime.UtcNow; entity.SyncedWithExchange = true; entity.ExistsInExchange = true; } else { var appointmentTime = EwsService.GetAppointment(ConnectingIdType.SmtpAddress, appointmentMailbox, itemId, filterPropertyList); if (!filterPropertyList.Any(fp => fp == AppointmentSchema.Recurrence)) { filterPropertyList.Add(AppointmentSchema.Recurrence); } var parentAppointment = EwsService.GetParentAppointment(appointmentTime, filterPropertyList); meeting = parentAppointment.Item; var mailboxId = parentAppointment.Organizer.Address; var refId = parentAppointment.ReferenceId; var meetingKey = parentAppointment.MeetingKey; // TODO: move this to the ServiceBus Processing if ((!string.IsNullOrEmpty(refId) || meetingKey.HasValue) && dbroom.Appointments.Any(f => f.BookingReference == refId || f.Id == meetingKey)) { var entity = dbroom.Appointments.FirstOrDefault(f => f.BookingReference == refId || f.Id == meetingKey); entity.EndUTC = meeting.End.ToUniversalTime(); entity.StartUTC = meeting.Start.ToUniversalTime(); entity.ExistsInExchange = true; entity.IsRecurringMeeting = meeting.IsRecurring; entity.Location = meeting.Location; entity.OrganizerSmtpAddress = mailboxId; entity.Subject = meeting.Subject; entity.RecurrencePattern = (meeting.Recurrence == null) ? string.Empty : meeting.Recurrence.ToString(); entity.BookingReference = refId; entity.BookingChangeKey = changeKey; entity.BookingId = itemId; entity.ModifiedDate = DateTime.UtcNow; entity.SyncedWithExchange = true; } else { var entity = new EntityRoomAppointment() { BookingReference = refId, BookingId = itemId, BookingChangeKey = changeKey, EndUTC = meeting.End.ToUniversalTime(), StartUTC = meeting.Start.ToUniversalTime(), ExistsInExchange = true, IsRecurringMeeting = meeting.IsRecurring, Location = meeting.Location, OrganizerSmtpAddress = mailboxId, Subject = meeting.Subject, RecurrencePattern = (meeting.Recurrence == null) ? string.Empty : meeting.Recurrence.ToString(), ModifiedDate = DateTime.UtcNow }; dbroom.Appointments.Add(entity); } } var appointmentsSaved = EwsDatabase.SaveChanges(); Trace.WriteLine($"Saved {appointmentsSaved} rows"); } catch (Exception dbex) { Trace.WriteLine($"Error occurred in Appointment creation or Database change {dbex}"); } finally { //await receiver.CompleteAsync(message.SystemProperties.LockToken); } } else { // purge / log it await receiver.DeadLetterAsync(message.SystemProperties.LockToken);//, "ProcessingError", "Don't know what to do with this message"); } } } catch (ServiceBusException e) { if (!e.IsTransient) { Trace.WriteLine(e.Message); throw; } } } } await receiver.CloseAsync(); }
/// <summary> /// Read Queue for Database Changes [preferably on a separate thread] and Store in Office 365 /// </summary> /// <param name="queueConnection"></param> /// <returns></returns> public async System.Threading.Tasks.Task ReceiveQueueDatabaseChangesAsync(string queueConnection) { var token = await RetreiveToken(); var EwsService = new EWService(token); var propertyIds = new List <PropertyDefinitionBase>() { ItemSchema.Subject, AppointmentSchema.Location, AppointmentSchema.Start, AppointmentSchema.End, EWSConstants.RefIdPropertyDef, EWSConstants.DatabaseIdPropertyDef }; var receiver = new MessageReceiver(queueConnection, SBQueueSyncDb, ReceiveMode.ReceiveAndDelete); _cancel.Token.Register(() => receiver.CloseAsync()); // when the cancellation token if triggered. while (!_cancel.Token.IsCancellationRequested) { // whatever you want to happen every 5 minutes Trace.WriteLine($"ReceiveQueueDatabaseChangesAsync({MailboxOwner}) starting at {DateTime.UtcNow.ToShortTimeString()}"); // With the receiver set up, we then enter into a simple receive loop that terminates using (var _context = new EWSDbContext(EWSConstants.Config.Database)) { try { // ask for the next message "forever" or until the cancellation token is triggered var message = await receiver.ReceiveAsync(); if (message != null) { if (message.Label != null && message.ContentType != null && message.Label.Equals(SBMessageSyncDb, StringComparison.InvariantCultureIgnoreCase) && message.ContentType.Equals("application/json", StringComparison.InvariantCultureIgnoreCase)) { // service bus // #TODO: Read bus events from database and write to O365 var booking = JsonConvert.DeserializeObject <EWS.Common.Models.UpdatedBooking>(Encoding.UTF8.GetString(message.Body)); Trace.WriteLine($"Msg received: {booking.SiteMailBox} - {booking.Subject}. Cancel status: {booking.ExchangeEvent.ToString("f")}"); var eventType = booking.CancelStatus; var eventStatus = booking.ExchangeEvent; var itemId = booking.ExchangeId; var changeKey = booking.ExchangeChangeKey; var appointmentMailbox = booking.SiteMailBox; try { Appointment meeting = null; if (!string.IsNullOrEmpty(itemId)) { var exchangeId = new ItemId(itemId); if (eventStatus == EventType.Deleted) { } else { if (string.IsNullOrEmpty(booking.BookingReference)) { booking.BookingReference = $"Ref{booking.DatabaseId.ToString().PadLeft(6, '0')}"; } EwsService.SetImpersonation(ConnectingIdType.SmtpAddress, booking.MailBoxOwnerEmail); var subAppointment = EwsService.GetAppointment(ConnectingIdType.SmtpAddress, booking.SiteMailBox, exchangeId, propertyIds); var parentAppt = EwsService.GetParentAppointment(subAppointment, propertyIds); meeting = parentAppt.Item; meeting.Subject = booking.Subject; meeting.Start = booking.StartUTC; meeting.End = booking.EndUTC; meeting.Location = booking.Location; //meeting.ReminderDueBy = DateTime.Now; meeting.SetExtendedProperty(EWSConstants.RefIdPropertyDef, booking.BookingReference); meeting.SetExtendedProperty(EWSConstants.DatabaseIdPropertyDef, booking.DatabaseId); meeting.Update(ConflictResolutionMode.AutoResolve, SendInvitationsOrCancellationsMode.SendOnlyToChanged); // Verify that the appointment was created by using the appointment's item ID. var item = Item.Bind(EwsService.Current, meeting.Id, new PropertySet(propertyIds)); Trace.WriteLine($"Appointment modified: {item.Subject} && ReserveRoomAsync({booking.Location}) completed"); if (item is Appointment) { Trace.WriteLine($"Item is Appointment"); } } } else { if (string.IsNullOrEmpty(booking.BookingReference)) { booking.BookingReference = $"Ref{booking.DatabaseId.ToString().PadLeft(6, '0')}"; } EwsService.SetImpersonation(ConnectingIdType.SmtpAddress, booking.MailBoxOwnerEmail); meeting = new Appointment(EwsService.Current); meeting.Resources.Add(booking.SiteMailBox); meeting.Subject = booking.Subject; meeting.Start = booking.StartUTC; meeting.End = booking.EndUTC; meeting.Location = booking.Location; //meeting.ReminderDueBy = DateTime.Now; meeting.SetExtendedProperty(EWSConstants.RefIdPropertyDef, booking.BookingReference); meeting.SetExtendedProperty(EWSConstants.DatabaseIdPropertyDef, booking.DatabaseId); meeting.Save(SendInvitationsMode.SendOnlyToAll); // Verify that the appointment was created by using the appointment's item ID. var item = Item.Bind(EwsService.Current, meeting.Id, new PropertySet(propertyIds)); Trace.WriteLine($"Appointment created: {item.Subject} && ReserveRoomAsync({booking.Location}) completed"); if (item is Appointment) { Trace.WriteLine($"Item is Appointment"); } } // this should exists as this particular message was sent by the database var dbAppointment = _context.AppointmentEntities.FirstOrDefault(a => a.Id == booking.DatabaseId); if (dbAppointment != null) { dbAppointment.ExistsInExchange = true; dbAppointment.SyncedWithExchange = true; dbAppointment.ModifiedDate = DateTime.UtcNow; if (meeting != null) { dbAppointment.BookingId = meeting.Id.UniqueId; dbAppointment.BookingChangeKey = meeting.Id.ChangeKey; } else { dbAppointment.IsDeleted = true; } if (string.IsNullOrEmpty(dbAppointment.BookingReference) || !dbAppointment.BookingReference.Equals(booking.BookingReference)) { dbAppointment.BookingReference = booking.BookingReference; } } var appointmentsSaved = _context.SaveChanges(); Trace.WriteLine($"Saved {appointmentsSaved} rows"); } catch (Exception dbex) { Trace.WriteLine($"Error occurred in Appointment creation or Database change {dbex}"); } finally { //await receiver.CompleteAsync(message.SystemProperties.LockToken); } } else { // purge / log it await receiver.DeadLetterAsync(message.SystemProperties.LockToken);//, "ProcessingError", "Don't know what to do with this message"); } } } catch (ServiceBusException e) { if (!e.IsTransient) { Trace.WriteLine(e.Message); throw; } } } } await receiver.CloseAsync(); }