Outlookgooglecalendarsync: Corporate policy blocking access to Outlook address book

Created on 5 Aug 2017  路  26Comments  路  Source: phw198/OutlookGoogleCalendarSync

Issue: OGCS fails with the message "OGCS is unable to communicate with Outlook, possibly due to anti-virus or corporate policies."

Enhancement/Workaround: Provide a code path that doesn't require address book access, with the following impact:

  • Meeting recipients cannot be synced
  • Description/body of appointmentments cannot be synced
  • Calendars shared by others cannot be synced

:+1: Please post a +1 reaction to this issue if you would like to see OGCS support this.

Actions:

  • [x] Review code implications
  • [x] Confirm if manual entry of username and email will be required
  • [x] Begin coding
  • [x] Post development builds here for willing users to test
  • [x] Merge into main application
enhancement resolved

Most helpful comment

I'm super excited to say that your code already works! @phw198, and you were 99% on your way to solve this issue
The exception was caused by calling Add() on a null Dictionary object (calendarFolders) at line 338.
I just added an initialization statement before that call:
calendarFolders = new Dictionary<string, MAPIFolder>();
And that was it! The application can launch and I could see my Outlook calendar in the list.

I was getting another exception when trying to sync:
ex = {"Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT))"}
StackTrace:
at Microsoft.Office.Interop.Outlook._AppointmentItem.get_Body()\r\n at OutlookGoogleCalendarSync.GoogleCalendar.createCalendarEntry(AppointmentItem ai)

This is probably caused by corporate policy forbidding access to event bodies which may contain sensitive information such as meeting agendas and so on. By examining the code, it appears there's already an option to exclude event description, so once I switched that off in the Settings UI, everything was completed successfully with zero errors or warnings.
The only thing remaining is the 10 second delay (with 5 attempts) when starting the app, and the blocking exception at startup (which is still there in the production code). I believe it's no longer necessary, at least for this particular use-case.
I won't create a pull-request since I only added a single line! And there's probably a better place to instantiate the Dictionary anyway, so I'll leave that to you :)

So thank you so much @phw198 for your assistance, and for this wonderful piece of software. I appreciate all the effort you've put into it.

Have a great weekend!

All 26 comments

When will it be ready?

To get the ball rolling, could you try this first patch and see how far OGCS gets opening. Please post your OGcalsync.log file once tested.

:package: v2.5.3.1.zip [see instructions for applying].

I have the same issue. Now with the hotfix I get "Object reference not set to an instance of an object"

Same error as above with the hotfix.
[OGcalsync.log.zip]

Thanks @gfxonline.

:package: v2.5.3.2.zip This is just a build with extra logging as I can't be sure where it's now failing. Please upload your logfile again once you've run it.

Thank you for the speedy investigation! :)
Here's the new logfile:
[OGcalsync.txt]

Here's mine. I just changed my username to USERNAME for privacy concerns:

OGcalsync.txt

Thanks guys, I now know where it's failing but unfortunately it is where it tries to retrieve the default calendar folder - but nothing is returned. I'm getting a slight sinking feeling that everything is so locked down OGCS just isn't going to get very far... :cry:

:package: Anyway, give v2.5.3.4.zip a go and let's see where you get to.

No luck. Thanks for trying so hard.
OGcalsync.txt

Same here 馃槩
[OGcalsync.txt]

I'm thinking about a workaround where we manually export a .ics file from Outlook and import it into the application to do the proper merging based on diff data.

All I really need is to see the free/busy slots when I'm outside the office. I don't want to carry an additional corporate phone just to access my calendar! And the app they have for smartphones refuses to work on rooted Android, so I can't use my personal phone.
It's like they're literally forcing us to bypass all their security guards just to get the bare minimum functionality..

:package: OK, so a last ditch attempt here with v2.5.3.5.zip.

Also, does it make any difference if you run OGCS (and Outlook) with elevated privileges (right click and "Run as Administrator")?

Note: If you're trying this hotfix after the release of v2.6.0, please don't accept the upgrade (unless you are finished with testing this hotfix)!

Still no luck. However I got a different "timeout" error when I start either Outlook or OGCS as admin.
Log file contains all 4 permutations of Outlook and/or OGCS running as admin.
Thank you for trying to fix this.
[OGcalsync.txt]

Thanks for your efforts @gfxonline, but no :game_die:

It appears that as soon as I try and add the default calendar object to the dictionary object, the calendar object suddenly becomes "unavailable" - which is strange because directly before the this, v2.5.3.5 is able to log it's name and the fact it is a COM object!!

