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("%s\n",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 Profile\n",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.