How to loop through mailboxes on Exchange by using the GetMailboxTable method (200160)



The information in this article applies to:

  • Microsoft Extended Messaging Application Programming Interface (MAPI)

This article was previously published under Q200160

SUMMARY

When you create mailbox maintenance utility programs, it may be useful to loop through all of the mailboxes on a server and gather information. The code below lists a count of the messages within the Deleted Items folder for each mailbox. The logic used in this code can be used to determine the number of messages in any folder of a mailbox.

MORE INFORMATION

To determine the number of messages in a folder, follow these steps:
  1. Create a MAPI Session pointer and open the private information store of a mailbox that is associated with the service account or some other account with administrative privileges.
  2. Use the GetMailboxTable() method to retrieve the table of mailboxes.
  3. Use the HrMailboxLogon() function to log on to each of the mailboxes.
  4. Specify a folder path included in a call to the HrMAPIOpenFolderEx() function to create a folder pointer.
The following libraries should be included on the Link tab of the Project settings dialog box when the code below is compiled and linked:
  • Advapi32.lib
  • Exchsdk.lib
  • Edkdebug.lib
//This code requires the following libraries: advapi32.lib exchsdk.lib edkdebug.lib
#include <stdio.h>
#include <edk.h>

HRESULT LoopMailboxes(LPMAPISESSION lpMAPISession, 
					  LPSTR pszExchangeServerName);

void main()
{
	HRESULT			hRes = S_OK;
	char			pszExchangeServerName[500];
	LPMAPISESSION	lpMAPISession = NULL;
	LPMDB			lpMDB = NULL;
	
	hRes = MAPIInitialize(NULL);
	if(FAILED(hRes))
	{
		printf("Failed to initialise MAPI\n");
		return;
	}
	
	
	// Get the Exchange Server name from the user
	// 
	printf("Please enter the name of your Exchange Server: ");
	gets(pszExchangeServerName);
	
	// TODO: Logon using a profile for the service account or an Exchange admin
	hRes = MAPILogonEx(
		0, 
		"", 
		NULL,
		MAPI_LOGON_UI | MAPI_NEW_SESSION |  MAPI_EXPLICIT_PROFILE ,
		&lpMAPISession);
	if (FAILED(hRes))
	{
		printf("MAPI Logon failed: %d\n",hRes);
		return;
	}
	
	printf("MAPI session created.\n");
	hRes = LoopMailboxes(lpMAPISession, pszExchangeServerName);
	
	if(FAILED(hRes))
		printf("LoopMailboxes failed: %x\n",hRes);
	else
		printf("Finished looping through mailboxes.\n");
	
	printf("Hit a key to exit.\n");
	while (!_kbhit()) Sleep(50);
	_getch();
	
	if(lpMAPISession) lpMAPISession->Release();
}