So it seems that my hope that OGCS wasn't working, purely because corporate IT might lock down access to the Outlook address book, isn't the full picture. I don't like admitting defeat, but in this case I don't see any workaround :disappointed:


For posterity (and if anyone wants to take this further), here is the code that produced your log file:
```c#
private Dictionary calendarFolders = new Dictionary();
...
defaultCalendar = oNS.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
if (defaultCalendar == null)
log.Debug("defaultCalendar = null");
else {
try { log.Debug("defaultCalendar = " + defaultCalendar.ToString()); }
catch (System.Exception ex) { log.Error("defaultCalendar: " + ex.Message); }
}
try {
log.Debug("defaultCalendar.Name = " + defaultCalendar.Name);
} catch (System.Exception ex) {
log.Error("defaultCalendar.Name: " + ex.Message);
}

if (defaultCalendar == null) {
log.Warn("No default calendar folder was found!");
} else {
log.Debug("Adding default calendar folder to dropdown");
try {
calendarFolders.Add("Default " + defaultCalendar.Name, defaultCalendar);
} catch (System.Exception ex) {
log.Error("Failed adding default calendar. " + ex.Message);
calendarFolders.Add("Default " + defaultCalendar.Name ?? "Calendar", defaultCalendar);
}
}
log.Debug("Setting excludeDeletedFolder");

The log output is:

2017-08-14 10:06:49,526 DEBUG 1 OutlookGoogleCalendarSync.OutlookNew [0] - Get the folders configured in Outlook
2017-08-14 10:06:49,538 DEBUG 1 OutlookGoogleCalendarSync.OutlookNew [0] - Finding default Mailbox calendar folders
2017-08-14 10:06:49,538 DEBUG 1 OutlookGoogleCalendarSync.OutlookNew [0] - Getting default calendar folder
2017-08-14 10:06:49,543 DEBUG 1 OutlookGoogleCalendarSync.OutlookNew [0] - defaultCalendar = System.__ComObject
2017-08-14 10:06:49,544 DEBUG 1 OutlookGoogleCalendarSync.OutlookNew [0] - defaultCalendar.Name = Calendar
2017-08-14 10:06:49,544 DEBUG 1 OutlookGoogleCalendarSync.OutlookNew [0] - Adding default calendar folder to dropdown
2017-08-14 10:06:49,545 ERROR 1 OutlookGoogleCalendarSync.OutlookNew [0] - Failed adding default calendar. Object reference not set to an instance of an object.
2017-08-14 10:06:49,546 ERROR 1 OutlookGoogleCalendarSync.OGCSexception [0] - System.NullReferenceException: Object reference not set to an instance of an object.
2017-08-14 10:06:49,546 ERROR 1 OutlookGoogleCalendarSync.OGCSexception [0] - Code: 0x80004003;-2147467261
2017-08-14 10:06:49,546 ERROR 1 OutlookGoogleCalendarSync.OGCSexception [0] - at OutlookGoogleCalendarSync.OutlookNew.getDefaultCalendar(NameSpace oNS, MAPIFolder& defaultCalendar)
2017-08-14 10:06:49,550 ERROR 1 OutlookGoogleCalendarSync.OGCSexception [0] - System.NullReferenceException: Object reference not set to an instance of an object.
2017-08-14 10:06:49,550 ERROR 1 OutlookGoogleCalendarSync.OGCSexception [0] - Code: 0x80004003;-2147467261
```

This is the specific line that fails in the production code.

@phw198 Thanks for the detailed analysis.
This does sound strange, so I'm contemplating forking the code and debugging in run-time to see how and why this is happening. I'm not sure how much time I can put into this, because I need to do it from the office, but it's worth a shot I guess.
I will keep you updated and create a pull-request IF I ever find a solution.
Cheers :)

@gfxonline Here's the full OutlookNew.cs file if you want to use that as a starter. Good luck - would be great if you _can_ find a solution!

I'm super excited to say that your code already works! @phw198, and you were 99% on your way to solve this issue
The exception was caused by calling Add() on a null Dictionary object (calendarFolders) at line 338.
I just added an initialization statement before that call:
calendarFolders = new Dictionary<string, MAPIFolder>();
And that was it! The application can launch and I could see my Outlook calendar in the list.

I was getting another exception when trying to sync:
ex = {"Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT))"}
StackTrace:
at Microsoft.Office.Interop.Outlook._AppointmentItem.get_Body()\r\n at OutlookGoogleCalendarSync.GoogleCalendar.createCalendarEntry(AppointmentItem ai)

