// 确保项目属性不为空引用 private void EnsureItemProperty(ref Outlook.ItemProperty property, string name, Outlook.OlUserPropertyType propertyType) { // 如果自定义属性为空时 // 首先从联系人项关联的属性集合中获得属性对象 // 如果项目集合中还不存在该属性时,就把该属性名称添加进ItemProperties集合中 if (property == null) { property = contactItem.ItemProperties[name]; if (property == null) { property = contactItem.ItemProperties.Add(name, propertyType); } } }
/// <summary> /// Executed when a new item is added to the calendar folder, and is adding additional parameters to it /// </summary> /// <param name="Item"></param> private void Items_ItemAdd(object Item) { Outlook.AppointmentItem item = Item as Outlook.AppointmentItem; //Debug.WriteLine("CalendarHandler: Items_ItemAdd fired for '" + item.Subject + "'"); // GAI (GlobalAppointmentID) needs to be added as item property, otherwise it cannot be found later Outlook.ItemProperty newPropGAI = item.ItemProperties.Add(ITEM_PROPERTY_GLOBAL_A_ID, Outlook.OlUserPropertyType.olText); item.Save(); newPropGAI.Value = item.GlobalAppointmentID; item.Save(); Marshal.ReleaseComObject(item); item = null; }
private void SyncValue(string methodName, object value) { methodName = methodName.Replace("set_", ""); Microsoft.Office.Interop.Outlook.ContactItem item = BaseContact as Microsoft.Office.Interop.Outlook.ContactItem; if (item != null) { Microsoft.Office.Interop.Outlook.ItemProperty prop = item.ItemProperties[methodName]; if (prop != null) { prop.Value = value; } } }
public void SyncValuesFromBase() { Microsoft.Office.Interop.Outlook.ContactItem item = BaseContact as Microsoft.Office.Interop.Outlook.ContactItem; PropertyInfo[] props = this.GetType().GetProperties(); foreach (PropertyInfo pi in props) { string name = pi.Name.Replace("set_", ""); object[] attribs = pi.GetCustomAttributes(typeof(OutlookSync), false); if (attribs.Length > 0) { Microsoft.Office.Interop.Outlook.ItemProperty oProp = item.ItemProperties[name]; if (oProp != null) { pi.SetValue(this, oProp.Value, null); } } } }
//public static void SetGoogleOutlookNoteId(string syncProfile, Document googleNote, Outlook.NoteItem outlookNote) //{ // if (outlookNote.EntryID == null) // throw new Exception("Must save outlook note before getting id"); // SetGoogleOutlookNoteId(syncProfile, googleNote, GetOutlookId(outlookNote)); //} //public static void SetGoogleOutlookNoteId(string syncProfile, Document googleNote, string outlookNoteId) //{ // // check if exists // bool found = false; // foreach (Google.GData.Extensions.ExtendedProperty p in googleNote.ExtendedProperties) // { // if (p.Name == "gos:oid:" + syncProfile + "") // { // p.Value = outlookNoteId; // found = true; // break; // } // } // if (!found) // { // Google.GData.Extensions.ExtendedProperty prop = new ExtendedProperty(outlookNoteId, "gos:oid:" + syncProfile + ""); // prop.Value = outlookNoteId; // googleNote.ExtendedProperties.Add(prop); // } //} //public static string GetGoogleOutlookNoteId(string syncProfile, Document googleNote) //{ // // get extended prop // foreach (Google.GData.Extensions.ExtendedProperty p in googleNote.DocumentEntry.ExtendedProperties) // { // if (p.Name == "gos:oid:" + syncProfile + "") // return (string)p.Value; // } // return null; //} //public static void ResetGoogleOutlookNoteId(string syncProfile, Document googleNote) //{ // // get extended prop // foreach (Google.GData.Extensions.ExtendedProperty p in googleNote.ExtendedProperties) // { // if (p.Name == "gos:oid:" + syncProfile + "") // { // // remove // googleNote.ExtendedProperties.Remove(p); // return; // } // } //} /// <summary> /// Sets the syncId of the Outlook note and the last sync date. /// Please assure to always call this function when saving OutlookItem /// </summary> /// <param name="sync"></param> /// <param name="outlookNote"></param> /// <param name="googleNote"></param> public static void SetOutlookGoogleNoteId(Synchronizer sync, Outlook.NoteItem outlookNote, Document googleNote) { if (googleNote.DocumentEntry.Id.Uri == null) { throw new NullReferenceException("GoogleNote must have a valid Id"); } //check if outlook note aready has google id property. Outlook.ItemProperties userProperties = outlookNote.ItemProperties; try { Outlook.ItemProperty prop = userProperties[sync.OutlookPropertyNameId]; if (prop == null) { prop = userProperties.Add(sync.OutlookPropertyNameId, Outlook.OlUserPropertyType.olText, true); } try { prop.Value = googleNote.DocumentEntry.Id.Uri.Content; } finally { Marshal.ReleaseComObject(prop); } } finally { Marshal.ReleaseComObject(userProperties); } //save last google's updated date as property /*prop = outlookNote.UserProperties[OutlookPropertyNameUpdated]; * if (prop == null) * prop = outlookNote.UserProperties.Add(OutlookPropertyNameUpdated, Outlook.OlUserPropertyType.olDateTime, null, null); * prop.Value = googleNote.Updated;*/ //Also set the OutlookLastSync date when setting a match between Outlook and Google to assure the lastSync updated when Outlook note is saved afterwards SetOutlookLastSync(sync, outlookNote); }
/// <summary> /// Matches outlook and Google appointment by a) id b) properties. /// </summary> /// <param name="sync">Syncronizer instance</param> /// <returns>Returns a list of match pairs (outlook appointment + Google appointment) for all appointment. Those that weren't matche will have it's peer set to null</returns> public static List <AppointmentMatch> MatchAppointments(Synchronizer sync) { Logger.Log("Matching Outlook and Google appointments...", EventType.Information); var result = new List <AppointmentMatch>(); var googleAppointmentExceptions = new List <Event>(); //for each outlook appointment try to get Google appointment id from user properties //if no match - try to match by properties //if no match - create a new match pair without Google appointment. //foreach (Outlook._AppointmentItem olc in outlookAppointments) var OutlookAppointmentsWithoutSyncId = new Collection <Outlook.AppointmentItem>(); #region Match first all outlookAppointments by sync id for (int i = 1; i <= sync.OutlookAppointments.Count; i++) { Outlook.AppointmentItem ola; try { ola = sync.OutlookAppointments[i] as Outlook.AppointmentItem; //For debugging: //if (ola.Subject == "Flex Pilot - Latest Status") // - 14.07.2014 11:30:00 // throw new Exception("Debugging: Flex Pilot - Latest Status"); if (ola == null || string.IsNullOrEmpty(ola.Subject) && ola.Start == AppointmentSync.outlookDateMin) { Logger.Log("Empty Outlook appointment found. Skipping", EventType.Warning); sync.SkippedCount++; sync.SkippedCountNotMatches++; continue; } else if (ola.MeetingStatus == Outlook.OlMeetingStatus.olMeetingCanceled || ola.MeetingStatus == Outlook.OlMeetingStatus.olMeetingReceivedAndCanceled) { Logger.Log("Skipping Outlook appointment found because it is cancelled: " + ola.Subject + " - " + ola.Start, EventType.Debug); //sync.SkippedCount++; //sync.SkippedCountNotMatches++; continue; } else if (Synchronizer.MonthsInPast > 0 && (ola.IsRecurring && ola.GetRecurrencePattern().PatternEndDate < DateTime.Now.AddMonths(-Synchronizer.MonthsInPast) || !ola.IsRecurring && ola.End < DateTime.Now.AddMonths(-Synchronizer.MonthsInPast)) || Synchronizer.MonthsInFuture > 0 && (ola.IsRecurring && ola.GetRecurrencePattern().PatternStartDate > DateTime.Now.AddMonths(Synchronizer.MonthsInFuture) || !ola.IsRecurring && ola.Start > DateTime.Now.AddMonths(Synchronizer.MonthsInFuture))) { Logger.Log("Skipping Outlook appointment because it is out of months range to sync:" + ola.Subject + " - " + ola.Start, EventType.Debug); continue; } //else if (ola.Subject != "Business Trip") //{//Only for debugging purposes, please comment if not needed // Logger.Log("Skipping Outlook appointment because of DEBUGGING:" + ola.Subject + " - " + ola.Start, EventType.Error); // continue; //} } catch (Exception ex) { //this is needed because some appointments throw exceptions Logger.Log("Accessing Outlook appointment threw and exception. Skipping: " + ex.Message, EventType.Warning); sync.SkippedCount++; sync.SkippedCountNotMatches++; continue; } //try //{ if (NotificationReceived != null) { NotificationReceived(String.Format("Matching appointment {0} of {1} by id: {2} ...", i, sync.OutlookAppointments.Count, ola.Subject)); } // Create our own info object to go into collections/lists, so we can free the Outlook objects and not run out of resources / exceed policy limits. //OutlookAppointmentInfo olci = new OutlookAppointmentInfo(ola, sync); //try to match this appointment to one of Google appointments Outlook.ItemProperties userProperties = ola.ItemProperties; Outlook.ItemProperty idProp = userProperties[sync.OutlookPropertyNameId]; try { if (idProp != null) { string googleAppointmentId = string.Copy((string)idProp.Value); Event foundAppointment = sync.GetGoogleAppointmentById(googleAppointmentId); var match = new AppointmentMatch(ola, null); if (foundAppointment != null && !foundAppointment.Status.Equals("cancelled")) { //we found a match by google id, that is not deleted or cancelled yet //ToDo: For an unknown reason, some appointments are duplicate in GoogleAppointments, therefore remove all duplicates before continuing while (foundAppointment != null) { match.AddGoogleAppointment(foundAppointment); result.Add(match); //Remove the appointment from the list to not sync it twice if (sync.GoogleAppointments.Contains(foundAppointment)) { sync.GoogleAppointments.Remove(foundAppointment); foundAppointment = sync.GetGoogleAppointmentById(googleAppointmentId); } else { foundAppointment = null; } } } else { OutlookAppointmentsWithoutSyncId.Add(ola); } } else { OutlookAppointmentsWithoutSyncId.Add(ola); } } finally { if (idProp != null) { Marshal.ReleaseComObject(idProp); } Marshal.ReleaseComObject(userProperties); } } #endregion #region Match the remaining appointments by properties for (int i = 0; i < OutlookAppointmentsWithoutSyncId.Count; i++) { Outlook.AppointmentItem ola = OutlookAppointmentsWithoutSyncId[i]; if (NotificationReceived != null) { NotificationReceived(String.Format("Matching appointment {0} of {1} by unique properties: {2} ...", i + 1, OutlookAppointmentsWithoutSyncId.Count, ola.Subject)); } //no match found by id => match by subject/title //create a default match pair with just outlook appointment. var match = new AppointmentMatch(ola, null); //foreach Google appointment try to match and create a match pair if found some match(es) for (int j = sync.GoogleAppointments.Count - 1; j >= 0; j--) { var googleAppointment = sync.GoogleAppointments[j]; // only match if there is a appointment targetBody, else // a matching Google appointment will be created at each sync if (!googleAppointment.Status.Equals("cancelled") && ola.Subject == googleAppointment.Summary && googleAppointment.Start.DateTime != null && ola.Start == googleAppointment.Start.DateTime) { match.AddGoogleAppointment(googleAppointment); sync.GoogleAppointments.Remove(googleAppointment); //ToDo: For an unknown reason, some appointments are duplicate in GoogleAppointments, therefore remove all duplicates before continuing Event foundAppointment = sync.GetGoogleAppointmentById(AppointmentPropertiesUtils.GetGoogleId(googleAppointment)); while (foundAppointment != null) { //we found a match by google id, that is not deleted yet match.AddGoogleAppointment(foundAppointment); //Remove the appointment from the list to not sync it twice if (sync.GoogleAppointments.Contains(foundAppointment)) { sync.GoogleAppointments.Remove(foundAppointment); foundAppointment = sync.GetGoogleAppointmentById(AppointmentPropertiesUtils.GetGoogleId(googleAppointment)); } else { foundAppointment = null; } } } } if (match.GoogleAppointment == null) { Logger.Log(string.Format("No match found for outlook appointment ({0}) => {1}", match.OutlookAppointment.Subject + " - " + match.OutlookAppointment.Start, (AppointmentPropertiesUtils.GetOutlookGoogleAppointmentId(sync, match.OutlookAppointment) != null ? "Delete from Outlook" : "Add to Google")), EventType.Information); } result.Add(match); } #endregion //for each Google appointment that's left (they will be nonmatched) create a new match pair without outlook appointment. for (int i = 0; i < sync.GoogleAppointments.Count; i++) { var googleAppointment = sync.GoogleAppointments[i]; //For debugging: //if (googleAppointment.Summary == "Flex Pilot - Latest Status") // throw new Exception("Debugging: Flex Pilot - Latest Status"); if (NotificationReceived != null) { NotificationReceived(String.Format("Adding new Google appointment {0} of {1} by unique properties: {2} ...", i + 1, sync.GoogleAppointments.Count, googleAppointment.Summary)); } if (googleAppointment.RecurringEventId != null) { sync.SkippedCountNotMatches++; googleAppointmentExceptions.Add(googleAppointment); } else if (googleAppointment.Status.Equals("cancelled")) { Logger.Log("Skipping Google appointment found because it is cancelled: " + googleAppointment.Summary + " - " + Synchronizer.GetTime(googleAppointment), EventType.Debug); //sync.SkippedCount++; //sync.SkippedCountNotMatches++; } else if (string.IsNullOrEmpty(googleAppointment.Summary) && (googleAppointment.Start == null || googleAppointment.Start.DateTime == null && googleAppointment.Start.Date == null)) { // no title or time sync.SkippedCount++; sync.SkippedCountNotMatches++; Logger.Log("Skipped GoogleAppointment because no unique property found (Subject or StartDate):" + googleAppointment.Summary + " - " + Synchronizer.GetTime(googleAppointment), EventType.Warning); } //else if (googleAppointment.Summary != "Business Trip") //{//Only for debugging purposes, please comment if not needed // Logger.Log("Skipping Google appointment because of DEBUGGING:" + googleAppointment.Summary + " - " + googleAppointment.Times[0].StartTime, EventType.Error); // continue; //} else { Logger.Log(string.Format("No match found for Google appointment ({0}) => {1}", googleAppointment.Summary + " - " + Synchronizer.GetTime(googleAppointment), (!string.IsNullOrEmpty(AppointmentPropertiesUtils.GetGoogleOutlookAppointmentId(sync.SyncProfile, googleAppointment)) ? "Delete from Google" : "Add to Outlook")), EventType.Information); var match = new AppointmentMatch(null, googleAppointment); result.Add(match); } } //for each Google appointment exception, assign to proper match for (int i = 0; i < googleAppointmentExceptions.Count; i++) { var googleAppointment = googleAppointmentExceptions[i]; if (NotificationReceived != null) { NotificationReceived(String.Format("Adding Google appointment exception {0} of {1} ...", i + 1, googleAppointmentExceptions.Count, googleAppointment.Summary + " - " + Synchronizer.GetTime(googleAppointment))); } //Search for original recurrent event in matches //AtomId atomId = new AtomId(googleAppointment.Id.AbsoluteUri.Substring(0, googleAppointment.Id.AbsoluteUri.LastIndexOf("/") + 1) + googleAppointment.RecurringEventId); bool found = false; foreach (AppointmentMatch match in result) { if (match.GoogleAppointment != null && googleAppointment.RecurringEventId.Equals(match.GoogleAppointment.Id)) { match.GoogleAppointmentExceptions.Add(googleAppointment); found = true; break; } } if (!found) { Logger.Log(string.Format("No match found for Google appointment exception: {0}", googleAppointment.Summary + " - " + Synchronizer.GetTime(googleAppointment)), EventType.Debug); } } return(result); }
public static void ResetOutlookGoogleNoteId(Synchronizer sync, Outlook.NoteItem outlookNote) { Outlook.ItemProperties userProperties = outlookNote.ItemProperties; try { Outlook.ItemProperty idProp = userProperties[sync.OutlookPropertyNameId]; try { Outlook.ItemProperty lastSyncProp = userProperties[sync.OutlookPropertyNameSynced]; try { if (idProp == null && lastSyncProp == null) { return; } List <int> indexesToBeRemoved = new List <int>(); IEnumerator en = userProperties.GetEnumerator(); en.Reset(); int index = 0; // 0 based collection while (en.MoveNext()) { Outlook.ItemProperty userProperty = en.Current as Outlook.ItemProperty; if (userProperty == idProp || userProperty == lastSyncProp) { indexesToBeRemoved.Add(index); //outlookNote.UserProperties.Remove(index); //Don't return to remove both properties, googleId and lastSynced //return; } index++; Marshal.ReleaseComObject(userProperty); } for (int i = indexesToBeRemoved.Count - 1; i >= 0; i--) { userProperties.Remove(indexesToBeRemoved[i]); } //throw new Exception("Did not find prop."); } finally { if (lastSyncProp != null) { Marshal.ReleaseComObject(lastSyncProp); } } } finally { if (idProp != null) { Marshal.ReleaseComObject(idProp); } } } finally { Marshal.ReleaseComObject(userProperties); } }
/// <summary> /// Returns a AppointmentSyncCollection, with all updates since the specified timestamp /// </summary> /// <param name="timestamp"></param> /// <returns></returns> private AppointmentSyncCollection GetUpdates(DateTime timestamp) { if (_customCalendar == null) { return(null); } AppointmentSyncCollection syncCollection = new AppointmentSyncCollection(); // Debug.WriteLine("CalendarHandler: TimeStamp -> " + timestamp); foreach (Outlook.AppointmentItem item in _customCalendar.Items) { Boolean updatedBySync = false; //Debug.WriteLine("CalendarHandler: Item (" + item.Subject + ") LastModificationTime -> " + item.LastModificationTime); // if the date from the SYNC_UPDATE is newer or as the LastModificationTime, the item was not updated by the user if (item.ItemProperties[ITEM_PROPERTY_SYNC_UPDATE] != null && DateTime.Parse(item.ItemProperties[ITEM_PROPERTY_SYNC_UPDATE].Value) >= item.LastModificationTime) { updatedBySync = true; } //Debug.WriteLine("CalendarHandler: Item (" + item.Subject + ") SyncUpdate -> " + syncUpdate); //Debug.WriteLine("CalendarHandler: Item (" + item.Subject + ") wasUpdatedBySync -> " + wasUpdatedBySync); if (item.LastModificationTime >= timestamp && !updatedBySync) { // ADDING // if SyncID does not exist, it is not yet synced and needs to be added to the other calendar if (item.ItemProperties[ITEM_PROPERTY_SYNC_ID] == null) { syncCollection.AddList.Add(new OutlookAppointment(item)); if (item.ItemProperties[ITEM_PROPERTY_GLOBAL_A_ID] == null) { // GAI (GlobalAppointmentID) needs to be added as item property, otherwise it cannot be found later Outlook.ItemProperty newProp = item.ItemProperties.Add(ITEM_PROPERTY_GLOBAL_A_ID, Outlook.OlUserPropertyType.olText); item.Save(); newProp.Value = item.GlobalAppointmentID; item.Save(); } } // UPDATING // if a SyncID exist, it is already synced and needs to be updated in the other calendar else { syncCollection.UpdateList.Add(new OutlookAppointment(item)); } } } // DELETING foreach (String syncID in GetAppointmentsForDeleting()) { OutlookAppointment item = new OutlookAppointment(); item.SyncID = syncID; syncCollection.DeleteList.Add(item); } Debug.WriteLine("CalendarHandler (GetUpdates): Added: " + syncCollection.AddList.Count + " | Updated: " + syncCollection.UpdateList.Count + " | Deleted: " + syncCollection.DeleteList.Count); ResetDeleteStorage(); SetSyncTime(DateTime.Now); return(syncCollection); }
/// <summary> /// Matches outlook and google note by a) google id b) properties. /// </summary> /// <param name="sync">Syncronizer instance</param> /// <returns>Returns a list of match pairs (outlook note + google note) for all note. Those that weren't matche will have it's peer set to null</returns> public static List <NoteMatch> MatchNotes(Syncronizer sync) { Logger.Log("Matching Outlook and Google notes...", EventType.Information); var result = new List <NoteMatch>(); //string duplicateGoogleMatches = ""; //string duplicateOutlookNotes = ""; //sync.GoogleNoteDuplicates = new Collection<NoteMatch>(); //sync.OutlookNoteDuplicates = new Collection<NoteMatch>(); //for each outlook note try to get google note id from user properties //if no match - try to match by properties //if no match - create a new match pair without google note. //foreach (Outlook._NoteItem olc in outlookNotes) var outlookNotesWithoutOutlookGoogleId = new Collection <Outlook.NoteItem>(); #region Match first all outlookNotes by sync id for (int i = 1; i <= sync.OutlookNotes.Count; i++) { Outlook.NoteItem oln; try { oln = sync.OutlookNotes[i] as Outlook.NoteItem; if (oln == null || string.IsNullOrEmpty(oln.Subject)) { Logger.Log("Empty Outlook note found. Skipping", EventType.Warning); sync.SkippedCount++; sync.SkippedCountNotMatches++; continue; } } catch (Exception ex) { //this is needed because some notes throw exceptions Logger.Log("Accessing Outlook note threw and exception. Skipping: " + ex.Message, EventType.Warning); sync.SkippedCount++; sync.SkippedCountNotMatches++; continue; } //try //{ if (NotificationReceived != null) { NotificationReceived(String.Format("Matching note {0} of {1} by id: {2} ...", i, sync.OutlookNotes.Count, oln.Subject)); } // Create our own info object to go into collections/lists, so we can free the Outlook objects and not run out of resources / exceed policy limits. //OutlookNoteInfo olci = new OutlookNoteInfo(oln, sync); //try to match this note to one of google notes Outlook.ItemProperties userProperties = oln.ItemProperties; Outlook.ItemProperty idProp = userProperties[sync.OutlookPropertyNameId]; try { if (idProp != null) { string googleNoteId = string.Copy((string)idProp.Value); Document foundNote = sync.GetGoogleNoteById(googleNoteId); var match = new NoteMatch(oln, null); //Check first, that this is not a duplicate //e.g. by copying an existing Outlook note //or by Outlook checked this as duplicate, but the user selected "Add new" // Collection<OutlookNoteInfo> duplicates = sync.OutlookNoteByProperty(sync.OutlookPropertyNameId, googleNoteId); // if (duplicates.Count > 1) // { // foreach (OutlookNoteInfo duplicate in duplicates) // { // if (!string.IsNullOrEmpty(googleNoteId)) // { // Logger.Log("Duplicate Outlook note found, resetting match and try to match again: " + duplicate.FileAs, EventType.Warning); // idProp.Value = ""; // } // } // if (foundNote != null && !foundNote.Deleted) // { // NotePropertiesUtils.ResetGoogleOutlookNoteId(sync.SyncProfile, foundNote); // } // outlookNotesWithoutOutlookGoogleId.Add(olci); // } // else // { if (foundNote != null) { //we found a match by google id, that is not deleted yet match.AddGoogleNote(foundNote); result.Add(match); //Remove the note from the list to not sync it twice sync.GoogleNotes.Remove(foundNote); } else { ////If no match found, is the note either deleted on Google side or was a copy on Outlook side ////If it is a copy on Outlook side, the idProp.Value must be emptied to assure, the note is created on Google side and not deleted on Outlook side ////bool matchIsDuplicate = false; //foreach (NoteMatch existingMatch in result) //{ // if (existingMatch.OutlookNote.UserProperties[sync.OutlookPropertyNameId].Value.Equals(idProp.Value)) // { // //matchIsDuplicate = true; // idProp.Value = ""; // break; // } //} outlookNotesWithoutOutlookGoogleId.Add(oln); //if (!matchIsDuplicate) // result.Add(match); } // } } else { outlookNotesWithoutOutlookGoogleId.Add(oln); } } finally { if (idProp != null) { Marshal.ReleaseComObject(idProp); } Marshal.ReleaseComObject(userProperties); } //} //finally //{ // Marshal.ReleaseComObject(oln); // oln = null; //} } #endregion #region Match the remaining notes by properties for (int i = 0; i < outlookNotesWithoutOutlookGoogleId.Count; i++) { Outlook.NoteItem oln = outlookNotesWithoutOutlookGoogleId[i]; if (NotificationReceived != null) { NotificationReceived(String.Format("Matching note {0} of {1} by unique properties: {2} ...", i + 1, outlookNotesWithoutOutlookGoogleId.Count, oln.Subject)); } //no match found by id => match by subject/title //create a default match pair with just outlook note. var match = new NoteMatch(oln, null); //foreach google contact try to match and create a match pair if found some match(es) for (int j = sync.GoogleNotes.Count - 1; j >= 0; j--) { Document entry = sync.GoogleNotes[j]; string body = NotePropertiesUtils.GetBody(sync, entry); if (!string.IsNullOrEmpty(body)) { body = body.Replace("\r\n", string.Empty).Replace(" ", string.Empty).Replace("�", string.Empty); } string outlookBody = null; if (!string.IsNullOrEmpty(oln.Body)) { outlookBody = oln.Body.Replace("\t", " ").Replace("\r\n", string.Empty).Replace(" ", string.Empty).Replace("�", string.Empty); } // only match if there is a note body, else // a matching google note will be created at each sync if (!string.IsNullOrEmpty(outlookBody) && !string.IsNullOrEmpty(body) && outlookBody.Equals(body, StringComparison.InvariantCultureIgnoreCase) ) { match.AddGoogleNote(entry); sync.GoogleNotes.Remove(entry); } } #region find duplicates not needed now //if (match.GoogleNote == null && match.OutlookNote != null) //{//If GoogleNote, we have to expect a conflict because of Google insert of duplicates // foreach (Note entry in sync.GoogleNotes) // { // if (!string.IsNullOrEmpty(olc.FullName) && olc.FullName.Equals(entry.Title, StringComparison.InvariantCultureIgnoreCase) || // !string.IsNullOrEmpty(olc.FileAs) && olc.FileAs.Equals(entry.Title, StringComparison.InvariantCultureIgnoreCase) || // !string.IsNullOrEmpty(olc.Email1Address) && FindEmail(olc.Email1Address, entry.Emails) != null || // !string.IsNullOrEmpty(olc.Email2Address) && FindEmail(olc.Email1Address, entry.Emails) != null || // !string.IsNullOrEmpty(olc.Email3Address) && FindEmail(olc.Email1Address, entry.Emails) != null || // olc.MobileTelephoneNumber != null && FindPhone(olc.MobileTelephoneNumber, entry.Phonenumbers) != null // ) // } //// check for each email 1,2 and 3 if a duplicate exists with same email, because Google doesn't like inserting new notes with same email //Collection<Outlook.NoteItem> duplicates1 = new Collection<Outlook.NoteItem>(); //Collection<Outlook.NoteItem> duplicates2 = new Collection<Outlook.NoteItem>(); //Collection<Outlook.NoteItem> duplicates3 = new Collection<Outlook.NoteItem>(); //if (!string.IsNullOrEmpty(olc.Email1Address)) // duplicates1 = sync.OutlookNoteByEmail(olc.Email1Address); //if (!string.IsNullOrEmpty(olc.Email2Address)) // duplicates2 = sync.OutlookNoteByEmail(olc.Email2Address); //if (!string.IsNullOrEmpty(olc.Email3Address)) // duplicates3 = sync.OutlookNoteByEmail(olc.Email3Address); //if (duplicates1.Count > 1 || duplicates2.Count > 1 || duplicates3.Count > 1) //{ // if (string.IsNullOrEmpty(duplicatesEmailList)) // duplicatesEmailList = "Outlook notes with the same email have been found and cannot be synchronized. Please delete duplicates of:"; // if (duplicates1.Count > 1) // foreach (Outlook.NoteItem duplicate in duplicates1) // { // string str = olc.FileAs + " (" + olc.Email1Address + ")"; // if (!duplicatesEmailList.Contains(str)) // duplicatesEmailList += Environment.NewLine + str; // } // if (duplicates2.Count > 1) // foreach (Outlook.NoteItem duplicate in duplicates2) // { // string str = olc.FileAs + " (" + olc.Email2Address + ")"; // if (!duplicatesEmailList.Contains(str)) // duplicatesEmailList += Environment.NewLine + str; // } // if (duplicates3.Count > 1) // foreach (Outlook.NoteItem duplicate in duplicates3) // { // string str = olc.FileAs + " (" + olc.Email3Address + ")"; // if (!duplicatesEmailList.Contains(str)) // duplicatesEmailList += Environment.NewLine + str; // } // continue; //} //else if (!string.IsNullOrEmpty(olc.Email1Address)) //{ // NoteMatch dup = result.Find(delegate(NoteMatch match) // { // return match.OutlookNote != null && match.OutlookNote.Email1Address == olc.Email1Address; // }); // if (dup != null) // { // Logger.Log(string.Format("Duplicate note found by Email1Address ({0}). Skipping", olc.FileAs), EventType.Information); // continue; // } //} //// check for unique mobile phone, because this sync tool uses the also the mobile phone to identify matches between Google and Outlook //Collection<Outlook.NoteItem> duplicatesMobile = new Collection<Outlook.NoteItem>(); //if (!string.IsNullOrEmpty(olc.MobileTelephoneNumber)) // duplicatesMobile = sync.OutlookNoteByProperty("MobileTelephoneNumber", olc.MobileTelephoneNumber); //if (duplicatesMobile.Count > 1) //{ // if (string.IsNullOrEmpty(duplicatesMobileList)) // duplicatesMobileList = "Outlook notes with the same mobile phone have been found and cannot be synchronized. Please delete duplicates of:"; // foreach (Outlook.NoteItem duplicate in duplicatesMobile) // { // sync.OutlookNoteDuplicates.Add(olc); // string str = olc.FileAs + " (" + olc.MobileTelephoneNumber + ")"; // if (!duplicatesMobileList.Contains(str)) // duplicatesMobileList += Environment.NewLine + str; // } // continue; //} //else if (!string.IsNullOrEmpty(olc.MobileTelephoneNumber)) //{ // NoteMatch dup = result.Find(delegate(NoteMatch match) // { // return match.OutlookNote != null && match.OutlookNote.MobileTelephoneNumber == olc.MobileTelephoneNumber; // }); // if (dup != null) // { // Logger.Log(string.Format("Duplicate note found by MobileTelephoneNumber ({0}). Skipping", olc.FileAs), EventType.Information); // continue; // } //} #endregion // if (match.AllGoogleNoteMatches == null || match.AllGoogleNoteMatches.Count == 0) // { // //Check, if this Outlook note has a match in the google duplicates // bool duplicateFound = false; // foreach (NoteMatch duplicate in sync.GoogleNoteDuplicates) // { // if (duplicate.AllGoogleNoteMatches.Count > 0 && // (!string.IsNullOrEmpty(olci.FileAs) && !string.IsNullOrEmpty(duplicate.AllGoogleNoteMatches[0].Title) && olci.FileAs.Equals(duplicate.AllGoogleNoteMatches[0].Title.Replace("\r\n", "\n").Replace("\n", "\r\n"), StringComparison.InvariantCultureIgnoreCase) || //Replace twice to not replace a \r\n by \r\r\n. This is necessary because \r\n are saved as \n only to google // !string.IsNullOrEmpty(olci.FileAs) && !string.IsNullOrEmpty(duplicate.AllGoogleNoteMatches[0].Name.FullName) && olci.FileAs.Equals(duplicate.AllGoogleNoteMatches[0].Name.FullName.Replace("\r\n", "\n").Replace("\n", "\r\n"), StringComparison.InvariantCultureIgnoreCase) || // !string.IsNullOrEmpty(olci.FullName) && !string.IsNullOrEmpty(duplicate.AllGoogleNoteMatches[0].Name.FullName) && olci.FullName.Equals(duplicate.AllGoogleNoteMatches[0].Name.FullName.Replace("\r\n", "\n").Replace("\n", "\r\n"), StringComparison.InvariantCultureIgnoreCase) || // !string.IsNullOrEmpty(olci.Email1Address) && duplicate.AllGoogleNoteMatches[0].Emails.Count > 0 && olci.Email1Address.Equals(duplicate.AllGoogleNoteMatches[0].Emails[0].Address, StringComparison.InvariantCultureIgnoreCase) || // //!string.IsNullOrEmpty(olci.Email2Address) && FindEmail(olci.Email2Address, duplicate.AllGoogleNoteMatches[0].Emails) != null || // //!string.IsNullOrEmpty(olci.Email3Address) && FindEmail(olci.Email3Address, duplicate.AllGoogleNoteMatches[0].Emails) != null || // olci.MobileTelephoneNumber != null && FindPhone(olci.MobileTelephoneNumber, duplicate.AllGoogleNoteMatches[0].Phonenumbers) != null || // !string.IsNullOrEmpty(olci.FileAs) && string.IsNullOrEmpty(duplicate.AllGoogleNoteMatches[0].Title) && duplicate.AllGoogleNoteMatches[0].Organizations.Count > 0 && olci.FileAs.Equals(duplicate.AllGoogleNoteMatches[0].Organizations[0].Name, StringComparison.InvariantCultureIgnoreCase) // ) || // !string.IsNullOrEmpty(olci.FileAs) && olci.FileAs.Equals(duplicate.OutlookNote.Subject, StringComparison.InvariantCultureIgnoreCase) || // !string.IsNullOrEmpty(olci.FullName) && olci.FullName.Equals(duplicate.OutlookNote.FullName, StringComparison.InvariantCultureIgnoreCase) || // !string.IsNullOrEmpty(olci.Email1Address) && olci.Email1Address.Equals(duplicate.OutlookNote.Email1Address, StringComparison.InvariantCultureIgnoreCase) || // // olci.Email1Address.Equals(duplicate.OutlookNote.Email2Address, StringComparison.InvariantCultureIgnoreCase) || // // olci.Email1Address.Equals(duplicate.OutlookNote.Email3Address, StringComparison.InvariantCultureIgnoreCase) // // ) || // //!string.IsNullOrEmpty(olci.Email2Address) && (olci.Email2Address.Equals(duplicate.OutlookNote.Email1Address, StringComparison.InvariantCultureIgnoreCase) || // // olci.Email2Address.Equals(duplicate.OutlookNote.Email2Address, StringComparison.InvariantCultureIgnoreCase) || // // olci.Email2Address.Equals(duplicate.OutlookNote.Email3Address, StringComparison.InvariantCultureIgnoreCase) // // ) || // //!string.IsNullOrEmpty(olci.Email3Address) && (olci.Email3Address.Equals(duplicate.OutlookNote.Email1Address, StringComparison.InvariantCultureIgnoreCase) || // // olci.Email3Address.Equals(duplicate.OutlookNote.Email2Address, StringComparison.InvariantCultureIgnoreCase) || // // olci.Email3Address.Equals(duplicate.OutlookNote.Email3Address, StringComparison.InvariantCultureIgnoreCase) // // ) || // olci.MobileTelephoneNumber != null && olci.MobileTelephoneNumber.Equals(duplicate.OutlookNote.MobileTelephoneNumber) || // !string.IsNullOrEmpty(olci.FileAs) && string.IsNullOrEmpty(duplicate.GoogleNote.Title) && duplicate.GoogleNote.Organizations.Count > 0 && olci.FileAs.Equals(duplicate.GoogleNote.Organizations[0].Name, StringComparison.InvariantCultureIgnoreCase) // ) // { // duplicateFound = true; // sync.OutlookNoteDuplicates.Add(match); // if (string.IsNullOrEmpty(duplicateOutlookNotes)) // duplicateOutlookNotes = "Outlook note found that has been already identified as duplicate Google note (either same email, Mobile or FullName) and cannot be synchronized. Please delete or resolve duplicates of:"; // string str = olci.FileAs + " (" + olci.Email1Address + ", " + olci.MobileTelephoneNumber + ")"; // if (!duplicateOutlookNotes.Contains(str)) // duplicateOutlookNotes += Environment.NewLine + str; // } // } // if (!duplicateFound) if (match.GoogleNote == null) { Logger.Log(string.Format("No match found for outlook note ({0}) => {1}", match.OutlookNote.Subject, (NotePropertiesUtils.GetOutlookGoogleNoteId(sync, match.OutlookNote) != null ? "Delete from Outlook" : "Add to Google")), EventType.Information); } // } // else // { // //Remember Google duplicates to later react to it when resetting matches or syncing // //ResetMatches: Also reset the duplicates // //Sync: Skip duplicates (don't sync duplicates to be fail safe) // if (match.AllGoogleNoteMatches.Count > 1) // { // sync.GoogleNoteDuplicates.Add(match); // foreach (Note entry in match.AllGoogleNoteMatches) // { // //Create message for duplicatesFound exception // if (string.IsNullOrEmpty(duplicateGoogleMatches)) // duplicateGoogleMatches = "Outlook notes matching with multiple Google notes have been found (either same email, Mobile, FullName or company) and cannot be synchronized. Please delete or resolve duplicates of:"; // string str = olci.FileAs + " (" + olci.Email1Address + ", " + olci.MobileTelephoneNumber + ")"; // if (!duplicateGoogleMatches.Contains(str)) // duplicateGoogleMatches += Environment.NewLine + str; // } // } // } result.Add(match); } #endregion //if (!string.IsNullOrEmpty(duplicateGoogleMatches) || !string.IsNullOrEmpty(duplicateOutlookNotes)) // duplicatesFound = new DuplicateDataException(duplicateGoogleMatches + Environment.NewLine + Environment.NewLine + duplicateOutlookNotes); //else // duplicatesFound = null; //return result; //for each google note that's left (they will be nonmatched) create a new match pair without outlook note. for (int i = 0; i < sync.GoogleNotes.Count; i++) { Document entry = sync.GoogleNotes[i]; if (NotificationReceived != null) { NotificationReceived(String.Format("Adding new Google note {0} of {1} by unique properties: {2} ...", i + 1, sync.GoogleNotes.Count, entry.Title)); } //string googleOutlookId = NotePropertiesUtils.GetGoogleOutlookNoteId(sync.SyncProfile, entry); //if (!String.IsNullOrEmpty(googleOutlookId) && skippedOutlookIds.Contains(googleOutlookId)) //{ // Logger.Log("Skipped GoogleNote because Outlook note couldn't be matched beacause of previous problem (see log): " + entry.Title, EventType.Warning); //} //else if (string.IsNullOrEmpty(entry.Title) && string.IsNullOrEmpty(entry.Content)) { // no title or content sync.SkippedCount++; sync.SkippedCountNotMatches++; Logger.Log("Skipped GoogleNote because no unique property found (Title or Content):" + entry.Title, EventType.Warning); } else { Logger.Log(string.Format("No match found for google note ({0}) => {1}", entry.Title, (NotePropertiesUtils.NoteFileExists(entry.Id, sync.SyncProfile) ? "Delete from Google" : "Add to Outlook")), EventType.Information); var match = new NoteMatch(null, entry); result.Add(match); } } return(result); }