/// <summary>
        /// Provides in-place (destructive) processing of the <see cref="Update"/>.
        /// </summary>
        /// <param name="update">The update instance.</param>
        /// <param name="file">
        /// A KmlFile containing the <c>Update</c> and the update targets.
        /// </param>
        /// <exception cref="ArgumentNullException">file is null.</exception>
        public static void Process(this Update update, KmlFile file)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file");
            }

            foreach (var child in update.Updates)
            {
                ChangeCollection change = child as ChangeCollection;
                if (change != null)
                {
                    ProcessChange(change, file);
                    continue;
                }

                CreateCollection create = child as CreateCollection;
                if (create != null)
                {
                    ProcessCreate(create, file);
                    continue;
                }

                DeleteCollection delete = child as DeleteCollection;
                if (delete != null)
                {
                    ProcessDelete(delete, file);
                }
            }
        }
        /// <summary>
        /// Sync folder hierarchy.
        /// </summary>
        /// <param name="exchangeService">Exchange service.</param>
        /// <returns></returns>
        public static async Task SyncFolderHierarchy(ExchangeService exchangeService)
        {
            ChangeCollection <MailFolderChange> folderChange = null;
            string syncState = null;

            do
            {
                folderChange = await exchangeService.SyncFolderHierarchy(null, syncState);

                syncState = folderChange.SyncState;

                foreach (MailFolderChange mailFolderChange in folderChange.Items)
                {
                    Assert.AreEqual(
                        ChangeType.Created,
                        mailFolderChange.ChangeType);
                }
            } while (folderChange.MoreAvailable);

            SearchFilter          inbox  = new SearchFilter.IsEqualTo(MailFolderObjectSchema.DisplayName, "Inbox");
            FindMailFolderResults result =
                await exchangeService.FindFolders(WellKnownFolderName.MsgFolderRoot, inbox, new MailFolderView());

            MailFolder mf = new MailFolder(exchangeService);

            mf.DisplayName = "kakakoko";
            await mf.SaveAsync(result.MailFolders[0]);

            do
            {
                folderChange = await exchangeService.SyncFolderHierarchy(null, syncState);

                syncState = folderChange.SyncState;

                Assert.AreEqual(
                    1,
                    folderChange.TotalCount);

                Assert.AreEqual(
                    ChangeType.Created,
                    folderChange.Items[0].ChangeType);
            } while (folderChange.MoreAvailable);

            await mf.DeleteAsync();

            do
            {
                folderChange = await exchangeService.SyncFolderHierarchy(null, syncState);

                syncState = folderChange.SyncState;

                Assert.AreEqual(
                    1,
                    folderChange.TotalCount);

                Assert.AreEqual(
                    ChangeType.Deleted,
                    folderChange.Items[0].ChangeType);
            } while (folderChange.MoreAvailable);
        }
Пример #3
0
 private List <Change> GetUniqueChanges(ChangeCollection changes)
 {
     return(changes
            .GroupBy(i => ((ChangeItem)i).ItemId,
                     (key, g) =>
                     g.OrderByDescending(e => e.Time).First()).OrderByDescending(c => c.Time)
            .ToList());
 }
        // Get the folder changes in the root folder.
        static void ProcessFolders(ChangeCollection <FolderChange> fcc)
        {
            // Create a variable for all the new folders in the FolderChange ChangeCollection.
            var newFolders = from fc in fcc
                             where fc.ChangeType == ChangeType.Create
                             select fc.FolderId;

            // Get the properties for each folder, so that they can be created on the client.
            foreach (var item in newFolders)
            {
                Folder newFolder = new Folder(service);
                newFolder = Folder.Bind(service, item);
                newFolder.Load();
                Console.WriteLine("New folder, all properties loaded");
                Console.WriteLine("Display name: {0}", newFolder.DisplayName);
                Console.WriteLine("Parent Folder Id: {0}", newFolder.ParentFolderId);
                Console.WriteLine("--------");

                // TODO: Create the folder on the client by using the properties
                // returned from Load.

                // Call SyncContents and SetStreamingNotifications on the new child folders.
                string ccSyncState = SyncContents(service, null, newFolder.Id);
                SetStreamingNotifications(service, ccSyncState, newFolder.Id);
            }

            // Create a variable for all the deleted folders in the FolderChange ChangeCollection.
            var deleteFolders = from fc in fcc
                                where fc.ChangeType == ChangeType.Delete
                                select fc.FolderId;

            // Display the FolderIds to be deleted on the client.
            foreach (var item in deleteFolders)
            {
                Console.WriteLine("Delete FolderId: {0}", item);
                Console.WriteLine("--------");
                // TODO: Delete messages on the client by using the FolderIds in deleteFolders.
            }

            // Create a variable for all the updated folders in the FolderChange ChangeCollection.
            var updateFolders = from fc in fcc
                                where fc.ChangeType == ChangeType.Update
                                select fc.Folder;

            // Display the display name for each updated folder.
            foreach (var item in updateFolders)
            {
                Folder folder = Folder.Bind(service, item.Id);
                folder.Load();
                Console.WriteLine("Updated folder, all properties loaded.");
                Console.WriteLine("Parent Folder Id: {0}", item.ParentFolderId);
                Console.WriteLine("Display name: {0}", item.DisplayName);
                Console.WriteLine("--------");
                // TODO: Compare the properties retrieved from Load to the
                // properties on the client and update the client properties accordingly.
            }
        }
Пример #5
0
        private void RenameCollectionButton_Click(object sender, EventArgs e)
        {
            Collection       collection = collections[CollectionsListBox.SelectedIndex];
            ChangeCollection form       = new ChangeCollection(collection);

            form.ShowDialog();
            InterplayForServer.UpdateCollection(collection);
            FindCollections();
        }
Пример #6
0
        private void AddCollectionButton_Click(object sender, EventArgs e)
        {
            Collection       collection = new Collection();
            ChangeCollection form       = new ChangeCollection(collection);

            form.ShowDialog();
            InterplayForServer.CreateCollection(collection.Name);
            FindCollections();
        }
Пример #7
0
        static void Main(string[] args)
        {
            ClientContext ctx = ContextHelper.GetSPContext("https://folkuniversitetetsp2016.sharepoint.com/").Result;


            List list = ctx.Web.GetListByTitle("CustomList");

            string      currentChangeTokenstr = list.GetPropertyBagValueString("customlistchangetoken", null);
            ChangeToken currentChangeToken    = null;

            if (currentChangeTokenstr != null)
            {
                currentChangeToken = new ChangeToken();

                currentChangeToken.StringValue = currentChangeTokenstr;
            }

            ChangeQuery q = new ChangeQuery(false, false);

            q.Update           = true;
            q.Add              = true;
            q.Item             = true;
            q.DeleteObject     = true;
            q.ChangeTokenStart = currentChangeToken;
            q.ChangeTokenEnd   = list.CurrentChangeToken;

            ChangeCollection changes = list.GetChanges(q);

            ctx.Load(changes);
            ctx.ExecuteQueryRetry();

            foreach (var change in changes)
            {
                if (change.ChangeType == ChangeType.Add)
                {
                    ChangeItem itemChange = change as ChangeItem;
                    Console.WriteLine("Item was added id = " + itemChange.ItemId);
                }
                if (change.ChangeType == ChangeType.DeleteObject)
                {
                    ChangeItem itemChange = change as ChangeItem;
                    Console.WriteLine("Item was deleted id = " + itemChange.ItemId);
                }
                if (change.ChangeType == ChangeType.Update)
                {
                    ChangeItem itemChange = change as ChangeItem;
                    Console.WriteLine("Item was updated id = " + itemChange.ItemId);
                }
            }
            list.SetPropertyBagValue("customlistchangetoken", q.ChangeTokenEnd.StringValue);



            Console.WriteLine("done");
            Console.ReadLine();
        }
