Eugene Astafiev

Don't stumble over a stone working with the PropertyAccessor and StorageItem classes in Outlook 2007

There are plenty of articles in the web dwelling upon new possibilities of Outlook 2007 programming. Among the most frequently discussed issues is how to access and set various MAPI properties and how the PropertyAccessor can help with this.

Let's have a close look at the new classes which were introduced in Outlook 2007 and let's cast even a closer look at possible traps that you may get in when using these classes.

With release of Outlook 2007 Microsoft added two key new classes to the Outlook Object Model (OOM): PropertyAccessor and StorageItem. That was yet another step to eliminate the need for lower-level programming interfaces such as Collaboration Data Objects, Outlook Redemption, Extended MAPI to retrieve and set property values that are not exposed in the Outlook Object Model. Let's have a short review of each.

PropertyAccessor
PropertyAccessor provides the ability to create, get, set, and delete properties of objects. It allows getting and setting item-level properties that are not explicitly exposed in the Outlook Object Model, or properties for the following non-item objects: AddressEntry, AddressList, Attachment, ExchangeDistributionList, ExchangeUser, Folder, Recipient, and Store.
You can find more info about PropertyAccessor in the Outlook Developer Reference.

To see PropertyAccessor in action, I created a small add-in with a button in a command bar. By clicking on the button you get the HTML body of the email message. I used PropertyAccessor to read this property. The property tag is 0x10130102 (PR_HTML). To make sure this property exists in your email, you check Outlook settings, and set Mail format to HTML. To my great surprise it didn't work. I kept getting the following exception

  • UnauthorizedAccessException:

The property “https://schemas.microsoft.com/mapi/proptag/0x10130102” does not support   this operation.

Have a look at C# code snippets related to PropertyAccessor and the MAPI Store Accessor, a free .NET component that we developed specially for handling events as well as retrieving and setting MAPI properties:


private object GetValuePropertyAccessor()
{
Outlook.Folder folderInbox = (Outlook.Folder)OutlookApp.GetNamespace("MAPI").GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);
Outlook.MailItem mailItem = (Outlook.MailItem)folderInbox.Items[1];
Outlook.PropertyAccessor accessor = mailItem.PropertyAccessor;
return accessor.GetProperty("https://schemas.microsoft.com/mapi/proptag/0x10130102");
}
private object GetValueMapiAccessor()
{
AddinExpress.MAPI.Folder folderInbox = adxmapiStoreAccessor1.MsgStores[0].RootFolder.Folders[1].Folders[1];
AddinExpress.MAPI.MapiItem mailItem = folderInbox.MapiItems[0];
return mailItem.GetProperty(0x10130102);
}

The VB.Net code will be the same. If you try to test these codes, you will notice that the MAPI Store Accessor works fine while PropertyAccessor fails.

If you use PropertyAccessor, you must have good knowledge of exception handling logic. Below I list some roadblocks that you may run into:

  • The body and content of an attachment of an Outlook items are not accessible through PropertyAccessor.
  • The PropertyAccessor ignores any seconds of the date/time value
  • String properties are limited in size depending on the information store type.
  • Limitation: Personal Folders files (.pst) and Exchange offline folders files (.ost) cannot be more than 4,088 bytes.
  • Limitation: For direct online access to Exchange mailbox or Public Folders hierarchy, the limit is 16,372 bytes.
  • Binary properties only those whose values are under 4,088 byte can be retrieved or set. (If trying to use larger values, you get an out-of-memory error).
  • Date/time MAPI properties return Coordinated Universal Time (UTC). The PropertyAccessor.LocalTimeToUTC and .UTCToLocalTime methods can help you with this.

With the MAPI Store Accessor you can easily bypass all these limitations.

StorageItem
StorageItem is a message object. It stores private data for Outlook solutions.  A StorageItem object is stored at the folder level. When Outlook needs to save folder information (or store-specific information) that is more complex than a simple folder property, Outlook keeps that information in an item that the user can't see. Views, custom form definitions, archive settings, and many other configuration options are contained in such hidden items. In Outlook 2007 using the Outlook Object Model,  you can also create new hidden items to maintain data for your own solutions in mail and post folders. To return an existing or new StorageItem, you can use the Folder.GetStorage method which takes two parameters because the Outlook Object Model does not provide any collection object for StorageItem objects.

Set stItem = objFolder.GetStorage(StorageId, StorageIdType)

The StorageId parameter is a string that contains one of the following values:

  • The EntryID for the StorageItem you want to get
  • A MessageClass value. Return a StorageItem with a message class
  • A Subject value.  Return a StorageItem with specified subject

But as usually, there is another side of the coin. And here is a list of the StorageItem object limitations:

  • Custom storage using StorageItem is possible only in mail and post folders. If you try to use the GetStorage method to create a new StorageItem object in a non-mail folder, Outlook will not create a StorageItem in that folder. Instead, it creates a visible item in the user's Inbox.
  • It is also not possible to create new storage items in folders in the Exchange Public Folders hierarchy.
  • Regarding existing storage items, the GetStorage method raises an error if you try to return a hidden item from an Exchange public folder or from an Exchange system folder, such as the Organizational Forms library.

So now you know about all weak points of PropertyAccessor and StorageItem. Knowledge is a great power, and armed with this knowledge you can get over all those limitations and live happily with the Outlook object model. Of course, there is a simpler way: third-party components such as the MAPI Store Accessor. In one of my previous post I wrote about accessing hidden Outlook items via extended MAPI with the above mentioned tool.

The MAPI Accessor allows you to easily avoid the above listed traps with PropertyAccessor and StorageItem. All features of the MAPI Accessor, including hidden items, properties, event notification and others work in all Outlook versions: Outlook 2000, Outlook 2002, Outlook 2003, and Outlook 2007.

Sources:
1.    Outlook Developer Reference.
2.    Professional Outlook 2007 Programming by Ken Slovak. Wrox Press: Oct.2007.
3.    Microsoft Outlook 2007 Programming by Sue Mosher. Digital Press: Jun.2007.

2 Comments

  • TPulley says:

    An additional caveat. You can’t create or access existing StorageItems in non-primary mailboxes. (Store.ExchangeStoreType = olExchangeMailbox)

  • Darío León says:

    Great work, congratulations!!! it is very usefull for me.

Post a comment

Have any questions? Ask us right now!