Redemption library consists of two families of objects: Safe*Item family of objects (listed on this page), which are designed to be used alongside your existing Outlook Object Model or CDO 1.21 code, and RDO (Redemption Data Objects), which are designed to be used as a CDO 1.21 or Outlook Object Model replacement. Unlike the Outlook Object Model objects, RDO objects can be used in a service.

Using Redemption Objects

Redemption is a regular COM object; once registered on the system, it is accessible to any programming language (VB, VBA, VC++, etc). Redemption uses Extended MAPI (which is not affected by the Security Patch since it is not accessible to the scripting languages) to duplicate the functionality blocked by the Security Patch. Most Redemption objects have an Item property which must be set to an Outlook item. Once set, you can access any properties and methods available on an original Outlook item, both blocked and not blocked. For the blocked properties and functions Redemption objects completely bypass Outlook object model and behave exactly like Outlook objects with no Security Patch applied. For the properties not blocked by the Security Patch, all calls to the properties and methods are forwarded to the Outlook object you assign to the Item property. With this approach changes to your code are minimal: you only change the way you declare the objects, but not the rest of your code that actually accesses blocked and not blocked properties and methods.

 

dim SafeContact, oContact 
set SafeContact = CreateObject("Redemption.SafeContactItem")
'Create an instance of Redemption.SafeContactItem 
set oContact = Application.Session.GetDefaultFolder(10).Items(1)
'Get a contact item from Outlook
SafeContact.Item = oContact
'set Item property of a SafeContact to an Outlook contact item
MsgBox SafeContact.Email1Address
'access Email1Address property from SafeContact, no warnings are displayed

 

There are matching objects for all other Outlook items with blocked properties: SafeContactItem, SafeMailItem, SafeTaskItem, SafeJournalItem, SafeMeetingItem and SafePostItem. See below for a complete list of properties and methods handled directly by Redemption.

Below are examples of code snippets before and after the change. Code in red corresponds to the difference in code between the two versions:

 

VB Script:

 

dim Contact 
set Contact = Application.Session.GetDefaultFolder(10).Items(1)


MsgBox Contact.Email1Address '
With Security patch, a warning is shown
no code below is affected

dim Contact, oContact 
set oContact = Application.Session.GetDefaultFolder(10).Items(1)
set Contact = CreateObject("Redemption.SafeContactItem")

Contact.Item = oContact 'never use "Set" when setting the Item property
MsgBox Contact.Email1Address 'No warnings are shown
no code below is affected:
'You can access Contact object as if no Security patch is applied 

 
VB:

dim Contact as Outlook.ContactItem
set Contact = Application.Session.GetDefaultFolder(10).Items(1)


MsgBox Contact.Email1Address
no code below is not affected

dim Contact as Object, oContact as Object
set oContact = Application.Session.GetDefaultFolder(10).Items(1)
set Contact = new Redemption.SafeContactItem

Contact.Item = oContact 'never use "Set" when setting the Item property
MsgBox Contact.Email1Address
no code below is not affected

 

C#:

Outlook.ContactItem Contact;
set Contact = Application.Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts).Items.GetFirst();


MsgBox.Show(Contact.Email1Address);
no code below is not affected

Outlook.ContactItem Contact;
set Contact = Application.Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts).Items.GetFirst();
Redemption.SafeContactItem sContact = new Redemption.SafeContactItem();
sContact.Item = Contact;

MsgBox.Show(
sContact.Email1Address);
no code below is not affected


Declare Contact as Object rather than Outlook.ContactItem if you are using VB: even though all Safe*Item objects expose all properties and methods of the corresponding Outlook items, they do so dynamically when you assign an Outlook item to their Item property - at design time compiler will complain that most properties and methods are not found if you declare them as anything but Object.

 

Properties and methods of the Redemption objects

Most Redemption objects support the same properties and methods as the corresponding native Outlook objects. This support is dynamic: after you assign the Item property of one of the Redemption objects to a native Outlook item and try to access any property or method not directly supported by the Redemption object, the call is transparently forwarded to the Outlook object. E.g. if you set Item property to one of the Outlook mail items and then access Subject property on the Redemption object, this call will be forwarded to and handled by the Outlook object transparently. Such dynamic binding is the reason why you must declare all Redemption object as an untyped Object rather than a typed object (e.g. Redemption.SafeMailItem): otherwise compiler will complain that a property or method is not found even though it will be resolved just fine at runtime. 

 

