MAPI C++ Exchange Public Folders

Microsoft Exchange Public Folders are the repositories of a lot of information belonging to the organization. Microsoft has provided a lot of COM Interfaces to work with Exchange servers and e-mail items. This C++ MAPI Public Folder article explains how to use Exchange Development Kit to enumerate and list the public folders in an Exchange Server.

C++ MAPI Public Folder – Sample Code:

The sample below can be used for the purpose. Copy and paste the following code and change only the values highlighted in blue to the actuals.

//PFFoldersListing.cpp
#include <afxwin.h>
#include <MAPI.H>
#include <edk.h>

#define PRIV_BUF_SIZE 256
#define PATH_SEP '\'

LPMDB pmdbPublic = NULL, pmdbPublicACL = NULL;
LPMAPIFOLDER pRoot = NULL, pRootACL= NULL;
LPMAPISESSION pSession = NULL;

HRESULT MAPIListPublicFolders(LPMAPIFOLDER lpFolder, LPCSTR lpszName)
{
HRESULT hr = NOERROR;
LPMAPITABLE lpTable = NULL;
LPSRowSet lpRow = NULL;
LPSPropValue lpRowProp = NULL;
ULONG i = 0L;
ULONG *lpcbeid =0; // pointer to count of bytes in entry ID
LPENTRYID *lppeid; // pointer to entry ID pointer

lppeid = NULL;
static const enum {IDISPNAME, IENTRYID, ICHILDCOUNT};
static SizedSPropTagArray( 3, rgColProps) = { 3, { PR_DISPLAY_NAME_A,          PR_ENTRYID,PR_FOLDER_CHILD_COUNT}};
CString l_strErrorFormatter;

ULONG ulObjType = 0L;

if( !lpFolder)
{
hr = HR_LOG( E_INVALIDARG);
goto cleanup;
}

//Open the public folder supplied as parameter using GetHierarchyTable
hr = MAPICALL( lpFolder)->GetHierarchyTable( MAPI_DEFERRED_ERRORS, &lpTable);
if (FAILED(hr))
{
hr = HR_LOG( E_FAIL);
goto cleanup;
}

//Get the list of public folders using HrQueryAllRows
hr = HrQueryAllRows( lpTable, (LPSPropTagArray)&rgColProps, NULL, NULL, 0L, &lpRow);
if( FAILED( hr))
{
if( hr == MAPI_E_NOT_FOUND)
hr = HR_LOG( EDK_E_NOT_FOUND);
else
hr = HR_LOG( E_FAIL);

goto cleanup;
}

ASSERTERROR( lpRow != NULL, "NULL Public Folders returned from QueryRows!");

// Search rows for the folder in question
for(i = 0; i < lpRow->cRows; i++)
{

//Display the fund Public folders

lpRowProp = lpRow->aRow[i].lpProps;
CString strFolder;
strFolder = lpRowProp[IDISPNAME].Value.lpszA;

printf("%sn",strFolder);
}

hr = HR_LOG( EDK_E_NOT_FOUND);

cleanup:
FREEPROWS(lpRow);
ULRELEASE(lpTable);

RETURN(hr);
}

int main()
{

HRESULT hr = S_OK;
//Initialize MAPI libraries
hr = MAPIInitialize (NULL);

// logon to MAPI for enumerating Public Folders. This can also be used to open the individual mail boxes.
hr = MAPILogonEx (NULL, "ProfileName", NULL, MAPI_EXTENDED| MAPI_NEW_SESSION|
MAPI_LOGON_UI| MAPI_EXPLICIT_PROFILE,&pSession);
if (FAILED (hr))
{
return E_FAIL;
}

//Open the MAPI Public Folder store using the IMAPISession interface
hr = HrOpenExchangePublicStore(pSession, &pmdbPublicACL);
if (FAILED (hr))
{
return E_FAIL;
}

// open the MAPI Public Folder tree
hr = HrOpenExchangePublicFolders (pmdbPublicACL, &pRoot);
if (FAILED (hr))
{
return E_FAIL;
}

DWORD cbeid = 0;
LPENTRYID lpeid = NULL;
LPMAPIFOLDER pFolder = NULL;
ULONG ulObjType = 0;

CString l_strFullPath = "TestFolder";
hr = HrMAPIFindSubfolderEx (pRoot, PATH_SEP, (LPCSTR)l_strFullPath, &cbeid, &lpeid);
if (FAILED (hr))
{
printf("MAPI Public Folder Access Error on %s for Profilen",l_strFullPath);
}
hr = pmdbPublicACL->OpenEntry ( cbeid, lpeid, NULL, MAPI_MODIFY, &ulObjType,(LPUNKNOWN*)&pFolder );
if (FAILED (hr))
{
printf("MAPI Public Folder Access Error on %s for Profile n",l_strFullPath);
}

MAPIFreeBuffer (lpeid);

MAPIListPublicFolders(pFolder,"");

pFolder = NULL;
//Free all MAPI libraries
MAPIUninitialize();

}

C++ MAPI Public Folder – Description of Sample:

Any MAPI Client program should start with a profile which has valid access permissions. The security context through which the program connects to the profile should also have enough permissions viz., User. Refer to MAPI C++ Enumerating Profiles for finding the profiles configured in the local system.

The first step of all MAPI programs will be to call MAPIInitialize() function, which initializes all the required libraries. At the end of the program, call MAPIUninitialize(), which will unload all the MAPI libraries.

The program should then login to the MS – Exchange Server using the function MapiLogonEx with the profile. This returns a MAPI session handle which can be used in C++ for accessing the Exchange public folders and mail box associated with the profile. This MAPI Session handle is of the type IMAPISession interface, declared in MAPIX.H.

This IMAPISession handle will be used to open the mail box or the public folders and a lot more. This article explains how to open a public folder store and list the folders. If needed to enumerate inbox items refer MAPI – Enumerating emails in C++.

Now, using HrOpenExchangePublicStore and then HrOpenExchangePublicFolders will return the pointer to IMAPIFolder for the root of the public folders. We can use this inside HrMAPIFindSubfolderEx to find if a folder is present inside the public folders hierarchy. Depending on the access permission levels of the connected user, the opened folders can be accessed for read/write operation by the program.

After finding the folder inside the hierarchy,  GetHierarchyTable and HrQueryAllRows functions are used to enumerate the folders inside the “TestFolder”.

C++ MAPI Public Folder – Libraries Required:

Link the MFC used in Shared Dll option in the MFC properties. Add these libraries in the project settings–> Link –> Object/library modules.
mapi32.lib Edkguid.lib Edkutils.lib Edkmapi.lib Addrlkup.lib Edkdebug.lib Version.lib Mblogon.lib.

When the program is compiled, if the ” LINK : fatal error LNK1104: cannot open the file “mfc40.lib” ” is seen, then this problem has to be resolved by Recompiling the MAPI Exchange Development Kit.