MAPI Folders

The MAPI folder object is used to organize both messages and subfolders in a message store. Each message store will typically contain at least five folders that are commonly used: Deleted Items, Drafts, Inbox, Outbox, and Sent Items. Every folder in the message store implements the IMAPIFolder interface, which can be used to create new messages, as well as copy and delete them. In addition, you can use IMAPIFolder to manage any subfolders.

Because a MAPI folder can contain objects that have multiple subfolders, or hierarchy, management of the tables supported in the folder object is handled by the IMAPIContainer interface, from which all IMAPIFolder objects are derived.

The IMAPIContainer interface supports the methods described in Table 11.16.

Table 11.16. IMAPIContainer Methods

Method

Description

GetContentsTable()

Returns an IMAPITable interface for a table that lists the contents of the container

GetHierarchyTable()

Returns an IMAPITable interface for a table that lists the container's hierarchy table

OpenEntry()

Returns an interface for a specific MAPI object based on its ENTRYID

As you can see, two different types of tables are available to a client application from the IMAPIContainer interface. Contents tables are used to return data about the objects contained within the current folder, and hierarchy tables are used only to return data about child objects within the current folder.

More specifically, if you wanted to get a table of the messages in a folder, you would use the IMAPIContainer::GetContentsTable() function. To get a list of subfolders for the current folder, you would use IMAPIContainer::GetHierarchyTable() instead.

The IMAPIContainer object is also derived from IMAPIProp, and supports the properties described in Table 11.17.

Table 11.17. IMAPIContainer Properties

Property Tag

Property Type

Description

PR_DISPLAYNAME

PT_TSTRING

The display name of the object

PR_ENTRYID

PT_BINARY

The object's entry identifier

PR_LAST_MODIFICATION_TIME

PT_SYSTIME

The last date and time the object was modified

PR_NULL

PT_NULL

A NULL value

PR_OBJECT_TYPE

PT_LONG

The type of object

PR_PARENT_ENTRYID

PT_BINARY

The parent object's entry identifier

The IMAPIFolder interface supports the methods described in Table 11.18.

Table 11.18. IMAPIFolder Methods

Method

Description

CopyFolder()

Copies or moves a folder

CopyMessages()

Copies or moves messages

CreateFolder()

Creates a new subfolder and returns a new IMAPIFolder interface

CreateMessage()

Creates a new message and returns a new IMessage interface

DeleteFolder()

Deletes a subfolder

DeleteMessages()

Deletes a message

In order to get the interface pointer for a specific MAPI folder object, you need to determine the ENTRYID for the folder to be used with the IMsgStore::OpenEntry() function.

One way to get the table of the folders in a message store is to use the IMAPIProp::GetProps() function on the message store to get the ENTRYID for the root object (using the PR_IPM_SUBTREE_ENTRYID property):

// After we have the pointer to the store we are interested
// in (pPop3Store) get the PR_IPM_SUBTREE_ENTRYID to get the
// entry identifer for the root folder.
LPSPropValue rgStoreProps = NULL;
ULONG cStoreValues = 0;
IMAPIFolder *pPOPRootFolder = NULL;
SizedSPropTagArray(2, rgStoreTags) = {2,{PR_IPM_SUBTREE_
  ENTRYID, PR_OBJECT_TYPE}};

// Now get the root folder.
hr = pPop3Store->GetProps((LPSPropTagArray)&rgStoreTags,
  MAPI_UNICODE, &cStoreValues, &rgStoreProps);
if(FAILED(hr))
   return FALSE;

hr = pPop3Store->OpenEntry(rgStoreProps[0].Value.bin.cb,
    (LPENTRYID)rgStoreProps[0].Value.bin.lpb, NULL,
          MAPI_MODIFY, NULL, (LPUNKNOWN*)&pPOPRootFolder);
if(FAILED(hr))
   return FALSE;

// Get the hierarchy table to get the entry identifier and
// name of each folder.
IMAPITable *pIFoldersTable = NULL;
hr = pPOPRootFolder->GetHierarchyTable(0, &pIFoldersTable);

while(1) {
   SRowSet *pRowSet = NULL;

   SizedSPropTagArray(2, tblColumns) = {2,{PR_DISPLAY_NAME,
      PR_ENTRYID}};
   pIFoldersTable->SetColumns((LPSPropTagArray)&tblColumns, 0);
   hr = pIFoldersTable->QueryRows(1, 0, &pRowSet);

   if(pRowSet->cRows != 1)
      break;

   // Do something, such as display the name
   OutputDebugString(pRowSet->aRow[0].lpProps[0].Value.lpszW);

   // Free buffers allocated by MAPI
   FreeProws(pRowSet);
};

The message store object on Pocket PC also supports properties that can be used to specify any of the following standard folders:

  • PM_IPM_OUTBOX_ENTRYID, for the Outbox folder

  • PM_IPM_SENTMAIL_ENTRYID, for the Sent Items folder

  • PM_IPM_WASTEBASKET_ENTRYID, for the Deleted Items folder

  • PM_CE_IPM_DRAFTS_ENTRYID, for the Drafts folder

  • PM_CE_IPM_INBOX_ENTRYID, for the Inbox folder

Once you have the pointer to the IMAPIFolder interface that you are interested in, you can then perform any operations on the folder, such as creating a new message, copying a message, or even creating a new subfolder.

To get a list of the subfolders for a particular folder object, you can use the IMAPIContainer::GetHierarchyTable() function:

HRESULT IMAPIContainer::GetHierarchyTable(ULONG ulFlags,
   LPMAPITABLE *lppTable);

The first parameter is ignored and can be set to 0. The lppTable parameter will point to a new IMAPITable interface when the function returns.