How to retrieve/get TO, CC, BCC recipient address of an email through CEMAPI (C++) in Windows Mobile device?
====>SiteMap of this Blog<===
How to retrieve/get TO, CC, BCC recipient address of an email through CEMAPI (C++) in Windows Mobile device?
Whenever you deal with email application through MAPI (or, CEMAPI, the trimmed version in Windows Mobile devices), quite possibly you need to load TO addresses, CC addresses from a given email message (or BCC addresses in case the message is in "draft" folder or "Sent Item" folder) . For example, when developing a mail transport, you not only need to synchronize the account's inbox with the remote server, but also have to deal with outgoing messages. Inevitably, you have to know TO/CC/BCC of any outgoing message.
Intuitive thought is to query them as corresponding properties from the message object IMessage using its GetProps method. Although the CEMAPI documentation is scarce, one can still find such properties from the header files:
- PR_DISPLAY_BCC
- PR_DISPLAY_CC
- PR_DISPLAY_TO
Unfortunately all of three properties returned me empty strings, at least in Pocket PC 2003 devices. Time to take a google search to see whether other people ran into the same issue. I did find two fellow clueless guys, who posted the question but got no useful answers:
- How to get TO, CC, BCC address list from IMessage object?
- how to retrive the cc and bcc recipient of an email through cemapi in evc 4.0
So I had to take the more complex approach, using the recipient table. Every message has a recipient table. Each record in the recipient table is a recipient, and has a couple of properties/columns. As with any other MAPI stuff, an email address is a property, a recipient's name is also a property, and an address type (TO/CC/BCC) is also a property.
So I changed my simple code to a slightly longer one:
- opening the recipient table by calling GetRecipientTable,
- setting the interested properties by calling SetColumns,
- iterating through the table record-by-record by calling QueryRows
Heck! This seemingly perfect and innocent code still did not work. After a debug, I soon realized that SetColumns returns a COM error meaning not implemented. Not surprisingly, CEMAPI is not the full-fleged MAPI in the desktop world, and here we tasted a slight bitterness.
So the natural solution is to loop though all the properties for each record, and figure out the type of each property. The number of the properties for each recipient is SRow.cValues, and the type of each property is specified in SPropValue.ulPropTag. Below is a code snippet:
// the hack is to loop through all rows without limiting the columnsHRESULT hr = pMessage->GetRecipientTable(0, &pRecipientTable);
EXIT_ON_FAILED(hr);
// iterate all the recipients
while (TRUE) {
hr = pRecipientTable->QueryRows(1, 0, &pRows);
if (FAILED(hr) || !pRows || pRows->cRows != 1) break;
// nProps is the number of columns in the recipient table
int nProps = pRows->aRow[0].cValues;
ULONG ulReceipType = 0;
// loop through all the properties
for (int ii = 0; ii < nProps; ii++) {
ULONG ulPT = pRows->aRow[0].lpProps[ii].ulPropTag;
switch (ulPT) {
case PR_EMAIL_ADDRESS:
// This is the email address
szReceipEmail = pRows->aRow[0].lpProps[ii].Value.LPSZ;
break;
case PR_RECIPIENT_TYPE:
// this is the recipient type: TO/CC/BCC
ulReceipType = pRows->aRow[0].lpProps[ii].Value.ul;
break;
case PR_DISPLAY_NAME:
// this is the display name
szReceipName = pRows->aRow[0].lpProps[ii].Value.LPSZ;
break;
default:
break;
} // switch
}
}
Category: [Outlook / Transport / MAPI]