All the properties and methods blocked by the Security Patch are handled by the Redemption objects directly without accessing Outlook object model. Below is a list of such properties and methods:

 


Object

Corresponding Outlook Object

Property or method

Comments


All objects

-

Item property (object)

must be set to an Outlook item before any other properties or methods are accessed. Read/Write

 

 

RTFBody property (string)

allows access to the raw RTF body of any item. Read/Write

 

SaveAs(Path, Type)

Save the item in the specified format. Only Type = olTemplate(2), olMsg (3), olMsgUnicode (9), olTxt(0), olRtf (1), olRtfNoHeaders(1026), olVCard (6), olTNEF (1025), olRFC822 (1024), olMHTML (1027), olVCal (7), olICal (8) are supported now, in all other cases the call will be forwarded to the original Outlook item.

 

Recipients property (object)

Recipients collection, the same as for any Outlook item. Read only

 

Attachments property (object)

Attachments collection. This collection is aware of all attachments, both safe and unsafe. Read only

 

Send method

Send the item.

 

Import(Path, Type) method

Import a file into an existing item. Path - full path to the file, Type - integer; olMSG (3), olTNEF (1025) and olRFC822 (1024) are the only types supported now. See example below 

 

Fields(PropTag) array property

Returns or sets any Extended MAPI property available on the item. PropTag - integer. Returns a variant of type determined by the property kind (integer, string, etc). To see what properties are available on the item, use OutlookSpy. For more information on Extended MAPI properties see Miscellaneous Redemption objects. See also example below.

 

To delete a property, set it to Empty, e.g. Fields(&H0037001E)=Empty deletes PR_SUBJECT property.

 

CopyTo(Item) method

Copies Redemption item (and hence the corresponding Outlook item) into any other Outlook or CDO item. See example below.

 

GetIDsFromNames(GUID, ID)

Returns an id suitable for use in the Fields() collection given the GUID (as string) and Id (can be either integer or a string). See example below. For the discussion of the named properties, see the Extended MAPI properties, especially the section on named properties.

 


SafeContactItem

ContactItem

Email1Address

Same as native Outlook properties

 

Email1AddressType

 
 

Email1DisplayName

 

Email1EntryID

Email2Address

Email2AddressType

Email2DisplayName

Email2EntryID

Email3Address

Email3AddressType

Email3DisplayName

Email3EntryID

NetMeetingAlias

ReferredBy


SafeAppointmentItem    

AppointmentItem

Organizer

Same as native Outlook properties

RequiredAttendees

OptionalAttendees

Resources

NetMeetingOrganizer


SafeMailItem

MailItem

SentOnBehalfOfName

Same as native Outlook properties

SenderName

ReceivedByName

ReceivedOnBehalfOfName

ReplyRecipientNames

To

CC

BCC


SafeTaskItem

TaskItem

ContactNames

Same as native Outlook properties

Contacts

Delegator

Owner

StatusUpdateRecipients

StatusOnCompletionRecipients


SafeJournalItem

JournalItem

ContactNames

Same as native Outlook properties


SafeMeetingItem

MeetingItem

SenderName

Same as native Outlook properties


SafePostItem

PostItem

SenderName

Same as native Outlook properties


SafeDistList

DistListItem

GetMember(Index) - returns SafeRecipient

Returns distribution list member as SafeRecipient

AddMember(Recipient)

Add new dist list member

AddMembers(Recipients)

Add new dist list members

RemoveMember(Recipient)

Remove a dist list member

RemoveMembers(Recipients)

Remove dist list members


SafeReportItem

ReportItem

Body

Returns the report body. Note that ReportItem body is not the same as PR_BODY in Extended MAPI; it is dynamically constructed from various report properties in the ReportItem recipients table.


Attachment object below is not directly creatable, it can only be accessed through the Attachments collection of any Safe*Item. Attachment object supports all the properties and methods as the native Outlook Attachment object, but in addition it also supports the following properties:


