/// <summary> /// Config Datei wird eingelesen und für für jedes Postfach werden die Jahrestage und Geburtstage überprüft und syncroniesiert. /// Danach werden die Kontakte Syncronisiert. /// </summary> /// <param name="args"></param> static void Main(string[] args) { Config config = ReadConfig(); ExchangeSync.writeLog("##################################################################"); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); foreach (var m in config.mailboxes) { ExchangeSync.writeLog("---------- " + m.smtpAdresse.ToUpper() + " ----------"); ExchangeService service = ExchangeConnect(config.username, config.password, config.domain, m.smtpAdresse, config.exUri); if (m.birthday || m.anniversary) { ExchangeSync.writeLog("---------- SyncRun Start - Appointment ----------"); Stopwatch sWatch = new Stopwatch(); sWatch.Start(); var BASync = new AppointmentSync(service, m.smtpAdresse); // Aktiviren wenn alle Termine gelöscht werden sollen //BASync.runDelete(); if (m.birthday) { BASync.runBirthdaySync(); } if (m.anniversary) { BASync.runAnniversarySync(); } sWatch.Stop(); ExchangeSync.writeLog("---------- SyncRun End - " + stopWatch.Elapsed + " ----------"); } if (m.folder.Count > 0 && m.folder[0] != "") { foreach (var f in m.folder) { var SyncRun = new ExchangeSync(service, m.smtpAdresse, f); SyncRun.writePublicIdInExProp(); bool changes = SyncRun.Sync(); if (changes) { MatchingList.Create(service, m.smtpAdresse, f); ExchangeSync.writeLog("Matching List created: " + m.smtpAdresse + " - " + f); } } } } stopWatch.Stop(); ExchangeSync.writeLog("Complete Sync - Time: " + stopWatch.Elapsed); }
/// <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); }