C# - Office Automation : Outlook Security Message
October 29, 2010 by
Christoff Truter
C#
Microsoft Office
If you've ever worked with office automation/integration (e.g. COM objects) and
outlook, chances are that you've had a run in with its "object model
guard".
This is a feature that Microsoft introduced (via Patch) since Office 98/2000 in order to secure Outlook
(against exploitation etc), observe the following snippet:
static void Appointments()
{
Outlook.ApplicationClass application = new Outlook.ApplicationClass();
Outlook.MAPIFolder folder = application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
foreach (Outlook.AppointmentItem item in folder.Items)
{
Console.WriteLine(item.Subject);
Console.WriteLine(item.Body);
}
}
As soon as the snippet executes, the following allow/deny popup appears:
This obviously defeats the whole concept of "automation", we don't want users to allow/deny actions, but how do
we get around this issue though?
We need to write code that is "trusted" by Outlook.
If you look at the preceding code snippet
(which is from a console app), the code won't be trusted since
first of all our code needs to run in context of outlook and secondly since we're outside the host process we can't
access its trusted application object, which forces us to instantiate a new "untrusted" application object.
In the following snippet we alter the preceding snippet to run in context of outlook
(via Add-In) and access the main
application object
(which is trusted), in theory the popup won't be displayed anymore.
(i've seen in quite a number of forums people complaining that it still brings up the popup. Works for me though)
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
{
applicationObject = application;
addInInstance = addInInst;
Outlook.ApplicationClass outlook = (Outlook.ApplicationClass)application;
Outlook.MAPIFolder folder = outlook.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
foreach (Outlook.AppointmentItem item in folder.Items)
{
MessageBox.Show(item.Subject);
MessageBox.Show(item.Body);
}
}
But what about scenarios where we need to be out of process - which translates to untrusted?
There are two solutions I am going to explain in this post, one requires some minor alterations to code, the
other one requires no changes in code.
In the following snippet I make use of the
Redemption class
written by the guys at dimastr.com:
static void Appointments()
{
Outlook.ApplicationClass application = new Outlook.ApplicationClass();
Outlook.MAPIFolder folder = application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
foreach (Outlook.AppointmentItem item in folder.Items)
{
Redemption.SafeAppointmentItemClass safe = new Redemption.SafeAppointmentItemClass();
safe.Item = item;
Console.WriteLine(item.Subject);
Console.WriteLine(safe.Body);
}
}
Basically instead of using the properties from the object model, the properties are extracted via Extended MAPI - bypassing the
object model guard - which means no popup.
Another solution comes in the form of an
Add-In written by
the guys at mapilab.com. When we run our "untrusted" code, instead of an allow/deny popup, you will notice the following popup
(for example) jumping up instead.
Which gives us a lot more control over external applications trying to access properties via COM.
Additional reading
http://www.mapilab.com/outlook/security/
http://www.dimastr.com/redemption/
http://support.microsoft.com/kb/327657