Attachment

Attachment

AsText property (string)

Attachment data as string. This property is only valid for the attachments with a type of olByValue. Read/Write.

AsArray property (Variant array of byte)

Attachment data as a variant array of byte. This property is only valid for the attachments with a type of olByValue. Read/Write.

Size property (integer)

The size of the attachment object. Note that the value of this property is usually larger than the size of the attachment data as it also includes additional properties stored by MAPI. Read only

Fields(PropTag) array property

Returns any Extended MAPI property available on the item. PropTag - integer. Returns a variant of type determined by the property kind (integer, string, etc). To see what properties are available on the item, use OutlookSpy. For more information on Extended MAPI properties see Miscellaneous Redemption objects. See also example below

EmbeddedMsg property

Allows to access embedded message attachments. Returns MessageItem object. For regular (file) attachments this property is NULL


Recipient object below is not directly creatable, it can only be accessed through the Recipients collection of any Safe*Item. Recipient object supports all the properties and methods as the native Outlook Recipient object, but in addition it also supports the following properties:


Recipient 

Recipient 

Fields(PropTag) array property

Returns any Extended MAPI property available on the item. PropTag - integer. Returns a variant of type determined by the property kind (integer, string, etc). To see what properties are available on the item, use OutlookSpy. For more information on Extended MAPI properties see Miscellaneous Redemption objects. See also example below

