Accessing MAPI Properties

Use Redemption to read and write Outlook and Exchange properties that are not exposed, are blocked, or are limited in the Outlook Object Model.

Recommended path: use the Fields collection on RDO objects and Safe*Item objects. The old Redemption.MAPIUtils object remains documented for existing code, but it should not be the first choice for new session-based work.
RDO objects

Use RDOSession and RDO objects when your code owns the MAPI session, needs folder/store/message objects, or runs outside a simple Outlook item wrapper.

Safe*Item objects

Use Safe*Item wrappers when you already have an Outlook item and want a minimal-change way to read or write blocked and missing properties.

Legacy MAPIUtils

Use MAPIUtils only for old code or stateless helper calls against objects you explicitly pass in. Prefer RDOSession for anything that needs a session.

Why use MAPI properties

Outlook exposes many item, folder, recipient, and store values through the Outlook Object Model, but not everything is available there. Some properties are Exchange-specific, PST-specific, security-sensitive, too low-level for the object model, or stored as property types the Outlook Object Model does not expose cleanly.

Typical examples include transport headers, sender and recipient address details, message size, icon indexes, named properties, and many provider-specific fields. Outlook 2007 and later include PropertyAccessor, but it still has limitations around certain property types, large binary properties, and properties Outlook treats specially.

Redemption exposes these values through Fields on RDO and Safe* objects, while still letting you use COM-friendly code from VBA, VBScript, .NET, Delphi, C++, and other COM-capable languages.

Why MAPIUtils is legacy

Redemption.MAPIUtils was the original utility object for raw MAPI property access and other helper operations. It is still documented because existing code uses it and some methods are useful when they operate only on an object you explicitly pass in.

The problem is session ownership. Some MAPIUtils methods need a MAPI session. You can set MAPIUtils.MAPIOBJECT to Application.Session.MAPIOBJECT, but if you do not, MAPIUtils can create or discover a session that is not the Outlook session your code meant to use.

RDOSession makes that choice explicit: set RDOSession.MAPIOBJECT from Outlook when you want to share Outlook's active session, or call one of the Logon methods when your code should open its own session. That makes failures and session boundaries much easier to reason about.

How MAPI property tags work

Most Extended MAPI objects are property bags. Messages, folders, stores, recipients, attachments, address book entries, and distribution lists all expose properties through the MAPI IMAPIProp interface.

Every tagged MAPI property is identified by a 32-bit property tag. The upper 16 bits are the property ID, and the lower 16 bits are the property type. For example, PR_SUBJECT_A is 0x0037001E: property ID 0x0037, type PT_STRING8 (0x001E).

Redemption exposes common tags through the MAPITags enumeration. Tools such as OutlookSpy are useful when you need to inspect the actual properties available on a live Outlook object.

Property type Hex value Description
PT_UNSPECIFIED0000Reserved; not directly useful from Automation clients.
PT_NULL0001Null value.
PT_I2, PT_SHORT0002Signed 16-bit integer.
PT_I4, PT_LONG0003Signed or unsigned 32-bit integer.
PT_R4, PT_FLOAT000432-bit floating-point value.
PT_R8, PT_DOUBLE000564-bit floating-point value.
PT_CURRENCY0006Currency value stored as a 64-bit integer.
PT_APPTIME0007Date/time value.
PT_ERROR000A32-bit error value.
PT_BOOLEAN000BBoolean value.
PT_OBJECT000DEmbedded MAPI object; not directly accessible from VB/VBA.
PT_I8, PT_LONGLONG001464-bit signed integer.
PT_STRING8001E8-bit string.
PT_UNICODE001FUnicode string.
PT_SYSTIME0040Date/time value.
PT_CLSID0048GUID value.
PT_BINARY0102Byte array.

Multi-valued properties add 0x1000 to the property type. For example, PT_MV_STRING8 is 0x101E, and PT_MV_UNICODE is 0x101F.

Named properties

Named properties solve the collision problem for custom or provider-specific data. Instead of choosing a fixed property ID yourself, you provide a GUID plus either a string name or numeric ID. MAPI maps that name to a store-specific property tag.

Outlook user properties use the public strings property set, {00020329-0000-0000-C000-000000000046}. For example, Outlook categories are stored as the named property Keywords in that property set.

Use GetIDsFromNames on an RDO or Safe* object to resolve the property ID, then combine it with the required property type before reading or writing through Fields.

Examples

These examples use Safe* objects or RDO objects first. The same low-level values can often be reached through MAPIUtils.HrGetOneProp or HrSetOneProp, but that is the legacy form.

Read a tagged property with SafeMailItem

dim sItem, MailItem, PR_SENDER_EMAIL_ADDRESS

set MailItem = Application.Session.GetDefaultFolder(6).Items(1)
set sItem = CreateObject("Redemption.SafeMailItem")
sItem.Item = MailItem

PR_SENDER_EMAIL_ADDRESS = &H0C1F001E
MsgBox sItem.Fields(PR_SENDER_EMAIL_ADDRESS)

Read the same property through RDO

dim Session, MailItem, Msg, PR_SENDER_EMAIL_ADDRESS

set MailItem = Application.Session.GetDefaultFolder(6).Items(1)
set Session = CreateObject("Redemption.RDOSession")
Session.MAPIOBJECT = Application.Session.MAPIOBJECT

set Msg = Session.GetRDOObjectFromOutlookObject(MailItem)
PR_SENDER_EMAIL_ADDRESS = &H0C1F001E
MsgBox Msg.Fields(PR_SENDER_EMAIL_ADDRESS)

Read transport headers

dim sItem, MailItem, PR_TRANSPORT_MESSAGE_HEADERS

set MailItem = Application.Session.GetDefaultFolder(6).Items(1)
set sItem = CreateObject("Redemption.SafeMailItem")
sItem.Item = MailItem

PR_TRANSPORT_MESSAGE_HEADERS = &H007D001E
MsgBox sItem.Fields(PR_TRANSPORT_MESSAGE_HEADERS)

Read Outlook categories as an array

dim sItem, MailItem, PR_CATEGORIES, Categories
const PS_PUBLIC_STRINGS = "{00020329-0000-0000-C000-000000000046}"
const PT_MV_STRING8 = &H101E

set MailItem = Application.Session.GetDefaultFolder(6).Items(1)
set sItem = CreateObject("Redemption.SafeMailItem")
sItem.Item = MailItem

PR_CATEGORIES = sItem.GetIDsFromNames(PS_PUBLIC_STRINGS, "Keywords")
PR_CATEGORIES = PR_CATEGORIES + PT_MV_STRING8
Categories = sItem.Fields(PR_CATEGORIES)

MsgBox Categories(0)

Set a MAPI property

To set a property, assign through Fields and save the item when the object requires it. This example sets an Outlook icon index on a message.

dim sItem, MailItem, PR_ICON_INDEX

set MailItem = Application.Session.GetDefaultFolder(6).Items(1)
set sItem = CreateObject("Redemption.SafeMailItem")
sItem.Item = MailItem

PR_ICON_INDEX = &H10800003
sItem.Fields(PR_ICON_INDEX) = 256
sItem.Save

Where to go next