This is probably caused by corporate policy forbidding access to event bodies which may contain sensitive information such as meeting agendas and so on. By examining the code, it appears there's already an option to exclude event description, so once I switched that off in the Settings UI, everything was completed successfully with zero errors or warnings.
The only thing remaining is the 10 second delay (with 5 attempts) when starting the app, and the blocking exception at startup (which is still there in the production code). I believe it's no longer necessary, at least for this particular use-case.
I won't create a pull-request since I only added a single line! And there's probably a better place to instantiate the Dictionary anyway, so I'll leave that to you :)

So thank you so much @phw198 for your assistance, and for this wonderful piece of software. I appreciate all the effort you've put into it.

Have a great weekend!

Ah, you genius @gfxonline! It always the simple things that catch people out :roll_eyes:

To my chagrin, I now see why I didn't spot this - the calendarFolders only gets set to null when the Disconnect() function is called, which happens after your 5 failed attempts to connect. Because I wasn't able to replicate those fails, Disconnect() wasn't getting called for me!

So we're back in play and it sounds like only syncing of recipients and description fall casualty to corporate lockdown - that's not too bad. I'll see if I can get another hotfix out over the weekend...

Yeah it's always those little unexpected things :)
The absence of recipients and description data is an acceptable compromise for my own use-case. I just wanted the ability to see my free/busy time on my personal phone outside the office.

I'd be happy to assist in future issues related to corporate restrictions since I can debug in a similar environment, just drop me a PM when needed.

鈽笍

:package: Please give hotfix v2.5.3.6.zip a go [see instructions for applying].

This has actually prompted a big win for everyone - the GAL is now only accessed on startup if users want to sync meeting attendees. This should greatly reduce the number of people that see the Outlook security pop-up :balloon:

Amazing work guys! It now works for me and doesn't prompt for security on startup which is also amazing!

There is a new (or related error now). When I click on "Shared Calendar" under the "Outlook" pane (which I never used previously), there is now an unhandled exception: Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT)).

Let me know if you would like my logs. If it is a new issue I can submit a new github bug.

@mherberg Thanks for testing so quickly! I suspect syncing someone else's shared calendar is going to be another feature that will have to be removed. At what point did it fail? Did your address book pop up from which to select someone, or was it later the error occurred?

@gfxonline This might be one I could do with you to confirm where it dies. I suspect any of these lines might cause problems:
In getCalendarStore()

snd = oNS.GetSelectNamesDialog();
String sharedURI = snd.Recipients[1].Address;

In getSharedCalendar()

sharer = oNS.CreateRecipient(sharedURI);
sharer.Resolve();
sharedCalendar = oNS.GetSharedDefaultFolder(sharer, OlDefaultFolders.olFolderCalendar);

Might be worth seeing if hard-coding the shared calendar's email address in getCalendarStore() makes the rest work?

Hi all,
I can confirm that the hotfix works for calendar sync issues.

I've tried the "Shared Calendar" option, and the code crashes at:
snd = oNS.GetSelectNamesDialog();
When I hardcode the email address in sharedURI, the app crashes with E_ABORT at:
sharer.Resolve();
I believe it's the same restriction as the one we had earlier. Apparently the policy forces Outlook to block access to the address book, so any attempts to access it for whatever purpose would probably fail. But that's just my guess, and the documentation over at MSDN doesn't really cover COM object exceptions so I couldn't find a concrete explanation.

Let me know if I can help further.

Working great. Small issue. Entries are syncing from OL to GC then on the next sync below error. Happens with "merge with existing entries" checked or unchecked.

INFO 9 OutlookGoogleCalendarSync.MainForm [0] - Comparing 16 existing Google calendar entries...
DEBUG 9 OutlookGoogleCalendarSync.GoogleCalendar [0] - Processing >> 8/31/2017 11:00 => " XXXXX"
INFO 9 OutlookGoogleCalendarSync.MainForm [0] - 8/31/2017 11:00 => "XXXXX"
INFO 9 OutlookGoogleCalendarSync.MainForm [0] - WARNING: Event update failed.
Operation aborted (Exception from HRESULT: 0x80004004 (E_ABORT))

@gfxonline Thanks for checking it out - suspected it would have to go, so will remove this functionality as well.

@lsu2010 Did you ever have two way sync, or synced items in to Outlook, before your company locked things down? Would be helpful to see more of the log if you can send over a redacted copy.

Whatever needed so I don't have to set exchange account on my phone and have my company manage my phone!

Changes for this enhancement have now been rolled in to v2.6.1. Thanks to @gfxonline especially for helping along the way!

@lsu2010 If you're still encountering the error you reported, could you raise a new issue for it please.

Was this page helpful?
0 / 5 - 0 ratings