FreeBusy((Start:, MinPerChar, CompleteFormat)

Returns Recipient's Free/Busy information. See Outlook help


 

SafeCurrentUser - this object is similar to the Namespace.CurrentUser.AddressEntry object. Use it if you need to find the name or e-mail address of the current user

Recipient 

Namespace.CurrentUser.AddressEntry

 Same properties and methods as Outlook's AddressEntry

Note that in Outlook Namespace.CurrentUser returns Recipient object which does not really make sense: Recipient.Type (To, CC, BCC), for example, is irrelevant in case of a current user.

Redemption returns AddressEntry object instead, see example below

Cleanup method

Redemption needs to keep reference to the IMAPISession Extended MAPI interface. Outlook 2002 might have a problem properly closing if there is an outstanding reference. Calling this method ensures that Redemption cleans up its internal references to all Extended MAPI objects.

Examples

NOTE: it is assumed that the Application variable in the samples below is initialized to point to an instance of the Outlook's Application object. If you write a COM add-in, you can grab Application from the OnConnection() callback. If you are creating a standalone app, one of the ways to initialize Outlook is as follows:

set Application = CreateObject("Outlook.Application")

set Namespace = Application.GetNamespace("MAPI")

Namespace.Logon

 

Send email bypassing the security prompt. Note that (see FAQ)  if you are using this code with Outlook 2002, it will work flawlessly only if you run it under an Exchange Server, otherwise the message will stay in the Outbox until you click "Send/Receive" in Outlook.

dim SafeItem, oItem 
set SafeItem = CreateObject("Redemption.SafeMailItem")
'Create an instance of Redemption.SafeMailItem 
set oItem = Application.CreateItem(0) 'Create a new message
SafeItem.Item = oItem 'set Item property
SafeItem.Recipients.Add "somebody@somewhere.com"
SafeItem.Recipients.ResolveAll
SafeItem.Subject = "Testing Redemption"
SafeItem.Send

Access blocked property (Email1Address in this example) that if used directly in Outlook with the Security patch applied would cause a warning to be displayed. Accessing this property using Outlook Redemption bypasses the Security Patch.

dim SafeContact, oContact 
set SafeContact = CreateObject("Redemption.SafeContactItem")
'Create an instance of Redemption.SafeContactItem 
set oContact = Application.Session.GetDefaultFolder(10).Items(1) 'Get a contact item from Outlook, can be any other contact
SafeContact.Item = oContact 'set Item property of a SafeContact to an Outlook contact item
MsgBox SafeContact.Email1Address 'access Email1Address property from SafeContact, no warnings are displayed

Import function. Import an MSG file. The example below creates a new mail item in the Drafts folder and imports an existing MSG file into it:

dim sItem, oItem
set sItem = CreateObject("Redemption.SafeMailItem")
set oItem = Application.Session.GetDefaultFolder(16).Items.Add(6)
sItem.Item = oItem
sItem.Import "c:\temp\test.msg", 3  '
olMSG, olRFC822 and olTNEF formats are supported
sItem.Save

Note the same can be achieved using the RDO family of objects, which does not rely on Outlook at all.

set Session = CreateObject("Redemption.RDOSession")
Session.MAPIOBJECT = Application.Session.MAPIOBJECT

set Msg = Session.GetDefaultFolder(16).Items.Add(6)
Msg.Import "c:\temp\test.msg", 3  '
olMSG, olRFC822 and olTNEF formats are supported
Msg.Save

Fields array. Display sender e-mail address (PR_SENDER_EMAIL_ADDRESS Extended MAPI property). Note that Outlook does not expose this property through its object model. There are dozens more properties that might be of interest to you: PR_TRANSPORT_MESSAGE_HEADERS on e-mail items, PR_SEND_RICH_INFO on Recipient objects, etc. Use MdbView or OutlookSpy to see which properties are available.

dim sItem, oItem
set sItem = CreateObject("Redemption.SafeMailItem")
set oItem = Application.Session.GetDefaultFolder(6).Items(1) '
get first e-mail from the Inbox, can be any other item
sItem.Item = oItem
PrSenderEmail = &H0C1F001E
MsgBox sItem.Fields(PrSenderEmail)

Another example on how to use the Fields array. The example shows how to add an extra RFC822 header to a message to be sent. It is assumed that MailItem variable points to an existing Outlook MailItem object. When adding your own headers, the name (second argument to getIDsfromNames) can be pretty-much anything you want, but make sure that the GUID is exactly the same as given below - Outlook only adds named properties with that GUID to the outgoing message headers.

set sItem = CreateObject("Redemption.SafeMailItem")
sItem.Item = MailItem
tag = sItem.GetIDsFromNames("{00020386-0000-0000-C000-000000000046}", "x-test-header")
tag = tag or &H1E     '
the type is PT_STRING8
sItem.Fields(Tag) = "test value"
sItem.Subject = sItem.Subject  '
to trick Outlook into thinking that something has changed
sItem.Save

SafeCurrentUser object. Use this object to find out the name or e-mail address of the current Outlook user

dim CU
set CU = CreateObject("Redemption.SafeCurrentUser")
MsgBox CU.Address
CU.Cleanup '
do call cleanup, otherwise Outlook might have trouble properly closing down
set CU = Nothing

CopyTo method. Note that the code below saves the new item, gets its EntryID, sets all the references to it (including the Redemption object) to Nothing, then reopens it. This is necessary since Outlook remembers the old values of some properties, such as whether the message was sent.

set oItem = Application.Session.GetDefaultFolder(6).Items(16)
set sItem = CreateObject("Redemption.SafeMailItem")
sItem.Item = oItem
set NewItem = Application.CreateItem(0)
sItem.CopyTo(NewItem)
'must save to have EntryID
NewItem.Save
EID = NewItem.EntryID
'de-reference the old item, then open it again
'otherwise Outlook might still have tidbits
'left from the original message
 
set NewItem = Nothing
set sItem = Nothing
set NewItem = Application.Session.GetItemFromID(EID)
NewItem.Display

Forcing Outlook to send a message in plain text format. The same technique can be used to send in Rich Text Format. Without going into the details of the one-off recipient entry id format (which is documented on MSDN), one-off recipient entry ids must have byte #22 (21 zero based) set to 1. The code first checks if the entry id is indeed one-off, then sets byte #22 to 1 for all recipients in a message (MailItem is assumed to be set to an Outlook Object Model message).

Function IsOneOffEntryID(EntryID)
  'check the first 20 bytes
  OOEID = Array(0,0,0,0,&H81,&H2B,&H1F,&HA4,&HBE,&HA3,&H10,&H19,&H9D,&H6E,0,&HDD,&H01,&H0F,&H54,&H02)
  IsOneOffEntryID = true
  for i = 0 to 19
    if EntryID(i) <> OOEID(i) Then
      IsOneOffEntryID = false
      Exit Function
    End If
  Next
End Function

PR_ENTRYID = &HFFF0102
PR_SEND_RICH_INFO = &H3A40000B
set sItem = CreateObject("Redemption.SafeMailItem")
sItem.Item = MailItem
For i = 1 to sItem.Recipients.Count
  entryBytes = sItem.Recipients.Item(i).Fields(PR_ENTRYID)
  If IsOneOffEntryID(entryBytes) Then
    entryBytes(22) = 1
    sItem.Recipients.Item(i).Fields(PR_ENTRYID) = entryBytes
    sItem.Recipients.Item(i).Fields(PR_SEND_RICH_INFO) = false
    MailItem.Subject = MailItem.Subject 
  ' just to make Outlook think something has changed
    MailItem.Save
  End If
Next

Create an HTML message with an embedded image. The code is adopted from the code posted on Slipstick.Com 

set DraftsFolder = Application.Session.GetDefaultFolder(16)
set MailItem = DraftsFolder.Items.Add
set sItem = CreateObject("Redemption.SafeMailItem")
sItem.Item = MailItem
'tell Outlook to hide the paperclip icon
'this is a named prop, so we must call GetIDsFromNames() first!
PT_BOOLEAN = 11
PR_HIDE_ATTACH = sItem.GetIDsFromNames("{00062008-0000-0000-C000-000000000046}", &H8514) or PT_BOOLEAN
sItem.Fields(PR_HIDE_ATTACH) = true
'add attachment
set Attach = sItem.Attachments.Add("c:\temp\test.jpg")
'content type
Attach.Fields(&H370E001E) = "image/jpeg"
'Attachment cid
Attach.Fields(&H3712001E) = "myident"
sItem.HTMLBody = "<b>test image:</b><IMG align=baseline border=0 hspace=0 src=cid:myident>"
sItem.Save
'IMPORTANT - dereference everything
set Attach = Nothing
set sItem = Nothing
set MailItem = Nothing
set DraftsFolder = Nothing

Use MAPIFolder object to access the hidden items collection to store custom configuration options

set MAPIFolder = Application.Session.GetDefaultFolder(6)

set sFolder = CreateObject("Redemption.MAPIFolder")

sFolder.Item = MAPIFolder

set Items = sFolder.HiddenItems

'search by subject

set HiddenMsg = Items.Item("My config message")

If (HiddenMsg is Nothing) Then

  set HiddenMsg = Items.Add("IPM.Note.MyProduct.Config")

  'set the subject so we can find this message next time

  HiddenMsg.Subject = "My config message"

End If

'just for the fun of it, store our custom data

'in a named prop. We can just as well use any fixed tag prop

' (e.g. &H6900001E) since we are the only ones using this message

'and there shouldn't be any conflicts

PT_STRING8 = &H001E

PR_MYSTRING_PROP = HiddenMsg.GetIDsFromNames("{FFF40745-D92F-4C11-9E14-92701F001EB3}", "TestProp") or PT_STRING8

PropValue = HiddenMsg.Fields(PR_MYSTRING_PROP)

MsgBox "Old Value: " & PropValue

HiddenMsg.Fields(PR_MYSTRING_PROP) = "New Value"

HiddenMsg.Save

 

Using GetIDsFromNames method to access the Email1Address property of a Contact. You can of course access this property using SafeContactItem.Email1Address, but there some named properties which are not exposed through the Outlook Object Model. To find out what the GUIDs and IDs are, use OutlookSpy (click IMessage button). For the discussion of the named properties, see the Extended MAPI properties, especially the section on named properties.

'The code assumes that OutlookContact points to an initialized ContactItem object retrieved from Outlook Object Model

sContact = CreateObject("Redemption.SafeContactItem")

sContact.Item = OutlookContact

PT_STRING8 = &H001E

PR_EMAIL1_ADDRESS = sContact.GetIDsFromNames("{00062004-0000-0000-C000-000000000046}", &H8083) or PT_STRING8 'type must be set!!!

MsgBox sContact.Fields(PR_EMAIL1_ADDRESS)