private MAPIFolder getSharedCalendar(NameSpace oNS, String sharedURI)
        {
            Recipient  sharer         = null;
            MAPIFolder sharedCalendar = null;

            try {
                sharer = oNS.CreateRecipient(sharedURI);
                sharer.Resolve();
                if (sharer.DisplayType == OlDisplayType.olDistList)
                {
                    throw new System.Exception("User selected a distribution list!");
                }

                sharedCalendar = oNS.GetSharedDefaultFolder(sharer, OlDefaultFolders.olFolderCalendar);
                if (sharedCalendar.DefaultItemType != OlItemType.olAppointmentItem)
                {
                    log.Debug(sharer.Name + " does not have a calendar shared.");
                    throw new System.Exception("Wrong default item type.");
                }
                calendarFolders.Add(sharer.Name, sharedCalendar);
                return(sharedCalendar);
            } catch (System.Exception ex) {
                log.Error("Failed to get shared calendar from " + sharedURI + ". " + ex.Message);
                MessageBox.Show("Could not find a shared calendar for '" + sharer.Name + "'.", "No shared calendar found",
                                MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return(null);
            } finally {
                sharer = (Recipient)OutlookCalendar.ReleaseObject(sharer);
            }
        }
        public void Disconnect(Boolean onlyWhenNoGUI = false)
        {
            if (!onlyWhenNoGUI ||
                (onlyWhenNoGUI && oApp.Explorers.Count == 0))
            {
                log.Debug("De-referencing all Outlook application objects.");
                try {
                    folders            = (Folders)OutlookCalendar.ReleaseObject(folders);
                    useOutlookCalendar = (MAPIFolder)OutlookCalendar.ReleaseObject(useOutlookCalendar);
                    for (int fld = calendarFolders.Count - 1; fld >= 0; fld--)
                    {
                        MAPIFolder mFld = calendarFolders.ElementAt(fld).Value;
                        mFld = (MAPIFolder)OutlookCalendar.ReleaseObject(mFld);
                        calendarFolders.Remove(calendarFolders.ElementAt(fld).Key);
                    }
                    calendarFolders = null;
                } catch (System.Exception ex) {
                    log.Debug(ex.Message);
                }

                log.Info("Disconnecting from Outlook application.");
                Marshal.FinalReleaseComObject(oApp);
                oApp = null;
                GC.Collect();
            }
        }
        public void GetAppointmentByID(String entryID, out AppointmentItem ai)
        {
            NameSpace ns = oApp.GetNamespace("mapi");

            ai = ns.GetItemFromID(entryID) as AppointmentItem;
            ns = (NameSpace)OutlookCalendar.ReleaseObject(ns);
        }
Beispiel #4
0
        public void BuildOutlookPattern(Event ev, AppointmentItem ai)
        {
            RecurrencePattern ignore;

            BuildOutlookPattern(ev, ai, out ignore);
            ignore = (RecurrencePattern)OutlookCalendar.ReleaseObject(ignore);
        }
Beispiel #5
0
        private static Boolean exceptionIsDeleted(Microsoft.Office.Interop.Outlook.Exception oExcp)
        {
            if (oExcp.Deleted)
            {
                return(true);
            }
            AppointmentItem ai = null;

            try {
                ai = oExcp.AppointmentItem;
                return(false);
            } catch (System.Exception ex) {
                if (ex.Message == "You changed one of the recurrences of this item, and this instance no longer exists. Close any open items and try again.")
                {
                    log.Warn("This Outlook recurrence instance has become inaccessible, probably due to caching");
                    return(true);
                }
                else
                {
                    log.Warn("Error when determining if Outlook recurrence is deleted or not.\r\n" + ex.Message);
                    return(true);
                }
            } finally {
                ai = (AppointmentItem)OutlookCalendar.ReleaseObject(ai);
            }
        }
Beispiel #6
0
        public void CompareOutlookPattern(Event ev, ref RecurrencePattern aiOpattern, SyncDirection syncDirection, System.Text.StringBuilder sb, ref int itemModified)
        {
            if (ev.Recurrence == null)
            {
                return;
            }

            log.Fine("Building a temporary recurrent Appointment generated from Event");
            AppointmentItem evAI = OutlookCalendar.Instance.IOutlook.UseOutlookCalendar().Items.Add() as AppointmentItem;

            evAI.Start = DateTime.Parse(ev.Start.Date ?? ev.Start.DateTime);

            RecurrencePattern evOpattern = null;

            try {
                buildOutlookPattern(ev, evAI, out evOpattern);
                log.Fine("Comparing Google recurrence to Outlook equivalent");

                if (MainForm.CompareAttribute("Recurrence Type", syncDirection,
                                              evOpattern.RecurrenceType.ToString(), aiOpattern.RecurrenceType.ToString(), sb, ref itemModified))
                {
                    aiOpattern.RecurrenceType = evOpattern.RecurrenceType;
                }
                if (MainForm.CompareAttribute("Recurrence Interval", syncDirection,
                                              evOpattern.Interval.ToString(), aiOpattern.Interval.ToString(), sb, ref itemModified))
                {
                    aiOpattern.Interval = evOpattern.Interval;
                }
                if (MainForm.CompareAttribute("Recurrence Instance", syncDirection,
                                              evOpattern.Instance.ToString(), aiOpattern.Instance.ToString(), sb, ref itemModified))
                {
                    aiOpattern.Instance = evOpattern.Instance;
                }
                if (MainForm.CompareAttribute("Recurrence DoW", syncDirection,
                                              evOpattern.DayOfWeekMask.ToString(), aiOpattern.DayOfWeekMask.ToString(), sb, ref itemModified))
                {
                    aiOpattern.DayOfWeekMask = evOpattern.DayOfWeekMask;
                }
                if (MainForm.CompareAttribute("Recurrence MoY", syncDirection,
                                              evOpattern.MonthOfYear.ToString(), aiOpattern.MonthOfYear.ToString(), sb, ref itemModified))
                {
                    aiOpattern.MonthOfYear = evOpattern.MonthOfYear;
                }
                if (MainForm.CompareAttribute("Recurrence NoEndDate", syncDirection,
                                              evOpattern.NoEndDate, aiOpattern.NoEndDate, sb, ref itemModified))
                {
                    aiOpattern.NoEndDate = evOpattern.NoEndDate;
                }
                if (MainForm.CompareAttribute("Recurrence Occurences", syncDirection,
                                              evOpattern.Occurrences.ToString(), aiOpattern.Occurrences.ToString(), sb, ref itemModified))
                {
                    aiOpattern.Occurrences = evOpattern.Occurrences;
                }
            } finally {
                evOpattern = (RecurrencePattern)OutlookCalendar.ReleaseObject(evOpattern);
                evAI.Delete();
                evAI = (AppointmentItem)OutlookCalendar.ReleaseObject(evAI);
            }
        }
Beispiel #7
0
        private void processOutlookExceptions(AppointmentItem ai, Event ev, Boolean forceCompare)
        {
            if (!HasExceptions(ev, checkLocalCacheOnly: true))
            {
                return;
            }

            if (!ai.Saved)
            {
                ai.Save();
            }

            RecurrencePattern oPattern = ai.GetRecurrencePattern();

            foreach (Event gExcp in Recurrence.Instance.googleExceptions.Where(exp => exp.RecurringEventId == ev.Id))
            {
                log.Fine("Found Google exception for " + (gExcp.OriginalStartTime.DateTime ?? gExcp.OriginalStartTime.Date));

                DateTime        oExcpDate = DateTime.Parse(gExcp.OriginalStartTime.DateTime ?? gExcp.OriginalStartTime.Date);
                AppointmentItem newAiExcp = getOutlookInstance(oPattern, oExcpDate);
                if (newAiExcp == null)
                {
                    continue;
                }

                if (gExcp.Status != "cancelled")
                {
                    int itemModified = 0;
                    newAiExcp = OutlookCalendar.Instance.UpdateCalendarEntry(newAiExcp, gExcp, ref itemModified, forceCompare);
                    if (itemModified > 0)
                    {
                        try {
                            newAiExcp.Save();
                        } catch (System.Exception ex) {
                            log.Warn(ex.Message);
                            if (ex.Message == "Cannot save this item.")
                            {
                                MainForm.Instance.Logboxout("Uh oh! Outlook wasn't able to save this recurrence exception! " +
                                                            "You may have two occurences on the same day, which it doesn't allow.");
                            }
                        }
                    }
                }
                else
                {
                    MainForm.Instance.Logboxout(OutlookCalendar.GetEventSummary(ai) + "\r\nDeleted.");
                    newAiExcp.Delete();
                }
                newAiExcp = (AppointmentItem)OutlookCalendar.ReleaseObject(newAiExcp);
            }
            if (!ai.Saved)
            {
                ai.Save();
            }
            oPattern = (RecurrencePattern)OutlookCalendar.ReleaseObject(oPattern);
        }
Beispiel #8
0
        private static void getOutlookInstance(RecurrencePattern oPattern, DateTime instanceDate, ref AppointmentItem ai)
        {
            //First check if this is not yet an exception
            try {
                ai = oPattern.GetOccurrence(instanceDate);
            } catch { }
            if (ai == null)
            {
                //The Outlook API is rubbish as the date argument is how it exists NOW (not OriginalDate).
                //If this has changed >1 in Google then there's no way of knowing what it might be!

                Exceptions oExcps = null;
                try {
                    oExcps = oPattern.Exceptions;
                    for (int e = 1; e <= oExcps.Count; e++)
                    {
                        Microsoft.Office.Interop.Outlook.Exception oExcp = null;
                        try {
                            oExcp = oExcps[e];
                            if (oExcp.OriginalDate.Date == instanceDate.Date)
                            {
                                try {
                                    log.Debug("Found Outlook exception for " + instanceDate);
                                    if (exceptionIsDeleted(oExcp))
                                    {
                                        log.Debug("This exception is deleted.");
                                        break;
                                    }
                                    else
                                    {
                                        ai = oExcp.AppointmentItem;
                                        break;
                                    }
                                } catch (System.Exception ex) {
                                    MainForm.Instance.Logboxout(ex.Message);
                                    MainForm.Instance.Logboxout("If this keeps happening, please restart OGCS.");
                                    break;
                                } finally {
                                    OutlookCalendar.ReleaseObject(oExcp);
                                }
                            }
                        } finally {
                            oExcp = (Microsoft.Office.Interop.Outlook.Exception)OutlookCalendar.ReleaseObject(oExcp);
                        }
                    }
                } finally {
                    oExcps = (Exceptions)OutlookCalendar.ReleaseObject(oExcps);
                }
                if (ai == null)
                {
                    log.Warn("Unable to find Outlook exception for " + instanceDate);
                }
            }
        }
Beispiel #9
0
 public void WindowsTimeZone_get(AppointmentItem ai, out String startTz, out String endTz)
 {
     Microsoft.Office.Interop.Outlook.TimeZone _startTz = null;
     Microsoft.Office.Interop.Outlook.TimeZone _endTz   = null;
     try {
         _startTz = ai.StartTimeZone;
         _endTz   = ai.EndTimeZone;
         startTz  = _startTz.ID;
         endTz    = _endTz.ID;
     } finally {
         _startTz = (Microsoft.Office.Interop.Outlook.TimeZone)OutlookCalendar.ReleaseObject(_startTz);
         _endTz   = (Microsoft.Office.Interop.Outlook.TimeZone)OutlookCalendar.ReleaseObject(_endTz);
     }
 }
Beispiel #10
0
        public static Boolean HasExceptions(AppointmentItem ai)
        {
            RecurrencePattern rp    = null;
            Exceptions        excps = null;

            try {
                rp    = ai.GetRecurrencePattern();
                excps = rp.Exceptions;
                return(excps.Count != 0);
            } finally {
                excps = (Exceptions)OutlookCalendar.ReleaseObject(excps);
                rp    = (RecurrencePattern)OutlookCalendar.ReleaseObject(rp);
            }
        }
        private void processOutlookExceptions(AppointmentItem ai, Event ev, Boolean forceCompare)
        {
            if (!HasExceptions(ev, checkLocalCacheOnly: true))
            {
                return;
            }

            if (!ai.Saved)
            {
                ai.Save();
            }

            RecurrencePattern oPattern = ai.GetRecurrencePattern();

            foreach (Event gExcp in Recurrence.Instance.googleExceptions.Where(exp => exp.RecurringEventId == ev.Id))
            {
                log.Fine("Found Google exception for " + (gExcp.OriginalStartTime.DateTime ?? gExcp.OriginalStartTime.Date));

                DateTime        oExcpDate = DateTime.Parse(gExcp.OriginalStartTime.DateTime ?? gExcp.OriginalStartTime.Date);
                AppointmentItem newAiExcp = getOutlookInstance(oPattern, oExcpDate);
                if (newAiExcp == null)
                {
                    continue;
                }

                if (gExcp.Status != "cancelled")
                {
                    int itemModified = 0;
                    newAiExcp = OutlookCalendar.Instance.UpdateCalendarEntry(newAiExcp, gExcp, ref itemModified, forceCompare);
                    if (itemModified > 0)
                    {
                        newAiExcp.Save();
                    }
                }
                else
                {
                    MainForm.Instance.Logboxout(OutlookCalendar.GetEventSummary(ai) + "\r\nDeleted.");
                    newAiExcp.Delete();
                }
                newAiExcp = (AppointmentItem)OutlookCalendar.ReleaseObject(newAiExcp);
            }
            if (!ai.Saved)
            {
                ai.Save();
            }
            oPattern = (RecurrencePattern)OutlookCalendar.ReleaseObject(oPattern);
        }
        public void CompareOutlookPattern(Event ev, AppointmentItem ai, System.Text.StringBuilder sb, ref int itemModified)
        {
            if (ev.Recurrence == null)
            {
                return;
            }

            log.Fine("Building a temporary recurrent Appointment generated from Event");
            AppointmentItem   evAI = OutlookCalendar.Instance.IOutlook.UseOutlookCalendar().Items.Add() as AppointmentItem;
            RecurrencePattern evOpattern;
            RecurrencePattern aiOpattern = ai.GetRecurrencePattern();

            BuildOutlookPattern(ev, evAI, out evOpattern);
            log.Fine("Comparing Google recurrence to Outlook equivalent");

            if (MainForm.CompareAttribute("Recurrence Type", Settings.Instance.SyncDirection,
                                          evOpattern.RecurrenceType.ToString(), aiOpattern.RecurrenceType.ToString(), sb, ref itemModified))
            {
                aiOpattern.RecurrenceType = evOpattern.RecurrenceType;
            }
            if (MainForm.CompareAttribute("Recurrence Interval", Settings.Instance.SyncDirection,
                                          evOpattern.Interval.ToString(), aiOpattern.Interval.ToString(), sb, ref itemModified))
            {
                aiOpattern.Interval = evOpattern.Interval;
            }
            if (MainForm.CompareAttribute("Recurrence Instance", Settings.Instance.SyncDirection,
                                          evOpattern.Instance.ToString(), aiOpattern.Instance.ToString(), sb, ref itemModified))
            {
                aiOpattern.Instance = evOpattern.Instance;
            }
            if (MainForm.CompareAttribute("Recurrence DoW", Settings.Instance.SyncDirection,
                                          evOpattern.DayOfWeekMask.ToString(), aiOpattern.DayOfWeekMask.ToString(), sb, ref itemModified))
            {
                aiOpattern.DayOfWeekMask = evOpattern.DayOfWeekMask;
            }
            if (MainForm.CompareAttribute("Recurrence MoY", Settings.Instance.SyncDirection,
                                          evOpattern.MonthOfYear.ToString(), aiOpattern.MonthOfYear.ToString(), sb, ref itemModified))
            {
                aiOpattern.MonthOfYear = evOpattern.MonthOfYear;
            }
            aiOpattern = (RecurrencePattern)OutlookCalendar.ReleaseObject(aiOpattern);
            evOpattern = (RecurrencePattern)OutlookCalendar.ReleaseObject(evOpattern);
            evAI       = (AppointmentItem)OutlookCalendar.ReleaseObject(evAI);
        }
Beispiel #13
0
        public List <String> BuildGooglePattern(AppointmentItem ai, Event ev)
        {
            if (!ai.IsRecurring || ai.RecurrenceState != OlRecurrenceState.olApptMaster)
            {
                return(null);
            }

            log.Debug("Creating Google iCalendar definition for recurring event.");
            List <String>     gPattern = new List <String>();
            RecurrencePattern rp       = null;

            try {
                rp = ai.GetRecurrencePattern();
                gPattern.Add("RRULE:" + buildRrule(rp));
            } finally {
                rp = (RecurrencePattern)OutlookCalendar.ReleaseObject(rp);
            }
            log.Debug(string.Join("\r\n", gPattern.ToArray()));
            return(gPattern);
        }
Beispiel #14
0
        private MAPIFolder getCalendarStore(NameSpace oNS)
        {
            MAPIFolder defaultCalendar = null;

            if (Settings.Instance.OutlookService == OutlookCalendar.Service.AlternativeMailbox && Settings.Instance.MailboxName != "")
            {
                log.Debug("Finding Alternative Mailbox calendar folders");
                Folders          binFolders = null;
                Store            binStore   = null;
                PropertyAccessor pa         = null;
                try {
                    binFolders = oNS.Folders;
                    binStore   = binFolders[Settings.Instance.MailboxName].Store;
                    pa         = binStore.PropertyAccessor;
                    object bin = pa.GetProperty(PR_IPM_WASTEBASKET_ENTRYID);
                    string excludeDeletedFolder = pa.BinaryToString(bin); //EntryID

                    MainForm.Instance.lOutlookCalendar.Text      = "Getting calendars";
                    MainForm.Instance.lOutlookCalendar.BackColor = System.Drawing.Color.Yellow;
                    findCalendars(oNS.Folders[Settings.Instance.MailboxName].Folders, calendarFolders, excludeDeletedFolder);
                    MainForm.Instance.lOutlookCalendar.BackColor = System.Drawing.Color.White;
                    MainForm.Instance.lOutlookCalendar.Text      = "Select calendar";
                } catch (System.Exception ex) {
                    log.Error("Failed to find calendar folders in alternate mailbox '" + Settings.Instance.MailboxName + "'.");
                    log.Debug(ex.Message);
                } finally {
                    pa         = (PropertyAccessor)OutlookCalendar.ReleaseObject(pa);
                    binStore   = (Store)OutlookCalendar.ReleaseObject(binStore);
                    binFolders = (Folders)OutlookCalendar.ReleaseObject(binFolders);
                }

                //Default to first calendar in drop down
                defaultCalendar = calendarFolders.FirstOrDefault().Value;
                if (defaultCalendar == null)
                {
                    log.Info("Could not find Alternative mailbox Calendar folder. Reverting to the default mailbox calendar.");
                    System.Windows.Forms.MessageBox.Show("Unable to find a Calendar folder in the alternative mailbox.\r\n" +
                                                         "Reverting to the default mailbox calendar", "Calendar not found", System.Windows.Forms.MessageBoxButtons.OK);
                    getDefaultCalendar(oNS, ref defaultCalendar);
                    MainForm.Instance.ddMailboxName.Text = "";
                }
            }
            else if (Settings.Instance.OutlookService == OutlookCalendar.Service.SharedCalendar)
            {
                log.Debug("Finding shared calendar");
                if (MainForm.Instance.Visible)
                {
                    SelectNamesDialog snd;
                    try {
                        snd = oNS.GetSelectNamesDialog();
                        snd.NumberOfRecipientSelectors = OlRecipientSelectors.olShowNone;
                        snd.ForceResolution            = true;
                        snd.AllowMultipleSelection     = false;
                        snd.Display();
                        if (snd.Recipients.Count == 0)
                        {
                            log.Info("No shared calendar selected.");
                            getDefaultCalendar(oNS, ref defaultCalendar);
                        }
                        else
                        {
                            String     sharedURI      = snd.Recipients[1].Address;
                            MAPIFolder sharedCalendar = getSharedCalendar(oNS, sharedURI);
                            if (sharedCalendar == null)
                            {
                                getDefaultCalendar(oNS, ref defaultCalendar);
                            }
                            else
                            {
                                Settings.Instance.SharedCalendar = sharedURI;
                                return(sharedCalendar);
                            }
                        }
                    } finally {
                        snd = null;
                    }
                }
                else
                {
                    defaultCalendar = getSharedCalendar(oNS, Settings.Instance.SharedCalendar);
                    if (defaultCalendar == null)
                    {
                        getDefaultCalendar(oNS, ref defaultCalendar);
                    }
                    else
                    {
                        return(defaultCalendar);
                    }
                }
            }
            else
            {
                getDefaultCalendar(oNS, ref defaultCalendar);
            }
            log.Debug("Default Calendar folder: " + defaultCalendar.Name);
            return(defaultCalendar);
        }
Beispiel #15
0
        public NameSpace GetCurrentUser(NameSpace oNS)
        {
            //We only need the current user details when syncing meeting attendees.
            //If GAL had previously been detected as blocked, let's always try one attempt to see if it's been opened up
            if (!Settings.Instance.OutlookGalBlocked && !Settings.Instance.AddAttendees)
            {
                return(oNS);
            }

            Boolean releaseNamespace = (oNS == null);

            if (releaseNamespace)
            {
                oNS = oApp.GetNamespace("mapi");
            }

            Recipient currentUser = null;

            try {
                DateTime triggerOOMsecurity = DateTime.Now;
                try {
                    currentUser = oNS.CurrentUser;
                    if (!MainForm.Instance.IsHandleCreated && (DateTime.Now - triggerOOMsecurity).TotalSeconds > 1)
                    {
                        log.Warn(">1s delay possibly due to Outlook security popup.");
                        OutlookCalendar.OOMsecurityInfo = true;
                    }
                } catch (System.Exception ex) {
                    OGCSexception.Analyse(ex);
                    if (Settings.Instance.OutlookGalBlocked)   //Fail fast
                    {
                        log.Debug("Corporate policy is still blocking access to GAL.");
                        return(oNS);
                    }
                    log.Warn("We seem to have a faux connection to Outlook! Forcing starting it with a system call :-/");
                    oNS = (NameSpace)OutlookCalendar.ReleaseObject(oNS);
                    Disconnect();
                    OutlookCalendar.AttachToOutlook(ref oApp, openOutlookOnFail: true, withSystemCall: true);
                    oNS = oApp.GetNamespace("mapi");

                    int maxDelay = 5;
                    int delay    = 1;
                    while (delay <= maxDelay)
                    {
                        log.Debug("Sleeping..." + delay + "/" + maxDelay);
                        System.Threading.Thread.Sleep(10000);
                        try {
                            currentUser = oNS.CurrentUser;
                            delay       = maxDelay;
                        } catch (System.Exception ex2) {
                            if (delay == maxDelay)
                            {
                                if (OGCSexception.GetErrorCode(ex2) == "0x80004004")   //E_ABORT
                                {
                                    log.Warn("Corporate policy or possibly anti-virus is blocking access to GAL.");
                                }
                                else
                                {
                                    OGCSexception.Analyse(ex2);
                                }
                                log.Warn("OGCS is unable to obtain CurrentUser from Outlook.");
                                Settings.Instance.OutlookGalBlocked = true;
                                return(oNS);
                            }
                            OGCSexception.Analyse(ex2);
                        }
                        delay++;
                    }
                }
                if (Settings.Instance.OutlookGalBlocked)
                {
                    log.Debug("GAL is no longer blocked!");
                }
                Settings.Instance.OutlookGalBlocked = false;
                currentUserSMTP = GetRecipientEmail(currentUser);
                currentUserName = currentUser.Name;
            } finally {
                currentUser = (Recipient)OutlookCalendar.ReleaseObject(currentUser);
                if (releaseNamespace)
                {
                    oNS = (NameSpace)OutlookCalendar.ReleaseObject(oNS);
                }
            }
            return(oNS);
        }
Beispiel #16
0
        public static void UpdateGoogleExceptions(AppointmentItem ai, Event ev)
        {
            if (ai.IsRecurring)
            {
                RecurrencePattern recurrence = ai.GetRecurrencePattern();
                try {
                    if (recurrence.Exceptions.Count > 0)
                    {
                        log.Debug(OutlookCalendar.GetEventSummary(ai));
                        log.Debug("This is a recurring appointment with " + recurrence.Exceptions.Count + " exceptions that will now be iteratively compared.");
                        foreach (Microsoft.Office.Interop.Outlook.Exception oExcp in recurrence.Exceptions)
                        {
                            int excp_itemModified = 0;

                            //Check the exception falls in the date range being synced
                            Boolean  oIsDeleted     = exceptionIsDeleted(oExcp);
                            String   logDeleted     = oIsDeleted ? " deleted and" : "";
                            DateTime oExcp_currDate = oIsDeleted ? oExcp.OriginalDate : oExcp.AppointmentItem.Start;
                            if (oExcp_currDate < Settings.Instance.SyncStart.Date || oExcp_currDate > Settings.Instance.SyncEnd.Date)
                            {
                                log.Fine("Exception is" + logDeleted + " outside date range being synced: " + oExcp_currDate.Date.ToString("dd/MM/yyyy"));
                                continue;
                            }

                            Event gExcp = Recurrence.Instance.GetGoogleInstance(oExcp, ev.RecurringEventId ?? ev.Id, OutlookCalendar.Instance.IOutlook.GetGlobalApptID(ai));
                            if (gExcp != null)
                            {
                                log.Debug("Matching Google Event recurrence found.");
                                if (gExcp.Status == "cancelled")
                                {
                                    log.Debug("It is deleted in Google, so cannot compare items.");
                                    if (!oIsDeleted)
                                    {
                                        log.Warn("Outlook is NOT deleted though - a mismatch has occurred somehow");
                                    }
                                    continue;
                                }
                                try {
                                    GoogleCalendar.Instance.UpdateCalendarEntry(oExcp.AppointmentItem, gExcp, ref excp_itemModified);
                                } catch (System.Exception ex) {
                                    if (oIsDeleted)
                                    {
                                        if (gExcp.Status != "cancelled")
                                        {
                                            gExcp.Status = "cancelled";
                                            excp_itemModified++;
                                        }
                                    }
                                    else
                                    {
                                        log.Error(ex.Message);
                                        log.Error(ex.StackTrace);
                                        throw ex;
                                    }
                                }
                                if (excp_itemModified > 0)
                                {
                                    try {
                                        GoogleCalendar.Instance.UpdateCalendarEntry_save(ref gExcp);
                                    } catch (System.Exception ex) {
                                        MainForm.Instance.Logboxout("WARNING: Updated event exception failed to save.\r\n" + ex.Message);
                                        log.Error(ex.StackTrace);
                                        if (MessageBox.Show("Updated Google event exception failed to save. Continue with synchronisation?", "Sync item failed", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                                        {
                                            continue;
                                        }
                                        else
                                        {
                                            throw new UserCancelledSyncException("User chose not to continue sync.");
                                        }
                                    }
                                }
                            }
                            else
                            {
                                log.Debug("No matching Google Event recurrence found.");
                                if (oIsDeleted)
                                {
                                    log.Debug("The Outlook appointment is deleted, so not a problem.");
                                }
                            }
                        }
                    }
                } finally {
                    recurrence = (RecurrencePattern)OutlookCalendar.ReleaseObject(recurrence);
                }
            }
        }
Beispiel #17
0
        public void Connect()
        {
            OutlookCalendar.AttachToOutlook(ref oApp, openOutlookOnFail: true, withSystemCall: false);
            log.Debug("Setting up Outlook connection.");

            // Get the NameSpace and Logon information.
            NameSpace oNS = null;

            try {
                oNS = oApp.GetNamespace("mapi");

                //Implicit logon to default profile, with no dialog box
                //If 1< profile, a dialogue is forced unless implicit login used
                exchangeConnectionMode = oNS.ExchangeConnectionMode;
                if (exchangeConnectionMode != OlExchangeConnectionMode.olNoExchange)
                {
                    log.Info("Exchange server version: Unknown");
                }
                log.Info("Exchange connection mode: " + exchangeConnectionMode.ToString());

                oNS = GetCurrentUser(oNS);

                if (!Settings.Instance.OutlookGalBlocked && currentUserName == "Unknown")
                {
                    log.Info("Current username is \"Unknown\"");
                    if (Settings.Instance.AddAttendees)
                    {
                        System.Windows.Forms.MessageBox.Show("It appears you do not have an Email Account configured in Outlook.\r\n" +
                                                             "You should set one up now (Tools > Email Accounts) to avoid problems syncing meeting attendees.",
                                                             "No Email Account Found", System.Windows.Forms.MessageBoxButtons.OK,
                                                             System.Windows.Forms.MessageBoxIcon.Warning);
                    }
                }

                log.Debug("Get the folders configured in Outlook");
                folders = oNS.Folders;

                // Get the Calendar folders
                useOutlookCalendar = getCalendarStore(oNS);
                if (MainForm.Instance.IsHandleCreated)
                {
                    log.Fine("Resetting connection, so re-selecting calendar from GUI dropdown");

                    MainForm.Instance.cbOutlookCalendars.SelectedIndexChanged -= MainForm.Instance.cbOutlookCalendar_SelectedIndexChanged;
                    MainForm.Instance.cbOutlookCalendars.DataSource            = new BindingSource(calendarFolders, null);

                    //Select the right calendar
                    int c = 0;
                    foreach (KeyValuePair <String, MAPIFolder> calendarFolder in calendarFolders)
                    {
                        if (calendarFolder.Value.EntryID == Settings.Instance.UseOutlookCalendar.Id)
                        {
                            MainForm.Instance.SetControlPropertyThreadSafe(MainForm.Instance.cbOutlookCalendars, "SelectedIndex", c);
                        }
                        c++;
                    }
                    if ((int)MainForm.Instance.GetControlPropertyThreadSafe(MainForm.Instance.cbOutlookCalendars, "SelectedIndex") == -1)
                    {
                        MainForm.Instance.SetControlPropertyThreadSafe(MainForm.Instance.cbOutlookCalendars, "SelectedIndex", 0);
                    }

                    KeyValuePair <String, MAPIFolder> calendar = (KeyValuePair <String, MAPIFolder>)MainForm.Instance.GetControlPropertyThreadSafe(MainForm.Instance.cbOutlookCalendars, "SelectedItem");
                    useOutlookCalendar = calendar.Value;

                    MainForm.Instance.cbOutlookCalendars.SelectedIndexChanged += MainForm.Instance.cbOutlookCalendar_SelectedIndexChanged;
                }
            } finally {
                // Done. Log off.
                if (oNS != null)
                {
                    oNS.Logoff();
                }
                oNS = (NameSpace)OutlookCalendar.ReleaseObject(oNS);
            }
        }
        public String GetRecipientEmail(Recipient recipient)
        {
            String  retEmail       = "";
            Boolean builtFakeEmail = false;

            log.Fine("Determining email of recipient: " + recipient.Name);
            AddressEntry addressEntry = null;

            try {
                try {
                    addressEntry = recipient.AddressEntry;
                } catch {
                    log.Warn("Can't resolve this recipient!");
                    addressEntry = null;
                }
                if (addressEntry == null)
                {
                    log.Warn("No AddressEntry exists!");
                    retEmail = EmailAddress.BuildFakeEmailAddress(recipient.Name, out builtFakeEmail);
                }
                else
                {
                    log.Fine("addressEntry Type: " + addressEntry.Type);
                    if (addressEntry.Type == "EX")   //Exchange
                    {
                        log.Fine("Address is from Exchange");
                        retEmail = ADX_GetSMTPAddress(addressEntry.Address);
                    }
                    else if (addressEntry.Type != null && addressEntry.Type.ToUpper() == "NOTES")
                    {
                        log.Fine("From Lotus Notes");
                        //Migrated contacts from notes, have weird "email addresses" eg: "James T. Kirk/US-Corp03/enterprise/US"
                        retEmail = EmailAddress.BuildFakeEmailAddress(recipient.Name, out builtFakeEmail);
                    }
                    else
                    {
                        log.Fine("Not from Exchange");
                        try {
                            if (string.IsNullOrEmpty(addressEntry.Address))
                            {
                                log.Warn("addressEntry.Address is empty.");
                                retEmail = EmailAddress.BuildFakeEmailAddress(recipient.Name, out builtFakeEmail);
                            }
                            else
                            {
                                retEmail = addressEntry.Address;
                            }
                        } catch (System.Exception ex) {
                            log.Error("Failed accessing addressEntry.Address");
                            log.Error(ex.Message);
                            retEmail = EmailAddress.BuildFakeEmailAddress(recipient.Name, out builtFakeEmail);
                        }
                    }
                }

                if (string.IsNullOrEmpty(retEmail) || retEmail == "Unknown")
                {
                    log.Error("Failed to get email address through Addin MAPI access!");
                    retEmail = EmailAddress.BuildFakeEmailAddress(recipient.Name, out builtFakeEmail);
                }

                if (retEmail != null && retEmail.IndexOf("<") > 0)
                {
                    retEmail = retEmail.Substring(retEmail.IndexOf("<") + 1);
                    retEmail = retEmail.TrimEnd(Convert.ToChar(">"));
                }
                log.Fine("Email address: " + retEmail, retEmail);
                if (!EmailAddress.IsValidEmail(retEmail) && !builtFakeEmail)
                {
                    retEmail = EmailAddress.BuildFakeEmailAddress(recipient.Name, out builtFakeEmail);
                    if (!EmailAddress.IsValidEmail(retEmail))
                    {
                        MainForm.Instance.Logboxout("ERROR: Recipient \"" + recipient.Name + "\" with email address \"" + retEmail + "\" is invalid.", notifyBubble: true);
                        MainForm.Instance.Logboxout("This must be manually resolved in order to sync this appointment.");
                        throw new ApplicationException("Invalid recipient email for \"" + recipient.Name + "\"");
                    }
                }
                return(retEmail);
            } finally {
                addressEntry = (AddressEntry)OutlookCalendar.ReleaseObject(addressEntry);
            }
        }
Beispiel #19
0
        private Event getGoogleInstance(ref Microsoft.Office.Interop.Outlook.Exception oExcp, String gRecurringEventID, String oEntryID, Boolean dirtyCache)
        {
            Boolean oIsDeleted = exceptionIsDeleted(oExcp);

            log.Debug("Finding Google instance for " + (oIsDeleted ? "deleted " : "") + "Outlook exception:-");
            log.Debug("  Original date: " + oExcp.OriginalDate.ToString("dd/MM/yyyy"));
            if (!oIsDeleted)
            {
                AppointmentItem ai = null;
                try {
                    ai = oExcp.AppointmentItem;
                    log.Debug("  Current  date: " + ai.Start.ToString("dd/MM/yyyy"));
                } finally {
                    ai = (AppointmentItem)OutlookCalendar.ReleaseObject(ai);
                }
            }
            if (dirtyCache)
            {
                log.Debug("Google exception cache not being used. Retrieving all recurring instances afresh...");
                //Remove dirty items
                googleExceptions.RemoveAll(ev => ev.RecurringEventId == gRecurringEventID);
            }
            else
            {
                foreach (Event gExcp in googleExceptions)
                {
                    if (gExcp.RecurringEventId == gRecurringEventID)
                    {
                        if ((!oIsDeleted &&
                             oExcp.OriginalDate == DateTime.Parse(gExcp.OriginalStartTime.Date ?? gExcp.OriginalStartTime.DateTime)
                             ) ||
                            (oIsDeleted &&
                             oExcp.OriginalDate == DateTime.Parse(gExcp.OriginalStartTime.Date ?? gExcp.OriginalStartTime.DateTime).Date
                            ))
                        {
                            return(gExcp);
                        }
                    }
                }
                log.Debug("Google exception event is not cached. Retrieving all recurring instances...");
            }
            List <Event> gInstances = GoogleCalendar.Instance.GetCalendarEntriesInRecurrence(gRecurringEventID);

            //Add any new exceptions to local cache
            googleExceptions = googleExceptions.Union(gInstances.Where(ev => !String.IsNullOrEmpty(ev.RecurringEventId))).ToList();
            foreach (Event gInst in gInstances)
            {
                if (gInst.RecurringEventId == gRecurringEventID)
                {
                    if (((!oIsDeleted || (oIsDeleted && !oExcp.Deleted)) && /* Weirdness when exception is cancelled by organiser but not yet deleted/accepted by recipient */
                         oExcp.OriginalDate == DateTime.Parse(gInst.OriginalStartTime.Date ?? gInst.OriginalStartTime.DateTime)
                         ) ||
                        (oIsDeleted &&
                         oExcp.OriginalDate == DateTime.Parse(gInst.OriginalStartTime.Date ?? gInst.OriginalStartTime.DateTime).Date
                        ))
                    {
                        return(gInst);
                    }
                }
            }
            return(null);
        }
        public void Connect()
        {
            OutlookCalendar.AttachToOutlook(ref oApp);
            log.Debug("Setting up Outlook connection.");

            // Get the NameSpace and Logon information.
            NameSpace oNS = null;

            try {
                oNS = oApp.GetNamespace("mapi");

                //Implicit logon to default profile, with no dialog box
                //If 1< profile, a dialogue is forced unless implicit login used
                exchangeConnectionMode = oNS.ExchangeConnectionMode;
                if (exchangeConnectionMode != OlExchangeConnectionMode.olNoExchange)
                {
                    log.Info("Exchange server version: Unknown");
                }
                log.Info("Exchange connection mode: " + exchangeConnectionMode.ToString());

                Recipient currentUser = null;
                try {
                    try {
                        currentUser = oNS.CurrentUser;
                    } catch {
                        log.Warn("We seem to have a faux connection to Outlook! Forcing starting it with a system call :-/");
                        oNS = (NameSpace)OutlookCalendar.ReleaseObject(oNS);
                        Disconnect();
                        OutlookCalendar.AttachToOutlook(ref oApp, openOutlookOnFail: true, withSystemCall: true);
                        oNS         = oApp.GetNamespace("mapi");
                        currentUser = oNS.CurrentUser;
                    }
                    currentUserSMTP = GetRecipientEmail(currentUser);
                    currentUserName = currentUser.Name;
                } finally {
                    currentUser = (Recipient)OutlookCalendar.ReleaseObject(currentUser);
                }

                if (currentUserName == "Unknown")
                {
                    log.Info("Current username is \"Unknown\"");
                    if (Settings.Instance.AddAttendees)
                    {
                        System.Windows.Forms.MessageBox.Show("It appears you do not have an Email Account configured in Outlook.\r\n" +
                                                             "You should set one up now (Tools > Email Accounts) to avoid problems syncing meeting attendees.",
                                                             "No Email Account Found", System.Windows.Forms.MessageBoxButtons.OK,
                                                             System.Windows.Forms.MessageBoxIcon.Warning);
                    }
                }

                //Get the folders configured in Outlook
                folders = oNS.Folders;

                // Get the Calendar folders
                useOutlookCalendar = getCalendarStore(oNS);
                if (MainForm.Instance.IsHandleCreated)   //resetting connection, so pick up selected calendar from GUI dropdown
                {
                    MainForm.Instance.cbOutlookCalendars.DataSource = new BindingSource(calendarFolders, null);
                    KeyValuePair <String, MAPIFolder> calendar = (KeyValuePair <String, MAPIFolder>)MainForm.Instance.cbOutlookCalendars.SelectedItem;
                    calendar           = (KeyValuePair <String, MAPIFolder>)MainForm.Instance.cbOutlookCalendars.SelectedItem;
                    useOutlookCalendar = calendar.Value;
                }
            } finally {
                // Done. Log off.
                oNS.Logoff();
                oNS = (NameSpace)OutlookCalendar.ReleaseObject(oNS);
            }
        }
Beispiel #21
0
        public static void CreateGoogleExceptions(AppointmentItem ai, String recurringEventId)
        {
            if (!ai.IsRecurring)
            {
                return;
            }

            log.Debug("Creating Google recurrence exceptions.");
            List <Event> gRecurrences = GoogleCalendar.Instance.GetCalendarEntriesInRecurrence(recurringEventId);

            if (gRecurrences != null)
            {
                RecurrencePattern rp    = null;
                Exceptions        excps = null;
                try {
                    rp    = ai.GetRecurrencePattern();
                    excps = rp.Exceptions;
                    for (int e = 1; e <= excps.Count; e++)
                    {
                        Microsoft.Office.Interop.Outlook.Exception oExcp = null;
                        try {
                            oExcp = excps[e];
                            for (int g = 0; g < gRecurrences.Count; g++)
                            {
                                Event   ev        = gRecurrences[g];
                                String  gDate     = ev.OriginalStartTime.DateTime ?? ev.OriginalStartTime.Date;
                                Boolean isDeleted = exceptionIsDeleted(oExcp);
                                if (isDeleted && !ai.AllDayEvent)   //Deleted items get truncated?!
                                {
                                    gDate = GoogleCalendar.GoogleTimeFrom(DateTime.Parse(gDate).Date);
                                }
                                if (oExcp.OriginalDate == DateTime.Parse(gDate))
                                {
                                    if (isDeleted)
                                    {
                                        MainForm.Instance.Logboxout(GoogleCalendar.GetEventSummary(ev));
                                        MainForm.Instance.Logboxout("Recurrence deleted.");
                                        ev.Status = "cancelled";
                                        GoogleCalendar.Instance.UpdateCalendarEntry_save(ref ev);
                                    }
                                    else
                                    {
                                        int   exceptionItemsModified = 0;
                                        Event modifiedEv             = GoogleCalendar.Instance.UpdateCalendarEntry(oExcp.AppointmentItem, ev, ref exceptionItemsModified, forceCompare: true);
                                        if (exceptionItemsModified > 0)
                                        {
                                            GoogleCalendar.Instance.UpdateCalendarEntry_save(ref modifiedEv);
                                        }
                                    }
                                    break;
                                }
                            }
                        } finally {
                            oExcp = (Microsoft.Office.Interop.Outlook.Exception)OutlookCalendar.ReleaseObject(oExcp);
                        }
                    }
                } finally {
                    excps = (Exceptions)OutlookCalendar.ReleaseObject(excps);
                    rp    = (RecurrencePattern)OutlookCalendar.ReleaseObject(rp);
                }
            }
        }
Beispiel #22
0
        public void Connect()
        {
            OutlookCalendar.AttachToOutlook(ref oApp, openOutlookOnFail: true, withSystemCall: false);
            log.Debug("Setting up Outlook connection.");

            // Get the NameSpace and Logon information.
            NameSpace oNS = null;

            try {
                oNS = oApp.GetNamespace("mapi");

                //Log on by using a dialog box to choose the profile.
                //oNS.Logon("", Type.Missing, true, true);

                //Implicit logon to default profile, with no dialog box
                //If 1< profile, a dialogue is forced unless implicit login used
                exchangeConnectionMode = oNS.ExchangeConnectionMode;
                if (exchangeConnectionMode != OlExchangeConnectionMode.olNoExchange)
                {
                    log.Info("Exchange server version: " + oNS.ExchangeMailboxServerVersion.ToString());
                }

                //Logon using a specific profile. Can't see a use case for this when using OGsync
                //If using this logon method, change the profile name to an appropriate value:
                //HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles
                //oNS.Logon("YourValidProfile", Type.Missing, false, true);

                log.Info("Exchange connection mode: " + exchangeConnectionMode.ToString());

                Recipient currentUser = null;
                try {
                    try {
                        currentUser = oNS.CurrentUser;
                    } catch {
                        log.Warn("We seem to have a faux connection to Outlook! Forcing starting it with a system call :-/");
                        oNS = (NameSpace)OutlookCalendar.ReleaseObject(oNS);
                        Disconnect();
                        OutlookCalendar.AttachToOutlook(ref oApp, openOutlookOnFail: true, withSystemCall: true);
                        oNS         = oApp.GetNamespace("mapi");
                        currentUser = oNS.CurrentUser;
                    }

                    //Issue 402
                    log.Debug("Getting active window inspector");
                    Inspector inspector = oApp.ActiveInspector();
                    inspector = (Inspector)OutlookCalendar.ReleaseObject(inspector);
                    log.Debug("Done.");
                    currentUserSMTP = GetRecipientEmail(currentUser);
                    currentUserName = currentUser.Name;
                } finally {
                    currentUser = (Recipient)OutlookCalendar.ReleaseObject(currentUser);
                }

                if (currentUserName == "Unknown")
                {
                    log.Info("Current username is \"Unknown\"");
                    if (Settings.Instance.AddAttendees)
                    {
                        System.Windows.Forms.MessageBox.Show("It appears you do not have an Email Account configured in Outlook.\r\n" +
                                                             "You should set one up now (Tools > Email Accounts) to avoid problems syncing meeting attendees.",
                                                             "No Email Account Found", System.Windows.Forms.MessageBoxButtons.OK,
                                                             System.Windows.Forms.MessageBoxIcon.Warning);
                    }
                }

                //Get the folders configured in Outlook
                folders = oNS.Folders;

                // Get the Calendar folders
                useOutlookCalendar = getCalendarStore(oNS);
                if (MainForm.Instance.IsHandleCreated)
                {
                    log.Fine("Resetting connection, so re-selecting calendar from GUI dropdown");

                    MainForm.Instance.cbOutlookCalendars.SelectedIndexChanged -= MainForm.Instance.cbOutlookCalendar_SelectedIndexChanged;
                    MainForm.Instance.cbOutlookCalendars.DataSource            = new BindingSource(calendarFolders, null);

                    //Select the right calendar
                    int c = 0;
                    foreach (KeyValuePair <String, MAPIFolder> calendarFolder in calendarFolders)
                    {
                        if (calendarFolder.Value.EntryID == Settings.Instance.UseOutlookCalendar.Id)
                        {
                            MainForm.Instance.SetControlPropertyThreadSafe(MainForm.Instance.cbOutlookCalendars, "SelectedIndex", c);
                        }
                        c++;
                    }
                    if ((int)MainForm.Instance.GetControlPropertyThreadSafe(MainForm.Instance.cbOutlookCalendars, "SelectedIndex") == -1)
                    {
                        MainForm.Instance.SetControlPropertyThreadSafe(MainForm.Instance.cbOutlookCalendars, "SelectedIndex", 0);
                    }

                    KeyValuePair <String, MAPIFolder> calendar = (KeyValuePair <String, MAPIFolder>)MainForm.Instance.GetControlPropertyThreadSafe(MainForm.Instance.cbOutlookCalendars, "SelectedItem");
                    useOutlookCalendar = calendar.Value;

                    MainForm.Instance.cbOutlookCalendars.SelectedIndexChanged += MainForm.Instance.cbOutlookCalendar_SelectedIndexChanged;
                }
            } finally {
                // Done. Log off.
                oNS.Logoff();
                oNS = (NameSpace)OutlookCalendar.ReleaseObject(oNS);
            }
        }
Beispiel #23
0
        public String GetRecipientEmail(Recipient recipient)
        {
            String  retEmail       = "";
            Boolean builtFakeEmail = false;

            log.Fine("Determining email of recipient: " + recipient.Name);
            AddressEntry addressEntry     = null;
            String       addressEntryType = "";

            try {
                try {
                    addressEntry = recipient.AddressEntry;
                } catch {
                    log.Warn("Can't resolve this recipient!");
                    addressEntry = null;
                }
                if (addressEntry == null)
                {
                    log.Warn("No AddressEntry exists!");
                    retEmail = EmailAddress.BuildFakeEmailAddress(recipient.Name, out builtFakeEmail);
                }
                else
                {
                    try {
                        addressEntryType = addressEntry.Type;
                    } catch {
                        log.Warn("Cannot access addressEntry.Type!");
                    }
                    log.Fine("AddressEntry Type: " + addressEntryType);
                    if (addressEntryType == "EX")   //Exchange
                    {
                        log.Fine("Address is from Exchange");
                        if (addressEntry.AddressEntryUserType == OlAddressEntryUserType.olExchangeUserAddressEntry ||
                            addressEntry.AddressEntryUserType == OlAddressEntryUserType.olExchangeRemoteUserAddressEntry)
                        {
                            ExchangeUser eu = null;
                            try {
                                eu = addressEntry.GetExchangeUser();
                                if (eu != null && eu.PrimarySmtpAddress != null)
                                {
                                    retEmail = eu.PrimarySmtpAddress;
                                }
                                else
                                {
                                    log.Warn("Exchange does not have an email for recipient: " + recipient.Name);
                                    Microsoft.Office.Interop.Outlook.PropertyAccessor pa = null;
                                    try {
                                        //Should I try PR_EMS_AB_PROXY_ADDRESSES next to cater for cached mode?
                                        pa       = recipient.PropertyAccessor;
                                        retEmail = pa.GetProperty(OutlookNew.PR_SMTP_ADDRESS).ToString();
                                        log.Debug("Retrieved from PropertyAccessor instead.");
                                    } catch {
                                        log.Warn("Also failed to retrieve email from PropertyAccessor.");
                                        retEmail = EmailAddress.BuildFakeEmailAddress(recipient.Name, out builtFakeEmail);
                                    } finally {
                                        pa = (Microsoft.Office.Interop.Outlook.PropertyAccessor)OutlookCalendar.ReleaseObject(pa);
                                    }
                                }
                            } finally {
                                eu = (ExchangeUser)OutlookCalendar.ReleaseObject(eu);
                            }
                        }
                        else if (addressEntry.AddressEntryUserType == OlAddressEntryUserType.olOutlookContactAddressEntry)
                        {
                            log.Fine("This is an Outlook contact");
                            ContactItem contact = null;
                            try {
                                try {
                                    contact = addressEntry.GetContact();
                                } catch {
                                    log.Warn("Doesn't seem to be a valid contact object. Maybe this account is no longer in Exchange.");
                                    retEmail = EmailAddress.BuildFakeEmailAddress(recipient.Name, out builtFakeEmail);
                                }
                                if (contact != null)
                                {
                                    if (contact.Email1AddressType == "EX")
                                    {
                                        log.Fine("Address is from Exchange.");
                                        log.Fine("Using PropertyAccessor to get email address.");
                                        Microsoft.Office.Interop.Outlook.PropertyAccessor pa = null;
                                        try {
                                            pa       = contact.PropertyAccessor;
                                            retEmail = pa.GetProperty(EMAIL1ADDRESS).ToString();
                                        } finally {
                                            pa = (Microsoft.Office.Interop.Outlook.PropertyAccessor)OutlookCalendar.ReleaseObject(pa);
                                        }
                                    }
                                    else
                                    {
                                        retEmail = contact.Email1Address;
                                    }
                                }
                            } finally {
                                contact = (ContactItem)OutlookCalendar.ReleaseObject(contact);
                            }
                        }
                        else
                        {
                            log.Fine("Exchange type: " + addressEntry.AddressEntryUserType.ToString());
                            log.Fine("Using PropertyAccessor to get email address.");
                            Microsoft.Office.Interop.Outlook.PropertyAccessor pa = null;
                            try {
                                pa       = recipient.PropertyAccessor;
                                retEmail = pa.GetProperty(OutlookNew.PR_SMTP_ADDRESS).ToString();
                            } finally {
                                pa = (Microsoft.Office.Interop.Outlook.PropertyAccessor)OutlookCalendar.ReleaseObject(pa);
                            }
                        }
                    }
                    else if (addressEntryType.ToUpper() == "NOTES")
                    {
                        log.Fine("From Lotus Notes");
                        //Migrated contacts from notes, have weird "email addresses" eg: "James T. Kirk/US-Corp03/enterprise/US"
                        retEmail = EmailAddress.BuildFakeEmailAddress(recipient.Name, out builtFakeEmail);
                    }
                    else
                    {
                        log.Fine("Not from Exchange");
                        try {
                            if (string.IsNullOrEmpty(addressEntry.Address))
                            {
                                log.Warn("addressEntry.Address is empty.");
                                retEmail = EmailAddress.BuildFakeEmailAddress(recipient.Name, out builtFakeEmail);
                            }
                            else
                            {
                                retEmail = addressEntry.Address;
                            }
                        } catch (System.Exception ex) {
                            log.Error("Failed accessing addressEntry.Address");
                            log.Error(ex.Message);
                            retEmail = EmailAddress.BuildFakeEmailAddress(recipient.Name, out builtFakeEmail);
                        }
                    }
                }

                if (retEmail != null && retEmail.IndexOf("<") > 0)
                {
                    retEmail = retEmail.Substring(retEmail.IndexOf("<") + 1);
                    retEmail = retEmail.TrimEnd(Convert.ToChar(">"));
                }
                log.Fine("Email address: " + retEmail, retEmail);
                if (!EmailAddress.IsValidEmail(retEmail) && !builtFakeEmail)
                {
                    retEmail = EmailAddress.BuildFakeEmailAddress(recipient.Name, out builtFakeEmail);
                    if (!EmailAddress.IsValidEmail(retEmail))
                    {
                        MainForm.Instance.Logboxout("ERROR: Recipient \"" + recipient.Name + "\" with email address \"" + retEmail + "\" is invalid.", notifyBubble: true);
                        MainForm.Instance.Logboxout("This must be manually resolved in order to sync this appointment.");
                        throw new ApplicationException("Invalid recipient email for \"" + recipient.Name + "\"");
                    }
                }
                return(retEmail);
            } finally {
                addressEntry = (AddressEntry)OutlookCalendar.ReleaseObject(addressEntry);
            }
        }