Пример #8
0
        /// <summary>
        /// Creates a <see cref="System.Collections.Generic.List&lt;T&gt;"/> from an <see cref="ChangeCollection"/>.
        /// </summary>
        /// <typeparam name="T">The type of the elements of source.</typeparam>
        /// <param name="collection">Extended collection of changes.</param>
        /// <returns>A <see cref="System.Collections.Generic.List&lt;T&gt;"/> that contains elements from the input sequence</returns>
        public static List <T> ToChangeList <T>(this ChangeCollection collection)
        {
            List <T> changes = new List <T>();

            foreach (Change change in collection)
            {
                changes.Add((T)(object)change);
            }

            return(changes);
        }
Пример #9
0
        public void TestChangeCoordinates()
        {
            // Create the target
            var point = new Point
            {
                Coordinate = new Vector(38.38, -122.122)
            };

            var placemark = new Placemark
            {
                Id       = "placemark123",
                Geometry = point,
                Name     = "placemark name"
            };

            var file = KmlFile.Create(placemark, false);

            // Now create the Update
            const double latitude  = -38.38;
            const double longitude = 122.122;

            point = new Point
            {
                Coordinate = new Vector(latitude, longitude)
            };

            placemark = new Placemark
            {
                Geometry = point,
                TargetId = "placemark123"
            };

            var change = new ChangeCollection {
                placemark
            };

            var update = new Update();

            update.AddUpdate(change);

            // Now test the update worked
            update.Process(file);

            placemark = file.Root as Placemark;
            Assert.That(placemark, Is.Not.Null);
            Assert.That(placemark.Id, Is.EqualTo("placemark123"));
            Assert.That(placemark.Name, Is.EqualTo("placemark name"));

            point = placemark.Geometry as Point;
            Assert.That(point, Is.Not.Null);
            Assert.That(point.Coordinate.Latitude, Is.EqualTo(latitude));
            Assert.That(point.Coordinate.Longitude, Is.EqualTo(longitude));
        }
Пример #10
0
        private void SyncContacts(ExchangeService service)
        {
            // Initialize the flag that will indicate when there are no more changes.
            bool isEndOfChanges = false;

            // Call SyncFolderItems repeatedly until no more changes are available.
            // sSyncState represents the sync state value that was returned in the prior synchronization response.
            do
            {
                ChangeCollection <ItemChange> icc = service.SyncFolderItems(new FolderId(WellKnownFolderName.Contacts), PropertySet.FirstClassProperties, null, 512, SyncFolderItemsScope.NormalItems, sSyncState);
                if (icc.Count == 0)
                {
                    Console.WriteLine("There are no item changes to synchronize.");
                }
                else
                {
                    foreach (ItemChange ic in icc)
                    {
                        if (ic.ChangeType == ChangeType.Create)
                        {
                            Contact contacts = Contact.Bind(service, ic.ItemId);
                            contact.AddContact(contacts);
                            contact.PushUpdatesToAuditTable("Added the record", contacts);
                        }
                        else if (ic.ChangeType == ChangeType.Update)
                        {
                            Contact contacts = Contact.Bind(service, ic.ItemId);
                            contact.UpdateContact(contacts);
                            contact.PushUpdatesToAuditTable("Updated the record", contacts);
                        }
                        else if (ic.ChangeType == ChangeType.Delete)
                        {
                            contact.PushUpdatesToAuditTable("Deleted the record", ic.ItemId);
                            contact.DeleteContact(ic.ItemId);
                        }
                        else if (ic.ChangeType == ChangeType.Delete)
                        {
                            //TODO: Update the item's read flag on the client.
                        }
                    }
                }

                // Save the sync state for use in future SyncFolderHierarchy calls.
                sSyncState = icc.SyncState;
                WriteSyncState();
                if (!icc.MoreChangesAvailable)
                {
                    isEndOfChanges = false;
                }
            } while (isEndOfChanges);
        }
        // Synchronize the folders in the specified root folder.
        static string SyncFolders(ExchangeService service, string FolderSyncState, FolderId rootSyncFolder)
        {
            Console.WriteLine("Starting folder sync on the following folder");
            Console.WriteLine("FolderId: {0}", rootSyncFolder);
            Console.WriteLine("--------");

            // Get a list of all folders under the rootSyncFolder by calling SyncFolderHierarchy.
            // The folderId parameter is the root folder to synchronize.
            // The propertySet parameter is set to IdOnly to reduce calls to the Exchange database,
            // because any additional properties result in another call to the Exchange database.
            // The syncState parameter is set to the folder sync state. When this method is called
            // on a new or empty mailbox, the value is null. If the method has been called before,
            // the FolderSyncState value contains the value previously returned by the server.
            FolderChangeCollection = service.SyncFolderHierarchy(rootSyncFolder, PropertySet.IdOnly, FolderSyncState);

            // Save the sync state for use in future SyncFolderItems requests.
            // The sync state is used by the server to determine what changes to report
            // to the client.
            FolderSyncState = FolderChangeCollection.SyncState;

            // If the count of changes is zero, there are no changes to synchronize.
            if (FolderChangeCollection.Count == 0)
            {
                Console.WriteLine("There are no new folders to synchronize.");
                Console.WriteLine("--------");
            }

            // Otherwise, write all the changes included in the response
            // to the console.
            // For the initial synchronization, all the changes will be of type
            // ChangeType.Create.
            else
            {
                foreach (FolderChange fc in FolderChangeCollection)
                {
                    Console.WriteLine("FolderChange.ChangeType: " + fc.ChangeType.ToString());
                    Console.WriteLine("FolderChange.FolderId: " + fc.FolderId);
                    Console.WriteLine("--------");
                }
            }

            // Send the FolderChangeCollection to ProcessItems to actually retrieve the messages and changes.
            ProcessFolders(FolderChangeCollection);

            Console.WriteLine("Finished folder sync on the following folder");
            Console.WriteLine("FolderId: {0}", rootSyncFolder);
            Console.WriteLine("--------");

            return(FolderSyncState);
        }
Пример #12
0
 private static void ProcessChange(ChangeCollection change, KmlFile file)
 {
     foreach (var source in change)
     {
         if (source.TargetId != null)
         {
             KmlObject target = file.FindObject(source.TargetId);
             if (target != null)
             {
                 target.Merge(source);
                 target.TargetId = null; // Merge copied the TargetId from the source, but target shouldn't have it set
             }
         }
     }
 }
Пример #13
0
 private static void ProcessChange(ChangeCollection change, KmlFile file)
 {
     foreach (KmlObject source in change)
     {
         if (source.TargetId != null)
         {
             KmlObject target = file.FindObject(source.TargetId);
             if (target != null)
             {
                 target.Merge(source);
                 target.TargetId = null; // Merge copied the TargetId from the source, but target shouldn't have it set
             }
         }
     }
 }
Пример #14
0
        public static void Run([QueueTrigger("achangeismade", Connection = "AzureWebJobsStorage")] string myQueueItem, TraceWriter log)
        {
            log.Info($"C# Queue trigger function processed: {myQueueItem}");
            NotificationModel notification = JsonConvert.DeserializeObject <NotificationModel>(myQueueItem);

            ClientContext ctx = ContextHelper.GetContext("https://folkis2018.sharepoint.com/sites/David");


            List list = ctx.Web.GetListByTitle("SampleList");
            var  lastCheckedString = list.GetPropertyBagValueString("lastchecked", null);

            ChangeQuery query = new ChangeQuery(false, false);

            query.Item   = true;
            query.Add    = true;
            query.Update = true;
            //query.DeleteObject = true; dont care
            if (lastCheckedString != null)
            {
                ChangeToken token = new ChangeToken();
                token.StringValue      = lastCheckedString;
                query.ChangeTokenStart = token;
            }
            query.ChangeTokenEnd = list.CurrentChangeToken;

            ChangeCollection changes = list.GetChanges(query);

            ctx.Load(changes);
            ctx.ExecuteQuery();

            foreach (ChangeItem change in changes)
            {
                log.Info(change.ItemId.ToString());
                log.Info(change.ChangeType.ToString());

                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(Environment.GetEnvironmentVariable("AzureWebJobsStorage"));
                // Get queue... create if does not exist.
                CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
                CloudQueue       queue       = queueClient.GetQueueReference("processitem");
                queue.CreateIfNotExists();

                queue.AddMessage(new CloudQueueMessage(change.ItemId.ToString()));
            }

            list.SetPropertyBagValue("lastchecked", list.CurrentChangeToken.StringValue);
        }
