How to use named properties to relate Contact Address Book entries to e-mail messages, e-mail addresses, and picture attachments in Outlook 2003 (912237)



The information in this article applies to:

  • Microsoft Office Outlook 2003, when used with:
    • Microsoft Office 2003 Service Pack 2

INTRODUCTION

The Contact Address Book is a feature in Microsoft Office Outlook 2003 Service Pack 2 (SP2), just as in earlier versions of Microsoft Outlook. This article describes how to use named properties to relate Contact Address Book entries to e-mail messages, e-mail addresses, and picture attachments in Outlook 2003 SP2.

MORE INFORMATION

About the Contact Address Book

The Contract Address Book provider that is included in Outlook 2003 SP2 is contab32.dll. This provider displays information from a Contacts folder in the form of a Contact Address Book. The provider does this so that you can use the contacts in the Contact Address Book to address e-mail messages. All contacts that have an e-mail address or a fax number are represented in the Contact Address Book by a separate listing for each e-mail address or fax number. Because a contact may have up to three e-mail addresses and three fax numbers, each contact may therefore be represented by up to six separate entries in the Contact Address Book.

How to relate Contact Address Book entries to e-mail messages

The information that is in a Contact Address Book entry is a subset of the information that is in the underlying e-mail message to the contact. The following CONTAB_ENTRYID structure can be used to determine the Contact Address Book entry from which an underlying message is derived.

Definition
#pragma pack(4)
typedef struct _contab_entryid
{
  BYTE misc1[4];
  MAPIUID misc2;
  ULONG misc3;
  ULONG misc4;
  ULONG misc5;
  // EntryID of contact in store.
  ULONG cbeid;
  BYTE abeid[1];
} CONTAB_ENTRYID, *LPCONTAB_ENTRYID;
#pragma pack()
The CONTAB_ENTRYID structure defines the format of the entry IDs of IMailUser objects that are used in the Contact Address Book. You can obtain entry IDs of this kind from one or both of the following sources:
  • The PR_ENTRYID column of the Contact Address Book contents table
  • The PR_ENTRYID property of an IMailUser object that is opened from the Contact Address Book
To open the underlying message, typecast the Contact Address Book entry ID to this structure. Then, use the cbeid and abeid members as the contact's entry ID.

ExampleMicrosoft provides programming examples for illustration only, without warranty either expressed or implied. This includes, but is not limited to, the implied warranties of merchantability or fitness for a particular purpose. This article assumes that you are familiar with the programming language that is being demonstrated and with the tools that are used to create and to debug procedures. Microsoft support engineers can help explain the functionality of a particular procedure, but they will not modify these examples to provide added functionality or construct procedures to meet your specific requirements.
HRESULT HrOpenContact(
  LPMAPISESSION lpSession,
  ULONG cbEntryID,
  LPENTRYID lpEntryID,  
  ULONG ulFlags,
  LPMESSAGE* lpContactMessage)
{
  ULONG ulObjType = NULL;
  if (sizeof(CONTAB_ENTRYID) > cbEntryID)
      return MAPI_E_INVALID_PARAMETER;
  LPCONTAB_ENTRYID lpContabEID = (LPCONTAB_ENTRYID) lpEntryID;
  HRESULT hRes = lpSession->OpenEntry(
      lpContabEID->cbeid,
      (LPENTRYID) lpContabEID->abeid,
      NULL,
      ulFlags,
      &ulObjType,
      (LPUNKNOWN*) lpContactMessage);
  return hRes;
}

How to relate Contact Address Book entries to e-mail addresses

The only way to access the e-mail addresses in a Contact Address Book message is through the named properties on the underlying message. The properties that are documented here are read-only properties. Outlook 2003 does not support solutions that write to these properties.

Definitions
DEFINE_OLEGUID(PSETID_Address, MAKELONG(0x2000+(0x04),0x0006),0,0);
#define dispidEmailAddrType 0x8082
#define dispidEmailEmailAddress 0x8083
#define dispidEmail2AddrType 0x8092
#define dispidEmail2EmailAddress 0x8093
#define dispidEmail3AddrType 0x80A2
#define dispidEmail3EmailAddress 0x80A3
Usage

You can use the following constants to fill out the MAPINAMEID structure. These constants are the various fields of the structure.
ConstantField
PSETID_AdresslpGuid
MNID_IDulKind
dispidlID
After you have filled out the MAPINAMEID structure, use the GetIDsFromNames method to obtain the current property IDs for these properties. These properties are all string properties.

ExampleMicrosoft provides programming examples for illustration only, without warranty either expressed or implied. This includes, but is not limited to, the implied warranties of merchantability or fitness for a particular purpose. This article assumes that you are familiar with the programming language that is being demonstrated and with the tools that are used to create and to debug procedures. Microsoft support engineers can help explain the functionality of a particular procedure, but they will not modify these examples to provide added functionality or construct procedures to meet your specific requirements.
HRESULT HrGetEmail1(LPMESSAGE lpContact)
{
  HRESULT hRes = S_OK;
  LPSPropTagArray lpNamedPropTags = NULL;
  MAPINAMEID NamedID = {0};
  LPMAPINAMEID lpNamedID = &NamedID;
  NamedID.lpguid = (LPGUID)&PSETID_Address;
  NamedID.ulKind = MNID_ID;
  NamedID.Kind.lID = dispidEmailEmailAddress;
  hRes = lpContact->GetIDsFromNames(
      1,
      &lpNamedID,
      NULL,
      &lpNamedPropTags);
  if (SUCCEEDED(hRes) && lpNamedPropTags)
  {
      SPropTagArray sPropTagArray;
      sPropTagArray.cValues = 1;
      sPropTagArray.aulPropTag[0] = CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[0],PT_STRING8);
      LPSPropValue lpProps = NULL;
      ULONG cProps = 0;
      hRes = lpContact->GetProps(
        &sPropTagArray,
        NULL,
        &cProps,
        &lpProps);
    if (SUCCEEDED(hRes) &&
      1 == cProps &&
      lpProps &&
      PT_STRING8 == PROP_TYPE(lpProps[0].ulPropTag) &&
      lpProps[0].Value.lpszA)
      {
          printf("Email address 1 = \"%s\"\n",lpProps[0].Value.lpszA);
      }
    MAPIFreeBuffer(lpProps);
    MAPIFreeBuffer(lpNamedPropTags);
  }
  return hRes;
}

How to relate Contact Address Book entries to pictures

Outlook supports a single picture for each contact. This picture is stored as an attachment in the underlying message. To determine which attachment contains the picture, use the PR_ATTACHMENT_CONTACTPHOTO property. The property that is documented here is a read-only property. Outlook does not support solutions that write to this property.

Definition

#define PR_ATTACHMENT_CONTACTPHOTO PROP_TAG( PT_BOOLEAN, 0x7FFF)
Usage

The PR_ATTACHMENT_CONTACTPHOTO property can be accessed as a column in the attachment table that is obtained through IMessage::GetAttachmentTable. The PR_ATTACHMENT_CONTACTPHOTO property is accessed as a property on the IAttach object. If the value of the PR_ATTACHMENT_CONTACTPHOTO property is true, the attachment contains the contact picture. The picture is stored as a .jpeg file. Use the typical MAPI methods to extract this attachment to a file.

Modification Type:MinorLast Reviewed:2/2/2006
Keywords:kbhowto KB912237 kbAudDeveloper