![]() |
General Programming »
Internet / Network »
MAPI
Intermediate
License: The Code Project Open License (CPOL)
Using Account Management API (IOlkAccountManger) to List Outlook Email AccountsBy Ashutosh BhawasinkaAn article on how to use the IOlkAccountManger to get email accounts configured in Outlook |
C++ (VC8.0), Windows, COM, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
This article shows how to use the Account Management APIs to get email accounts configured in Outlook.
The reason for writing this article is that Microsoft didn't provide a header file for the interface used. Moreover, not all the properties of the account are documented by Microsoft.
If you want to skip the technical details and just want to use the feature, follow these steps:
CAccountHelper CAccountHelper GetAccounts passing it the Outlook profile name as shown below: TCHAR szProfile[] = _T("ProfileName"); // Add your outlook profile name here
AccountData *pAccountData = NULL; // This will contain the email account data
DWORD cAccountData = 0; // This will contain the count of the email account
if(FAILED(GetAccounts(szProfile, &cAccountData, &pAccountData)))
{
AfxMessageBox(_T("Failed to get account data"));
return;
}
else
{
for(DWORD i = 0 ; i <cAccountData; i++)
{
_tprintf(_T("Is Exchange account : %d"),pAccountData[i].lIsExchange);
_tprintf(_T("Email ID is : %s"),pAccountData[i].szEmailID);
_tprintf(_T("Incoming Server (POP/IMAP) is : %s"),
pAccountData[i].szIncomingServer);
_tprintf(_T("Outgoing Server is : %s"),pAccountData[i].szOutgoingServer);
_tprintf(_T("Account Stamp : %s"),pAccountData[i].szAccountStamp);
//similarly all other properties
}
}
If you want to implement this yourself, you need to do these things:
IOlkAccountHelper. Let's assume that the class name is CAccountHelper CAccountHelper IID_IOlkAccountManager CAccountHelper IOlkAccountManager:Init passing the CAccountHelper object you created IOlkAccountManager::EnumerateAccounts to get an interface to IOlkEnum IOlkEnum::GetCount to get the accounts count IOlkEnum::Reset IOlkEnum::GetNext to retrieve all the accounts The code for GetAccount which actually does these looks like this:
HRESULT GetAccounts(LPWSTR lpwszProfile, DWORD* pcAccounts, AccountData** ppAccounts)
{
HRESULT hRes = S_OK;
LPMAPISESSION lpSession;
LPOLKACCOUNTMANAGER lpAcctMgr = NULL;
hRes = MAPILogonEx(0,
(LPTSTR)lpwszProfile,
NULL,
fMapiUnicode | MAPI_EXTENDED | MAPI_EXPLICIT_PROFILE |
MAPI_NEW_SESSION | MAPI_NO_MAIL | MAPI_LOGON_UI,
&lpSession);
if(FAILED(hRes))
{
AfxMessageBox(L"Failed to login to the selected profile");
}
hRes = CoCreateInstance(CLSID_OlkAccountManager,
NULL,
CLSCTX_INPROC_SERVER,
IID_IOlkAccountManager,
(LPVOID*)&lpAcctMgr);
if(SUCCEEDED(hRes) && lpAcctMgr)
{
CAccountHelper* pMyAcctHelper = new CAccountHelper(lpwszProfile, lpSession);
if(pMyAcctHelper)
{
LPOLKACCOUNTHELPER lpAcctHelper = NULL;
hRes = pMyAcctHelper->QueryInterface
(IID_IOlkAccountHelper, (LPVOID*)&lpAcctHelper);
if(SUCCEEDED(hRes) && lpAcctHelper)
{
hRes = lpAcctMgr->Init(lpAcctHelper, ACCT_INIT_NOSYNCH_MAPI_ACCTS);
if(SUCCEEDED(hRes))
{
LPOLKENUM lpAcctEnum = NULL;
hRes = lpAcctMgr->EnumerateAccounts(&CLSID_OlkMail,
NULL,
OLK_ACCOUNT_NO_FLAGS,
&lpAcctEnum);
if(SUCCEEDED(hRes) && lpAcctEnum)
{
DWORD cAccounts = 0;
hRes = lpAcctEnum->GetCount(&cAccounts);
if(SUCCEEDED(hRes) && cAccounts)
{
AccountData* pAccounts = new AccountData[cAccounts];
hRes = lpAcctEnum->Reset();
if(SUCCEEDED(hRes))
{
DWORD i = 0;
for (i = 0; i < cAccounts; i++)
{
LPUNKNOWN lpUnk = NULL;
hRes = lpAcctEnum->GetNext(&lpUnk);
if(SUCCEEDED(hRes) && lpUnk)
{
LPOLKACCOUNT lpAccount = NULL;
hRes = lpUnk->QueryInterface(IID_IOlkAccount,
(LPVOID*)&lpAccount);
if(SUCCEEDED(hRes) && lpAccount)
{
ACCT_VARIANT pProp = {0};
//suppress the use of outer hRes
HRESULT hRes = S_OK;
//Account ID
hRes = lpAccount->GetProp
(PROP_ACCT_ID, &pProp);
if(SUCCEEDED(hRes) && pProp.Val.dw)
{
pAccounts[i].lAccountID = pProp.Val.dw;
}
//Account Name
hRes = lpAccount->GetProp(PROP_ACCT_NAME,
&pProp);
if(SUCCEEDED(hRes) && pProp.Val.pwsz)
{
pAccounts[i].szAccountName =
pProp.Val.pwsz;
}
//Is Exchange account flag
hRes = lpAccount->GetProp
(PROP_ACCT_IS_EXCH, &pProp);
if(SUCCEEDED(hRes) && pProp.Val.dw)
{
pAccounts[i].lIsExchange = pProp.Val.dw;
}
else
{
pAccounts[i].lIsExchange = 0;
}
//Account Send Stamp
hRes = lpAccount->GetProp
(PROP_ACCT_SEND_STAMP, &pProp);
if(SUCCEEDED(hRes) && pProp.Val.pwsz)
{
pAccounts[i].szSendStamp = pProp.Val.pwsz;
lpAccount->FreeMemory
((LPBYTE)pProp.Val.pwsz);
}
//similarly retrieve all other properties.
//the sample code has the complete code
//it's been removed from here just for clarity
}
if(lpAccount)
lpAccount->Release();
lpAccount = NULL;
}
if(lpUnk)
lpUnk->Release();
lpUnk = NULL;
}
*pcAccounts = cAccounts;
*ppAccounts = pAccounts;
}
}
}
if(lpAcctEnum)
lpAcctEnum->Release();
}
}
if(lpAcctHelper)
lpAcctHelper->Release();
}
if(pMyAcctHelper)
pMyAcctHelper->Release();
}
if(lpAcctMgr)
lpAcctMgr->Release();
lpSession->Logoff(0,0,0);
lpSession->Release();
return hRes;
}
In the demo application, I have added two buttons "Show Account Dialog" & "Show Add Account Wizard".
The new method added to the interface has this signature:
HRESULT IOlkAccountManager::DisplayAccountList (
HWND hwnd,
DWORD dwFlags,
LPCWSTR lpwszReserved,
DWORD dwReserved,
const CLSID * pclsidReserved1,
const CLSID * pclsidReserved2
);
To use this, I have added this code when the above mentioned buttons are clicked:
LPOLKACCOUNTMANAGER lpAcctMgr = NULL;
hRes = CoCreateInstance(CLSID_OlkAccountManager,
NULL,
CLSCTX_INPROC_SERVER,
IID_IOlkAccountManager,
(LPVOID*)&lpAcctMgr);
if(SUCCEEDED(hRes) && lpAcctMgr)
{
CAccountHelper* pMyAcctHelper = new CAccountHelper(szProfileName, lpSession);
if(pMyAcctHelper)
{
LPOLKACCOUNTHELPER lpAcctHelper = NULL;
hRes = pMyAcctHelper->QueryInterface(IID_IOlkAccountHelper,
(LPVOID*)&lpAcctHelper);
if(SUCCEEDED(hRes) && lpAcctHelper)
{
hRes = lpAcctMgr->Init(lpAcctHelper, ACCT_INIT_NOSYNCH_MAPI_ACCTS);
if(SUCCEEDED(hRes))
{
hRes = lpAcctMgr->DisplayAccountList(this->m_hWnd,dwFlags,0,0,0,0);
if(hRes == MAPI_E_INVALID_PARAMETER)
{
AfxMessageBox(L"dwReserved, pclsidReserved1 or
pclsidReserved2 were non-NULL.");
}
else if(hRes == E_ACCT_UI_BUSY)
{
AfxMessageBox(L"The account dialog class could not be created.");
}
else if( hRes == MAPI_E_USER_CANCEL)
{
AfxMessageBox(L"The Account Settings dialog box returned an error.");
}
else if(hRes == MAPI_E_CALL_FAILED)
{
AfxMessageBox(L"The Add New E-Mail property sheet
returned an error.");
}
}
else
{
AfxMessageBox(L"Failed to initialize IOlkAccountManager");
}
lpAcctHelper>Release();
}
else
{
AfxMessageBox(L"Failed to get Account Helper interface");
}
pMyAcctHelper->Release();
}
else
{
AfxMessageBox(L"Oops!!! Out of memory");
}
lpAcctMgr->Release();
}
else
{
AfxMessageBox(L"Ohhhhhhh No!!! failed to get IOlkAccountManager interface");
}
Exchange accounts don't have an incoming or outgoing server. Also the email ID for the exchange account is not in the normal form we see to like. To get mailbox server or email ID of the exchange account, you need to open the Global profile section of the profile.
The mailbox server name is stored in the property tag:
PR_INTERNET_CONTENT_ID PROP_TAG(PT_UNICODE, 0x662A)
The email ID is in general stored in these property tags:
PROP_EXCHANGE_EMAILID PROP_TAG(PT_UNICODE, 0x663D) //email ID
PROP_EXCHANGE_EMAILID2 PROP_TAG(PT_UNICODE, 0x6641) //email ID
In some exchange 2000 accounts, you won't find these properties. In that case, you have to get the IMailUse interface of the user, then query for PR_SMTP_ADDRESS property.
For further reading, you may refer to Account Management API Reference.
| You must Sign In to use this message board. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 28 Aug 2008 Editor: Deeksha Shenoy |
Copyright 2008 by Ashutosh Bhawasinka Everything else Copyright © CodeProject, 1999-2009 Web18 | Advertise on the Code Project |