Пример #15
0
        private static void DisplayChanges(ChangeCollection coll, ChangeToken ct)
        {
            if (coll.Count == 0)
            {
                Console.WriteLine(string.Format("No changes to {0} since {1} UTC.", listName, GetDateStringFromChangeToken(ct)));
                return;
            }

            Console.ForegroundColor = ConsoleColor.Green;
            foreach (ChangeItem itm in coll)
            {
                Console.WriteLine();
                Console.WriteLine(string.Format("List {0} had a Change of type \"{1}\" on the item with Id {2}.", listName, itm.ChangeType.ToString(), itm.ItemId));
            }
            Console.WriteLine();
            Console.ResetColor();
        }
Пример #16
0
        public void CountEmailsNumber()
        {
            string syncState = "";
            ChangeCollection <ItemChange> itemChanges = null;

            int count = 0;

            do
            {
                itemChanges = _service.SyncFolderItems(new FolderId(WellKnownFolderName.Inbox), PropertySet.IdOnly, null, 500, SyncFolderItemsScope.NormalItems, syncState);
                syncState   = itemChanges.SyncState;
                count      += itemChanges.Count;
                Console.WriteLine("itemchanges count : " + count);
                //Console.WriteLine("syncState: " + syncState);
            } while (itemChanges.MoreChangesAvailable);
            Console.WriteLine($"total mail in Inbox number: {count}");
        }
        public static ChangeCollection GetAllChanges(List ListWebHook, ChangeQuery ListChangeQuery,
                                                     ClientContext SPClientContext, TraceWriter log)
        {
            ChangeCollection chcReturn = null;

            try
            {
                chcReturn = ListWebHook.GetChanges(ListChangeQuery);
                SPClientContext.Load(chcReturn);
                SPClientContext.ExecuteQuery();
            }
            catch (Exception ex)
            {
                log.Info($"Error in GetAllChanges: " + ex.ToString());
            }

            return(chcReturn);
        }