HRESULT LoopMailboxes(LPMAPISESSION lpMAPISession, LPSTR pszServerName)
{
	HRESULT      hRes			= S_OK;
	LPMAPITABLE  lpMailBoxTable = NULL;
	LPSRowSet    lpRows         = NULL;
	LPENTRYID    lpMsgStoreID   = NULL;
	ULONG        cbMsgStoreID   = 0;
	LPMDB        lpMDB          = NULL;
	LPMDB        lpUserMDB      = NULL;
	LPMAPIFOLDER lpFolder       = NULL;
	LPSPropValue lpProp			= NULL;
	
	LPEXCHANGEMANAGESTORE lpIManageStore = NULL;
	char pszServerDN[500];
	
	if (FAILED(hRes = HrOpenExchangePrivateStore(lpMAPISession,&lpMDB)))
	{
		printf("Message Store Not Available.\n");
		return MAPI_E_NOT_FOUND;
	}
	
	if (FAILED(hRes = lpMDB->QueryInterface(IID_IExchangeManageStore,
		(void **) &lpIManageStore)))
	{
		printf("QueryInterace Failed.\n");
		return MAPI_E_NOT_FOUND;
	}
	
	// Create server DN
	sprintf(pszServerDN,"/o=microsoft/cn=servers/cn=%s",
		pszServerName);
	
	if (FAILED(hRes = lpIManageStore->GetMailboxTable(pszServerDN,
		&lpMailBoxTable,0)))
	{
		printf("Mailbox Table Not Available.\n");
		return MAPI_E_NOT_FOUND;
	}
	
	// Get a list of Mailboxes taking up resources
	hRes = HrQueryAllRows(lpMailBoxTable, NULL, NULL, NULL, 0, &lpRows);
	
	if(SUCCEEDED(hRes))
	{
		if (lpRows->cRows > 0)
		{
			for (UINT i=0; i < lpRows->cRows; i++)
			{
				LPSPropValue lpspv = PpropFindProp( lpRows->aRow[i].lpProps,
					lpRows->aRow[i].cValues,
					PR_EMAIL_ADDRESS );
				
				//Create Information Store DN
				sprintf(pszServerDN,
					"/o=microsoft/cn=servers/cn=%s%s",
					pszServerName,
					"/cn=Microsoft Private MDB");
				
				hRes = HrMailboxLogon(
					lpMAPISession,
					lpMDB,
					pszServerDN,
					lpspv->Value.lpszA,
					&lpUserMDB);
				if(FAILED(hRes))
				{
					printf(
						"%d Mailbox (%s) Not Available: %d\n",
						i,
						lpspv->Value.lpszA,hRes);
					hRes = S_OK;
					//Since we failed to open the mailbox, skip to the next one.
					continue;
				}
				else
				{
					printf("%d Opened %s \n",i,lpspv->Value.lpszA);
				}
				
				//  ********** Place Mailbox Processing Here **********
				
				hRes = HrGetOneProp(
					lpUserMDB, 
					PR_MESSAGE_SIZE, 
					&lpProp);
				if (FAILED(hRes))
				{
					printf("HrGetOneProp error %x\n",hRes);
				}
				else
				{
					printf("Total Message Size = %d\n",lpProp->Value);
				}
				
				if (lpProp) MAPIFreeBuffer(lpProp);
				lpProp = NULL;
				
				hRes = HrGetOneProp(
					lpUserMDB, 
					PR_CONTENT_COUNT, 
					&lpProp);
				if (FAILED(hRes))
				{
					printf("HrGetOneProp error %x\n",hRes);
				}
				else
				{
					printf("Total Message Count = %d\n",lpProp->Value);
				}
				
				if (lpProp) MAPIFreeBuffer(lpProp);
				lpProp = NULL;
				
				hRes = HrMAPIOpenFolderEx(
					lpUserMDB, 
					'\\', 
					"Top of Information Store\\Deleted Items", 
					&lpFolder);
				if (FAILED(hRes))
				{
					printf("HrMAPIOpenFolderEx error %x\n",hRes);
					//Q194435 PRB: Error "800b0001" From HrMAPIOpenFolderEx()
					if (hRes == 0x800b0001) 
					{
						printf("Mailbox does not contain desired path.\n");
						//Don't return an error
						hRes = S_OK;
					}
				}
				else
				{
					hRes = HrGetOneProp(
						lpFolder, 
						PR_CONTENT_COUNT, 
						&lpProp);
					if (FAILED(hRes))
					{
						printf("HrGetOneProp error %x\n",hRes);
					}
					else
					{
						printf("Delete Message Count = %d\n",lpProp->Value);
					}
					if (lpProp) MAPIFreeBuffer(lpProp);
					lpProp = NULL;

					if (lpFolder) lpFolder->Release();
				}
				if (lpUserMDB) lpUserMDB->Release();
			}
		}
	}
	
	if(lpRows) FreeProws(lpRows);
	if(lpMailBoxTable) lpMailBoxTable->Release();
	return hRes;
}

REFERENCES

You can export folder size information to a text file by using Exchange System Manager. If you want this kind of information in a report to use for management purposes, you can use the text file that is generated from Exchange System Manager without programming.

For more information, click the following article numbers to view the articles in the Microsoft Knowledge Base:

194435 Error "800b0001" from HrMAPIOpenFolderEx()

260141 OpenMsgStore() and HrMailboxLogon() may fail when you open more than 255 mailboxes


Modification Type:MinorLast Reviewed:1/13/2006
Keywords:kbhowto KB200160 kbAudDeveloper