Пример #18
0
        public async Task <bool> ReceiveEmail()
        {
            string      syncState = "";
            PropertySet ps        = new PropertySet(ItemSchema.Subject, ItemSchema.Body, ItemSchema.Attachments, ItemSchema.ConversationId, ItemSchema.Id,
                                                    EmailMessageSchema.Sender, EmailMessageSchema.CcRecipients, EmailMessageSchema.ToRecipients);
            ChangeCollection <ItemChange> itemChanges = null;
            int count = 0;
            int index = 512;

            do
            {
                itemChanges = await _service.SyncFolderItems(new FolderId(WellKnownFolderName.Inbox), PropertySet.IdOnly, null, index, SyncFolderItemsScope.NormalItems, syncState);

                syncState = itemChanges.SyncState;
                count    += itemChanges.Count;
                Console.WriteLine("itemchanges count : " + count);
                //Console.WriteLine("syncState: " + syncState);

                foreach (ItemChange itemChange in itemChanges)
                {
                    try
                    {
                        if (itemChange.ChangeType == ChangeType.Create)
                        {
                            EmailMessage emailMessage = await EmailMessage.Bind(_service, itemChange.ItemId, ps);

                            Console.WriteLine("to: " + emailMessage.ToRecipients);
                            Console.WriteLine("create time: " + emailMessage.DateTimeCreated + ": " + emailMessage.Subject + ", from: " + emailMessage.From.Address);
                            //Console.WriteLine(emailMessage.Body);
                            //Console.WriteLine(count + ": " + itemChange.ItemId.UniqueId);
                        }
                        else
                        {
                            Console.WriteLine("type:" + itemChange.ChangeType.ToString());
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.Write(ex.Message);
                    }
                }
            }while (itemChanges.MoreChangesAvailable && count < index);
            return(true);
        }
Пример #19
0
        private static void SyncMailboxes(ExchangeService service)
        {
            // Retrieve a collection of changes from the server for the Inbox, including the first-class properties. When the synch state parameter is null,
            // changes for all subfolders under the specified folder will be retrieved.
            ChangeCollection <FolderChange> folderChangeCollection = service.SyncFolderHierarchy(new FolderId(WellKnownFolderName.Inbox), PropertySet.FirstClassProperties, null);

            // Display changes, if any. Note that instead of displaying the changes,
            // you can create, update, or delete folders based on the changes retrieved from the server.
            if (folderChangeCollection.Count != 0)
            {
                foreach (FolderChange fc in folderChangeCollection)
                {
                    Console.WriteLine("ChangeType: " + fc.ChangeType.ToString());
                    Console.WriteLine("DisplayName: " + fc.Folder.DisplayName);
                    Console.WriteLine("ChildFolderCount: " + fc.Folder.ChildFolderCount);
                    Console.WriteLine("===========");
                }
            }
        }
Пример #20
0
        public void TestChangeCoordinates()
        {
            // Create the target
            var point = new Point();
            point.Coordinate = new Vector(38.38, -122.122);

            var placemark = new Placemark();
            placemark.Id = "placemark123";
            placemark.Geometry = point;
            placemark.Name = "placemark name";

            var file = KmlFile.Create(placemark, false);

            // Now create the Update
            const double latitude = -38.38;
            const double longitude = 122.122;

            point = new Point();
            point.Coordinate = new Vector(latitude, longitude);

            placemark = new Placemark();
            placemark.Geometry = point;
            placemark.TargetId = "placemark123";

            var change = new ChangeCollection();
            change.Add(placemark);

            var update = new Update();
            update.AddUpdate(change);

            // Now test the update worked
            update.Process(file);

            placemark = file.Root as Placemark;
            Assert.That(placemark, Is.Not.Null);
            Assert.That(placemark.Id, Is.EqualTo("placemark123"));
            Assert.That(placemark.Name, Is.EqualTo("placemark name"));

            point = placemark.Geometry as Point;
            Assert.That(point, Is.Not.Null);
            Assert.That(point.Coordinate.Latitude, Is.EqualTo(latitude));
            Assert.That(point.Coordinate.Longitude, Is.EqualTo(longitude));
        }
Пример #21
0
        public void ReceiveEmail()
        {
            string syncState = "";
            ChangeCollection <ItemChange> itemChanges = null;
            //PropertySet properties = new PropertySet();
            //properties.();
            int count = 0;

            do
            {
                itemChanges = _service.SyncFolderItems(new FolderId(WellKnownFolderName.Inbox), PropertySet.IdOnly, null, 50, SyncFolderItemsScope.NormalItems, syncState);
                syncState   = itemChanges.SyncState;
                count      += itemChanges.Count;
                Console.WriteLine("itemchanges count : " + count);
                //Console.WriteLine("syncState: " + syncState);

                foreach (ItemChange itemChange in itemChanges)
                {
                    try
                    {
                        if (itemChange.ChangeType == ChangeType.Create)
                        {
                            EmailMessage emailMessage = EmailMessage.Bind(_service, itemChange.ItemId);
                            Console.WriteLine("create time: " + emailMessage.DateTimeCreated + ": " + emailMessage.Subject + ", from: " + emailMessage.From.Address);
                            Console.WriteLine($"emailMessage.Id.UniqueId: {emailMessage.Id.UniqueId}");
                            //Console.WriteLine($"itemChange.Item.Id.UniqueId: { itemChange.Item.Id.UniqueId}");
                            Console.WriteLine(emailMessage.Id.UniqueId == itemChange.Item.Id.UniqueId);
                            //Console.WriteLine(emailMessage.Body);
                            //Console.WriteLine(count + ": " + itemChange.ItemId.UniqueId);
                        }
                        else
                        {
                            Console.WriteLine("type:" + itemChange.ChangeType.ToString());
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.Write(ex.Message);
                    }
                }
            }while (itemChanges.MoreChangesAvailable && count < 50);
        }
        static void GetChanges(ClientContext SPClientContext, string ListId, TraceWriter log)
        {
            // Get the List where the WebHook is working
            List myListWebHook = WHHelpRoutines.GetListWebHook(SPClientContext, log);

            // Get the Change Query
            ChangeQuery myChangeQuery = WHHelpRoutines.GetChangeQueryNew(ListId, log); // Only new items and for the last one minute

            // Get all the Changes
            ChangeCollection allChanges = WHHelpRoutines.GetAllChanges(myListWebHook, myChangeQuery, SPClientContext, log);

            foreach (Change oneChange in allChanges)
            {
                if (oneChange is ChangeItem)
                {
                    // Get what is changed
                    ListItem itemChanged = WHHelpRoutines.GetItemChanged(myListWebHook, oneChange, SPClientContext, log);
                    log.Info($"itemChangedID - " + itemChanged.Id.ToString());

                    // Do something with the Item Changed
                    DoSomething(SPClientContext, itemChanged, log);
                }
            }
        }
Пример #23
0
        public static void Run([QueueTrigger("eventhappened", Connection = "AzureWebJobsStorage")] string myQueueItem, TraceWriter log)
        {
            log.Info($"C# Queue trigger function processed: {myQueueItem}");
            ConfigureBindingRedirects();

            var notification = JsonConvert.DeserializeObject <NotificationModel>(myQueueItem);


            ClientContext ctx = Common.Helpers.ContextHelper.GetSPContext("https://folkuniversitetetsp2016.sharepoint.com" + notification.SiteUrl).Result;

            // notification.Resource is our list id
            List list = ctx.Web.Lists.GetById(new Guid(notification.Resource));

            string      currentChangeTokenstr = list.GetPropertyBagValueString("customlistchangetoken", null);
            ChangeToken currentChangeToken    = null;

            if (currentChangeTokenstr != null)
            {
                currentChangeToken = new ChangeToken();

                currentChangeToken.StringValue = currentChangeTokenstr;
            }

            ctx.Load(list, l => l.CurrentChangeToken);
            ctx.ExecuteQuery();

            ChangeQuery q = new ChangeQuery(false, false);

            q.Update = true;
            q.Add    = true;
            q.Item   = true;

            q.DeleteObject     = true;
            q.ChangeTokenStart = currentChangeToken;
            q.ChangeTokenEnd   = list.CurrentChangeToken;

            ChangeCollection changes = list.GetChanges(q);

            ctx.Load(changes);
            ctx.ExecuteQueryRetry();

            foreach (var change in changes)
            {
                if (change.ChangeType == ChangeType.Add)
                {
                    ChangeItem itemChange = change as ChangeItem;
                    log.Info("Item was added id = " + itemChange.ItemId);
                }
                if (change.ChangeType == ChangeType.DeleteObject)
                {
                    ChangeItem itemChange = change as ChangeItem;
                    log.Info("Item was deleted id = " + itemChange.ItemId);
                }
                if (change.ChangeType == ChangeType.Update)
                {
                    ChangeItem itemChange = change as ChangeItem;
                    log.Info("Item was updated id = " + itemChange.ItemId);
                }
            }
            list.SetPropertyBagValue("customlistchangetoken", q.ChangeTokenEnd.StringValue);
        }
Пример #24
0
 public ChangeCollectionAdapter(ChangeCollection changeCollection)
 {
     _changeCollection = changeCollection;
 }
Пример #25
0
        public static void Run([QueueTrigger("eventhappened", Connection = "AzureWebJobsStorage")] string myQueueItem, TraceWriter log)
        {
            log.Info($"C# Queue trigger function processed: {myQueueItem}");
            ConfigureBindingRedirects();

            var notification = JsonConvert.DeserializeObject <Common.Models.NotificationModel>(myQueueItem);


            ClientContext ctx = Common.Helpers.ContextHelper.GetSPContext("https://folkuniversitetetsp2016.sharepoint.com" + notification.SiteUrl).Result;

            // notification.Resource is our list id
            List list = ctx.Web.Lists.GetById(new Guid(notification.Resource));

            string      currentChangeTokenstr = list.GetPropertyBagValueString("customlistchangetoken", null);
            ChangeToken currentChangeToken    = null;

            if (currentChangeTokenstr != null)
            {
                currentChangeToken = new ChangeToken();

                currentChangeToken.StringValue = currentChangeTokenstr;
            }

            ctx.Load(list, l => l.CurrentChangeToken);
            ctx.ExecuteQuery();

            ChangeQuery q = new ChangeQuery(false, false);

            q.Update = true;
            q.Add    = true;
            q.Item   = true;

            q.DeleteObject     = true;
            q.ChangeTokenStart = currentChangeToken;
            q.ChangeTokenEnd   = list.CurrentChangeToken;

            ChangeCollection changes = list.GetChanges(q);

            ctx.Load(changes);
            ctx.ExecuteQueryRetry();

            //create queue if not exists
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["AzureWebJobsStorage"]);
            // Get queue... create if does not exist.
            CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
            CloudQueue       queue       = queueClient.GetQueueReference("changehappened");

            queue.CreateIfNotExists();

            foreach (var change in changes)
            {
                if (change.ChangeType == ChangeType.Add)
                {
                    ChangeItem itemChange = change as ChangeItem;
                    ChangeInfo changeInfo = new ChangeInfo()
                    {
                        SiteUrl = notification.SiteUrl, ListId = notification.Resource, ItemId = itemChange.ItemId
                    };
                    queue.AddMessage(new CloudQueueMessage(JsonConvert.SerializeObject(changeInfo)));
                    log.Info("Item was added id = " + itemChange.ItemId);
                }
                if (change.ChangeType == ChangeType.DeleteObject)
                {
                    ChangeItem itemChange = change as ChangeItem;
                    ChangeInfo changeInfo = new ChangeInfo()
                    {
                        SiteUrl = notification.SiteUrl, ListId = notification.Resource, ItemId = itemChange.ItemId
                    };
                    queue.AddMessage(new CloudQueueMessage(JsonConvert.SerializeObject(changeInfo)));
                    log.Info("Item was deleted id = " + itemChange.ItemId);
                }
                if (change.ChangeType == ChangeType.Update)
                {
                    ChangeItem itemChange = change as ChangeItem;
                    ChangeInfo changeInfo = new ChangeInfo()
                    {
                        SiteUrl = notification.SiteUrl, ListId = notification.Resource, ItemId = itemChange.ItemId
                    };
                    queue.AddMessage(new CloudQueueMessage(JsonConvert.SerializeObject(changeInfo)));
                    log.Info("Item was updated id = " + itemChange.ItemId);
                }
            }
            list.SetPropertyBagValue("customlistchangetoken", q.ChangeTokenEnd.StringValue);
        }
Пример #26
0
        public void ProcessChanges(string webID, string listID, string siteUrl)
        {
            ClientContext cc = null;

            try
            {
                #region Setup SharePoint Online ClientContext
                //DO NOT USE THIS IN PRODUCTION
                //Try to implement proper authentication based on Azure AD app instead!!!
                string url        = String.Format("https://{0}{1}", TenantURL, siteUrl);
                string initString = "YOUR PASSWORD";
                // Instantiate the secure string.
                SecureString testString = new SecureString();
                // Use the AppendChar method to add each char value to the secure string.
                foreach (char ch in initString)
                {
                    testString.AppendChar(ch);
                }

                cc = new ClientContext(url);
                cc.AuthenticationMode = ClientAuthenticationMode.Default;
                cc.Credentials        = new SharePointOnlineCredentials("YOUR USER", testString);
                #endregion

                #region Grab the wikipage PublishingPageContent for the page the web hook was triggered
                Web web = cc.Site.OpenWebById(new Guid(webID));
                cc.Load(web);
                List ls = web.Lists.GetById(new Guid(listID));
                cc.Load(ls);
                ChangeQuery query = new ChangeQuery(false, false);
                query.Item   = true;
                query.Update = true;
                ChangeCollection changes = ls.GetChanges(query);
                cc.Load(changes);
                cc.ExecuteQuery();

                Console.WriteLine("Starting to process changes for List {0} in Web {1} under site {2}", ls.Title, web.Title, siteUrl);

                Dictionary <String, String> qna = new Dictionary <string, string>();

                foreach (Change change in changes)
                {
                    if (change is Microsoft.SharePoint.Client.ChangeItem)
                    {
                        ChangeItem ci         = change as ChangeItem;
                        var        changeType = ci.ChangeType.ToString();
                        var        itemId     = ci.ItemId.ToString();
                        Console.WriteLine("Going to process changes for {0}: {1}", itemId, changeType);
                        Dictionary <string, string> res = this.GetWikiPageContententForKB(ci.ItemId, new Guid(listID), siteUrl);
                        foreach (string key in res.Keys)
                        {
                            if (!qna.ContainsKey(key))
                            {
                                qna.Add(key, res[key]);
                            }
                        }
                    }
                }

                KnowledgeBaseManager kb = new KnowledgeBaseManager("https://westus.api.cognitive.microsoft.com/qnamaker/v2.0/knowledgebases/", "CLIENT SECRETE", "KNOWLEDGEBASE ID");
                kb.AddQnAToKB(qna);
                kb.PublishKB();

                #endregion
            }
            catch (Exception ex)
            {
                // Log error
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                if (cc != null)
                {
                    cc.Dispose();
                }
            }
        }
Пример #27
0
        private async Task ChecksConnection()
        {
            var current = Connectivity.NetworkAccess;

            if (current == NetworkAccess.Internet)
            {
                Title             = "Saan muudatused...";
                activityIndicator = new ActivityIndicator
                {
                    IsRunning = true, Margin = 175, Color = Color.FromHex("#A22538")
                };
                if (ChangesListView == null)
                {
                    Content = activityIndicator;
                }
                await Task.Run(() => { LoadChanges(ChangeCollection.GetChangeList()); });

                if (ChangesListView == null)
                {
                    activityIndicator.IsRunning = false;
                    activityIndicator.IsVisible = false;
                    InitializeComponent();
                    string group = Preferences.Get("group", "none");
                    if (group != "none")
                    {
                        ChangesPageSearchBar.Placeholder = group;
                    }
                }
                else
                {
                    Title = "Tunniplaani muudatused";
                    string group = Preferences.Get("group", "none");
                    if (group != "none")
                    {
                        ChangesPageSearchBar.Placeholder = group;
                        Content = ChangesListView;
                    }
                }
                ChangesListView.IsRefreshing        = false;
                ChangesListView.RefreshControlColor = Color.FromHex("#A22538");
            }
            else
            {
                Title             = "Saan muudatused...";
                activityIndicator = new ActivityIndicator
                {
                    IsRunning = true, Margin = 175, Color = Color.FromHex("#A22538")
                };
                if (ChangesListView == null)
                {
                    Content = activityIndicator;
                }

                await GetChangesFromDatabase();

                if (ChangesListView == null)
                {
                    activityIndicator.IsRunning = false;
                    activityIndicator.IsEnabled = false;
                    InitializeComponent();
                    ChangesListView.IsRefreshing = false;
                    string group = Preferences.Get("group", "none");
                    if (group != "none")
                    {
                        ChangesPageSearchBar.Placeholder = group;
                    }
                }
                else
                {
                    ChangesListView.IsRefreshing = false;
                    Content = ChangesListView;
                }

                DependencyService.Get <IMessage>().ShortAlert("Teil puudub ühendus.");
            }
        }
        // Get the items and changes in the root folder.
        static void ProcessItems(ChangeCollection <ItemChange> icc)
        {
            // Create a variable for all the new items in the ItemChangeCollection.
            var newItems = from ic in icc
                           where ic.ChangeType == ChangeType.Create
                           select ic.Item;

            // Get the properties for each item, so that they can be created on the client.
            foreach (var item in newItems)
            {
                service.LoadPropertiesForItems(newItems, PropertySet.FirstClassProperties);
                Console.WriteLine("New item, all properties loaded");
                Console.WriteLine("Subject: {0}", item.Subject);
                Console.WriteLine("ParentFolderId: {0}", item.ParentFolderId);
                Console.WriteLine("DateTimeCreated: {0}", item.DateTimeCreated);
                Console.WriteLine("--------");
                // TODO: Create the messages on the client by using the properties
                // returned from LoadPropertiesForItems.
            }

            // Create a variable for all the deleted items in the ItemChangeCollection.
            var deleteItems = from ic in icc
                              where ic.ChangeType == ChangeType.Delete
                              select ic.ItemId;

            // Display the ItemIds to be deleted on the client.
            foreach (var item in deleteItems)
            {
                Console.WriteLine("Delete ItemId: {0}", item);
                Console.WriteLine("--------");
                // TODO: Delete messages on the client by using the ItemIds in deleteItems.
            }

            // Create a variable for all the items with read state changes in the ItemChangeCollection.
            var readFlagChangeItems = from ic in icc
                                      where ic.ChangeType == ChangeType.ReadFlagChange
                                      select ic.ItemId;

            // Display the ItemIds that have read state changes.
            foreach (var item in readFlagChangeItems)
            {
                Console.WriteLine("Read flag change to ItemId: {0}", item);
                Console.WriteLine("--------");
                // TODO: Change the read state of the item saved on the client
                // by using the ItemIds in readFlagChangeItems.
            }

            // Create a variable for all the updated items in the ItemChangeCollection.
            var updateItems = from ic in icc
                              where ic.ChangeType == ChangeType.Update
                              select ic.Item;

            // Display the subject for each updated item.
            foreach (var item in updateItems)
            {
                service.LoadPropertiesForItems(updateItems, PropertySet.FirstClassProperties);
                Console.WriteLine("Updated item, all properties loaded");
                Console.WriteLine("Subject: {0}", item.Subject);
                Console.WriteLine("ParentFolderId: {0}", item.ParentFolderId);
                Console.WriteLine("DateTimeCreated: {0}", item.DateTimeCreated);
                Console.WriteLine("--------");
                // TODO: Compare the properties retrieved from LoadPropertiesForItems to the
                // properties on the client and update the client properties accordingly.
            }
        }
        // Synchronize the contents of the rootSyncFolder folder.
        static string SyncContents(ExchangeService service, string cSyncState, FolderId rootSyncFolder)
        {
            Console.WriteLine("--------");
            Console.WriteLine("Starting content sync on the following folder");
            Console.WriteLine("FolderId: {0}", rootSyncFolder);
            Console.WriteLine("--------");

            bool moreChangesAvailable = false;

            do
            {
                // Get a change collection of all items in the rootSyncFolder by calling SyncFolderItems
                // repeatedly until no more changes are available.
                // The folderId parameter must be set to the same folder ID as the previous synchronization call.
                // The propertySet parameter is set to IdOnly to reduce calls to the Exchange database,
                // because any additional properties result in another call to the Exchange database.
                // The ignoredItemIds parameter is set to null, so no items are ignored.
                // The maxChangesReturned parameter is set to return a maximum of 500 items (512 is the default).
                // The syncScope parameter is set to Normal items, so associated items will not be returned.
                // The syncState parameter is set to the content sync state. When this method is called
                // on a new or empty mailbox, the value is null. If the method has been called before,
                // the cSyncState value contains the value previously returned by the server.
                ItemChangeCollection = service.SyncFolderItems(rootSyncFolder, PropertySet.IdOnly, null, 500, SyncFolderItemsScope.NormalItems, cSyncState);

                // Save the sync state for use in future SyncFolderItems requests.
                // The sync state is used by the server to determine what changes to report
                // to the client.
                cSyncState = ItemChangeCollection.SyncState;

                // If the count of changes is zero, there are no changes to synchronize.
                if (ItemChangeCollection.Count == 0)
                {
                    Console.WriteLine("There are no items to synchronize.");
                    Console.WriteLine("--------");
                }

                // Otherwise, write all the changes included in the response
                // to the console.
                else
                {
                    foreach (ItemChange ic in ItemChangeCollection)
                    {
                        Console.WriteLine("ItemChange.ChangeType: " + ic.ChangeType.ToString());
                        Console.WriteLine("ItemChange.ItemId: " + ic.ItemId.UniqueId);
                        Console.WriteLine("--------");
                    }
                }

                // Determine whether more changes are available on the server.
                moreChangesAvailable = ItemChangeCollection.MoreChangesAvailable;

                // Send the ItemChangeCollection to ProcessItems to actually retrieve the messages and changes.
                ProcessItems(ItemChangeCollection);
            }while (moreChangesAvailable);

            Console.WriteLine("Finished content sync on the following folder");
            Console.WriteLine("FolderId: {0}", rootSyncFolder);
            Console.WriteLine("--------");

            return(cSyncState);
        }
Пример #30
0
        private void btnSynchronize_Click(object sender, EventArgs e)
        {
            try
            {
                this.Cursor = Cursors.WaitCursor;

                bool keepGoing  = true;
                int  totalItems = 0;

                this.lstChanges.Items.Clear();

                while (keepGoing)
                {
                    ChangeCollection <ItemChange> changes = this.CurrentService.SyncFolderItems(
                        this.CurrentFolderId,
                        this.CurrentPropertySet,
                        null,
                        500,
                        SyncFolderItemsScope.NormalItems,
                        this.txtSyncState.Text);

                    keepGoing = changes.MoreChangesAvailable;

                    foreach (ItemChange change in changes)
                    {
                        ListViewItem item = new ListViewItem();
                        item.Tag  = change;
                        item.Text = change.ChangeType.ToString();
                        item.SubItems.Add(change.IsRead.ToString());
                        item.SubItems.Add(change.ItemId.UniqueId);

                        try
                        {
                            if (item.SubItems != null)
                            {
                                if (change.Item.Subject != null)
                                {
                                    item.SubItems.Add(change.Item.Subject);
                                }
                                else
                                {
                                    item.SubItems.Add("");
                                }

                                if (change.Item.ItemClass != null)
                                {
                                    item.SubItems.Add(change.Item.ItemClass);
                                }
                                else
                                {
                                    item.SubItems.Add("");
                                }

                                if (change.Item.LastModifiedTime != null)
                                {
                                    item.SubItems.Add(change.Item.LastModifiedTime.ToString());
                                }
                                else
                                {
                                    item.SubItems.Add("");
                                }
                            }
                            else
                            {
                                item.SubItems.Add("");
                                item.SubItems.Add("");
                                item.SubItems.Add("");
                            }
                        }
                        catch (ServiceResponseException oExECF)
                        {
                            System.Diagnostics.Debug.WriteLine(oExECF.ToString());  // Catch a connection error.
                        }
                        catch (Exception oEx)
                        {
                            System.Diagnostics.Debug.WriteLine(oEx.ToString());  // Catch error in case no no-id propreties were not returned.
                        }

                        lstChanges.Items.Add(item);
                    }

                    this.txtSyncState.Text = changes.SyncState;
                    totalItems             = totalItems + changes.Count;
                }

                this.lblLastSyncTime.Text = string.Format(Application.CurrentCulture, "Last SyncFolderItems: {0}", DateTime.Now.ToString());
            }
            catch (ServiceResponseException oExECF)
            {
                System.Diagnostics.Debug.WriteLine(oExECF.ToString());  // Catch a connection error.
            }
            catch (Exception oEx)
            {
                System.Diagnostics.Debug.WriteLine(oEx.ToString());  // Catch error in case no no-id propreties were not returned.
            }


            finally
            {
                this.Cursor = Cursors.Default;
            }
        }
Пример #31
0
 /// <summary>
 /// Adds the specified <see cref="ChangeCollection"/> to <see cref="Updates"/>.
 /// </summary>
 /// <param name="update">The <c>Change</c> to add.</param>
 /// <exception cref="ArgumentNullException">update is null.</exception>
 /// <exception cref="InvalidOperationException">
 /// update belongs to another <see cref="Element"/>.
 /// </exception>
 public void AddUpdate(ChangeCollection update)
 {
     this.AddChild(update);
 }
Пример #32
0
        private static void DisplayChanges(ChangeCollection coll, ChangeToken ct)
        {
            if (coll.Count == 0)
            {
                Console.WriteLine(string.Format("No changes to {0} since {1} UTC.", listName, GetDateStringFromChangeToken(ct)));
                return;
            }

            Console.ForegroundColor = ConsoleColor.Green;
            foreach (ChangeItem itm in coll)
            {

                Console.WriteLine();
                Console.WriteLine(string.Format("List {0} had a Change of type \"{1}\" on the item with Id {2}.", listName, itm.ChangeType.ToString(), itm.ItemId));
            }
            Console.WriteLine();
            Console.ResetColor();
        }
        public static async Task RunAsync([QueueTrigger("processchanges", Connection = "AzureWebJobsStorage")] WebhookNotification notificationModel, ILogger log)
        {
            log.LogInformation($"ProcesResourceChange queue trigger function process Site:{notificationModel.SiteUrl} Resource{notificationModel.Resource} ");

            string tenant  = System.Environment.GetEnvironmentVariable("Tenant", EnvironmentVariableTarget.Process);
            string siteUrl = $"https://{tenant}.sharepoint.com{notificationModel.SiteUrl}";

            log.LogInformation("Getting Azure SharePoint Token");
            LoginEntity loginDetails = await LoginUtil.CertificateLoginDetails();

            OfficeDevPnP.Core.AuthenticationManager authManager = new OfficeDevPnP.Core.AuthenticationManager();

            log.LogInformation("Connecting to SharePoint");
            using (ClientContext clientContext = authManager.GetAzureADAppOnlyAuthenticatedContext(siteUrl, loginDetails.ClientId, loginDetails.Tenant, loginDetails.Certificate))
            {
                log.LogInformation("Getting SharePoint List");
                Guid listId = new Guid(notificationModel.Resource);
                List list   = clientContext.Web.Lists.GetById(listId);

                // grab the changes to the provided list using the GetChanges method
                // on the list. Only request Item changes as that's what's supported via
                // the list web hooks
                ChangeQuery changeQuery = new ChangeQuery(false, false)
                {
                    Item         = true,
                    Add          = true,
                    DeleteObject = false,
                    Update       = true,
                    FetchLimit   = 1000
                };

                ChangeToken lastChangeToken = null;
                if (null == notificationModel.ClientState)
                {
                    throw new ApplicationException("Webhook doesn't contain a Client State");
                }

                Guid id = new Guid(notificationModel.ClientState);
                log.LogInformation("Checking Database for Change Token");
                AzureTableSPWebHook listWebHookRow = await AzureTable.GetListWebHookByID(id, listId);

                if (!string.IsNullOrEmpty(listWebHookRow.LastChangeToken))
                {
                    log.LogInformation("Change Token found");
                    lastChangeToken = new ChangeToken
                    {
                        StringValue = listWebHookRow.LastChangeToken
                    };
                }
                //Start pulling down the changes
                bool allChangesRead = false;

                do
                {
                    if (lastChangeToken == null)
                    {
                        log.LogInformation("Change Token not found grabbing the last 5 days of changes");
                        //If none found, grab only the last 5 day changes.
                        lastChangeToken = new ChangeToken
                        {
                            StringValue = string.Format("1;3;{0};{1};-1", notificationModel.Resource, DateTime.Now.AddDays(-5).ToUniversalTime().Ticks.ToString())
                        };
                    }

                    //Assing the change token to the query..this determins from what point in time we'll receive changes
                    changeQuery.ChangeTokenStart = lastChangeToken;

                    ChangeCollection changes = list.GetChanges(changeQuery);
                    clientContext.Load(list);
                    clientContext.Load(changes);
                    await clientContext.ExecuteQueryAsync();

                    if (changes.Count > 0)
                    {
                        log.LogInformation($"Found {changes.Count} changes");
                        foreach (Change change in changes)
                        {
                            lastChangeToken = change.ChangeToken;

                            if (change is ChangeItem item)
                            {
                                log.LogInformation($"Change {change.ChangeType} on Item:{item.ItemId} on List:{list.Title} Site:{notificationModel.SiteUrl}");
                            }
                        }

                        if (changes.Count < changeQuery.FetchLimit)
                        {
                            allChangesRead = true;
                        }
                    }
                    else
                    {
                        allChangesRead = true;
                    }
                } while (allChangesRead == false);

                if (!listWebHookRow.LastChangeToken.Equals(lastChangeToken.StringValue, StringComparison.InvariantCultureIgnoreCase))
                {
                    listWebHookRow.LastChangeToken = lastChangeToken.StringValue;
                    log.LogInformation("Updating change token");
                    await AzureTable.InsertOrReplaceListWebHook(listWebHookRow);
                }

                if (notificationModel.ExpirationDateTime.AddDays(-30) < DateTime.Now)
                {
                    bool updateResult = list.UpdateWebhookSubscription(new Guid(notificationModel.SubscriptionId), DateTime.Now.AddMonths(2));

                    if (!updateResult)
                    {
                        log.LogError($"The expiration date of web hook {notificationModel.SubscriptionId} with endpoint 'https://{Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME")}/SharePointWebHook' could not be updated");
                    }
                    else
                    {
                        log.LogInformation($"The expiration date of web hook {notificationModel.SubscriptionId} with endpoint 'https://{Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME")}/SharePointWebHook' successfully updated until {DateTime.Now.AddMonths(2).ToLongDateString()} ");
                    }
                }
            }
        }
Пример #34
0
        /// <summary>
        /// <h2>Hauptfunktion</h2>
        /// Hier werden die SyncStates der einzelnen Ordner verglichen und verarbeitet.
        /// Das alles wird umspannt von einer Stopuhr um im Log eine Ausgabe zu haben wie viel Zeit für jeden SyncRun gebraucht wird.
        /// <h3>LOCAL SYNC</h3>
        /// Zuerst wird der Kontakt Ordner im Postfach bearbeitet.
        /// Dazu wird der gespeicherte SyncStatus vom letzten Durchgang gelesen und mit dem aktuellen Status verglichen.
        /// In einer Schleife wird dann über jede erfasste änderung gegangen und in verschiedenen if Abfragen verarbeitet.
        /// Da die SyncStatus Abfrage nur 512 Änderungen zurückgibt, muss die Schleife so lange wiederholt werden bis es keine Änderungen mehr gibt.
        /// <ul>
        /// <li>Create : Kontakt wird wieder gelöscht</li>
        /// <li>Update : Werden aktuell ignoriert da der ChacheModus von Outlook auch immer wieder Änderungen vornimmt.</li>
        /// <li>Delete : Vom gelöschten Kontakt wird das public Pendant in der MatchingListe gesucht. Danach wird der Kontakt aus dem öffentlichen Ordner wieder kopiert.</li>
        /// </ul>
        /// <h3>PUBLIC SYNC</h3>
        /// Als Zweites wird der öffentliche Ordner bearbeitet.
        /// <i>siehe LOCAL SYNC</i>
        /// <ul>
        /// <li>Create : Kontakt wird in das Postfach kopiert.</li>
        /// <li>Update : Kontakt wird in der MatchingListe gesucht. Pendant im Postfach wird gelöscht und aus dem öffentlichen Ordner wieder kopiert.</li>
        /// <li>Delete : Kontakt wird in der MatchingListe gesucht. Pendant wird im Postfach gesucht und gelöscht. Es wird mit dem AppointmentSync der Jahrestag und Geburtstag aus dem Kalender gelöscht.</li>
        /// </ul>
        /// <h3>GET AND SET LOCAL SYNC</h3>
        /// Hier wird noch mal über die Änderungen im Postfach Ordner gegangen aber nichts bearbeitet. Nach der Schleife wird der neue SyncStatus für das Postfach geschrieben.
        /// Das muss im nach dem PUBLIC SYNC nochmal passieren das dur den PUBLIC SYNC änderungen am Postfach Ordner vorgenommen werden können.
        /// </summary>
        /// <returns>Gibt zurück ob min. eine Änderung gemacht worden ist</returns>
        public bool Sync()
        {
            var changeValue = false;

            if (service != null)
            {
                var PublicContactFolder = getPublicFolder();

                writeLog("---------- SyncRun Start - " + ContactFolderName + " ----------");
                Stopwatch stopWatch = new Stopwatch();
                stopWatch.Start();

                #region LOCAL SYNC
                bool isEndOfChanges = false;
                var  localSyncState = getSyncState(false, SMTPAdresse); // Ist null falls Initialer SyncRun

                var MailboxContactFolder = getMailboxFolder(localSyncState == null);

                //makeChangeKey(SMTPAdresse, MailboxContactFolder.Id, "Anfang"); // DEBUG
                do
                {
                    ChangeCollection <ItemChange> icc_mailbox = service.SyncFolderItems(MailboxContactFolder.Id, PropertySet.FirstClassProperties, null, 512, SyncFolderItemsScope.NormalItems, localSyncState);

                    if (icc_mailbox.Count != 0)
                    {
                        changeValue = true;
                        var c = 0;
                        var u = 0;
                        var d = 0;
                        //writeLog(SMTPAdresse + " - " + icc_mailbox.Count + " changes in own mailbox folder");

                        foreach (ItemChange ic_mailbox in icc_mailbox)
                        {
                            Console.WriteLine(ic_mailbox.ChangeType);
                            try
                            {
                                //changeKeys += ic_mailbox.ChangeType + "_" + ic_mailbox.Item.Subject + "_" + ic_mailbox.ItemId.ChangeKey + System.Environment.NewLine; //DEBUG
                            }
                            catch (Exception) {}


                            if (ic_mailbox.ChangeType == ChangeType.Create)
                            {
                                c++;
                                try
                                {
                                    Contact contacts = Contact.Bind(service, ic_mailbox.ItemId);
                                    //writeLog(contacts.Subject + " - Create");
                                    contacts.Delete(DeleteMode.HardDelete);
                                }
                                catch (Exception ex)
                                {
                                    writeLog("ERROR: LocalSync Create: " + ex.Message);
                                }


                                //Console.WriteLine(SMTPAdresse + " - LocalChange " + contacts.Subject + " was created locally and removed automatically");
                            }
                            else if (ic_mailbox.ChangeType == ChangeType.Update)
                            {
                                u++;
                                // Wird nicht benutzt da der ChacheModus von Outlook die ChangeKeys ändert und damit ca alle 30min ein InitialerSync stattfindet
                                // Evtl eigenen Hash über Felder sobalt die Kontakte aus SAP kommen alternativ anderes Feld mit dem letzten Änderungsdatum.
                                // Lokale Änderungen würden sowieso nicht zurück in den Öffentlichen Ordner geschrieben, sondern nur mit den Daten von dort ersetzt werden.
                                // Damit werden lokale Änderungen (z.B Name, Tel ... ) vom Benutzer nicht mehr berücksichtigt, sondern nur noch Create und Delete.

                                //try
                                //{
                                //    Contact contacts = Contact.Bind(service, ic_mailbox.ItemId);
                                //    //writeLog(contacts.Subject + " - Update");

                                //    contacts.Delete(DeleteMode.HardDelete);

                                //    var MailboxId = ic_mailbox.ItemId.UniqueId;
                                //    List<Matching> matchingList = MatchingList.GetList(SMTPAdresse, ContactFolderName);
                                //    Matching result = matchingList.Find(x => x.MailboxId == MailboxId);

                                //    Contact PublicContacts = Contact.Bind(service, result.PublicId);
                                //    PublicContacts.Copy(MailboxContactFolder.Id);
                                //}
                                //catch (Exception ex)
                                //{
                                //    writeLog("ERROR: LocalSync Update: " + ex.Message);
                                //}
                            }
                            else if (ic_mailbox.ChangeType == ChangeType.Delete)
                            {
                                d++;
                                var MailboxId = ic_mailbox.ItemId.UniqueId;

                                try
                                {
                                    List <Matching> matchingList = MatchingList.GetList(SMTPAdresse, ContactFolderName);
                                    Matching        result       = matchingList.Find(x => x.MailboxId == MailboxId);

                                    if (result == null)
                                    {
                                        writeLog("ERROR: No match in MatchingList for: " + MailboxId);
                                    }
                                    else
                                    {
                                        Contact contacts = Contact.Bind(service, result.PublicId);
                                        //writeLog(contacts.Subject + " - Delete");
                                        contacts.Copy(MailboxContactFolder.Id);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    writeLog("ERROR: LocalSync Delete: " + ex.Message);
                                }
                            }
                        }

                        writeLog(SMTPAdresse + " - " + icc_mailbox.Count + " changes (" + c + " created, " + u + " updated, " + d + " deleted) in own mailbox folder");
                        writeLog("LOCAL UPDATES ARE IGNORED!");
                    }

                    localSyncState = icc_mailbox.SyncState;

                    if (!icc_mailbox.MoreChangesAvailable)
                    {
                        isEndOfChanges = true;
                    }
                } while (!isEndOfChanges);

                // DEBUG
                //Int32 unixTimestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
                //File.WriteAllText(binaryPath + @"\changeKeys\ChangeKeys_" + ContactFolderName + SMTPAdresse + "_" + unixTimestamp, changeKeys);

                writeSyncState(localSyncState, false, SMTPAdresse);
                #endregion

                #region PUBLIC SYNC
                bool isEndOfChangesPublic = false;
                var  sSyncState           = getSyncState(true, SMTPAdresse);
                var  index = 0;

                do
                {
                    ChangeCollection <ItemChange> icc = service.SyncFolderItems(PublicContactFolder.Id, PropertySet.FirstClassProperties, null, 512, SyncFolderItemsScope.NormalItems, sSyncState);

                    if (icc.Count == 0)
                    {
                        writeLog(SMTPAdresse + " - There are no item changes to synchronize.");
                    }
                    else
                    {
                        var c = 0;
                        var u = 0;
                        var d = 0;
                        changeValue = true;
                        //writeLog(SMTPAdresse + " - " + icc.Count + " changes in public folder");

                        foreach (ItemChange ic in icc)
                        {
                            if (ic.ChangeType == ChangeType.Create)
                            {
                                c++;
                                try
                                {
                                    Contact contacts = Contact.Bind(service, ic.ItemId);
                                    contacts.Copy(MailboxContactFolder.Id);
                                }
                                catch (Exception ex)
                                {
                                    writeLog("ERROR: ExchangeSync.cs - 152: " + ic.Item.Subject + " - " + ex.Message);
                                }
                            }
                            else if (ic.ChangeType == ChangeType.Update)
                            {
                                u++;
                                try
                                {
                                    List <Matching> matchingList = MatchingList.GetList(SMTPAdresse, ContactFolderName);
                                    Matching        result       = matchingList.Find(x => x.PublicId == ic.ItemId.UniqueId);

                                    Contact LocalContact = Contact.Bind(service, result.MailboxId);
                                    LocalContact.Delete(DeleteMode.HardDelete);

                                    Contact PublicContact = Contact.Bind(service, ic.ItemId);
                                    PublicContact.Copy(MailboxContactFolder.Id);
                                }
                                catch (Exception ex)
                                {
                                    writeLog("ExchangeSync.cs - 265: " + ic.Item.Subject + " - " + ex.Message);
                                }

                                //Console.WriteLine(SMTPAdresse + " - " + index + " - PublicChange " + contacts.Subject + " was updated in public and updated in the mailbox");
                            }
                            else if (ic.ChangeType == ChangeType.Delete)
                            {
                                d++;
                                var PublicId = ic.ItemId.UniqueId;



                                List <Matching> matchingList = MatchingList.GetList(SMTPAdresse, ContactFolderName);

                                if (matchingList != null)
                                {
                                    try
                                    {
                                        Matching result = matchingList.Find(x => x.PublicId == PublicId);

                                        // Löscht nur die Geburtstage und Jahrestage bei Arges Intern Kontakten
                                        if (ContactFolderName == "Arges Intern")
                                        {
                                            var BASync = new AppointmentSync(service, SMTPAdresse);
                                            BASync.deleteName(result.Subject);
                                        }

                                        Contact contacts = Contact.Bind(service, result.MailboxId);
                                        contacts.Delete(DeleteMode.HardDelete);
                                    }
                                    catch (Exception ex)
                                    {
                                        writeLog("ERROR: ExchangeSync.cs - 187: " + ex.Message);
                                    }
                                }
                                else
                                {
                                    writeLog(SMTPAdresse + " - Mailbox MatchingListe konnte nicht geladen werden");
                                }


                                //Contact contacts = Contact.Bind(service, ic.ItemId);

                                //SearchFilter.IsEqualTo filter2 = new SearchFilter.IsEqualTo(ItemSchema.Subject, contacts.Subject);
                                //FindItemsResults<Item> findResults = service.FindItems(MailboxContactFolder.Id, filter2, new ItemView(1));
                                //foreach (Contact item in findResults.Items)
                                //{
                                //    item.Delete(DeleteMode.HardDelete);
                                //}
                            }

                            //var OutputText = index + " - " + ic.ChangeType.ToString() + " - ";
                            //if (ic.Item != null) { OutputText += ic.Item.Subject; }
                            //Console.WriteLine(OutputText);

                            if (index % 50 == 0)
                            {
                                Console.WriteLine("SyncIndex: " + index);
                            }

                            index++;
                        }

                        writeLog(SMTPAdresse + " - " + icc.Count + " changes (" + c + " created, " + u + " updated, " + d + " deleted) in public folder");
                    }

                    sSyncState = icc.SyncState;

                    if (!icc.MoreChangesAvailable)
                    {
                        isEndOfChangesPublic = true;
                    }
                } while (!isEndOfChangesPublic);

                writeSyncState(sSyncState, true, SMTPAdresse);
                #endregion

                #region GET AND SET LOCAL SYNC
                bool isEndOfChangesLocal = false;
                var  sSyncStateLocal     = getSyncState(false, SMTPAdresse);

                do
                {
                    ChangeCollection <ItemChange> icc_mailbox2 = service.SyncFolderItems(MailboxContactFolder.Id, PropertySet.FirstClassProperties, null, 512, SyncFolderItemsScope.NormalItems, sSyncStateLocal);
                    sSyncStateLocal = icc_mailbox2.SyncState;

                    if (!icc_mailbox2.MoreChangesAvailable)
                    {
                        isEndOfChangesLocal = true;
                    }
                } while (!isEndOfChangesLocal);



                writeSyncState(sSyncStateLocal, false, SMTPAdresse);

                //writeSyncState(localSyncState, false, SMTPAdresse);
                #endregion


                //makeChangeKey(SMTPAdresse, MailboxContactFolder.Id, "Ende"); // DEBUG

                stopWatch.Stop();
                writeLog("---------- SyncRun End - " + stopWatch.Elapsed + " ----------");
            }
            return(changeValue);
        }