Modifying Message Properties in Folders
| Nik Okuntseff |
MS Exchange Server Programming |
Modifying Message Properties in Folders
Let us suppose that we need to replace a specific property of a message
with the same property from another message. For the sake of simplicity
let us assume that both messages reside in Inbox. How do we go about it?
The program below (Folders/ReplaceProps) does it by first locating and
opening the profile's Inbox, opening both messages and then doing IMAPIProp::CopyProps
operation.
#include <afxwin.h>
#include <edk.h>
int main()
{
// Change if necessary
char * pszSourceMsgSubject = "Source";
char * pszTargetMsgSubject = "Target";
HRESULT hr;
LPMAPISESSION pSession = NULL;
// Initialize MAPI
hr = MAPIInitialize(NULL);
if (FAILED(hr)) throw -1;
// Obtain MAPI session
hr = MAPILogonEx(0, // Handle
to parent window
"MS Exchange Settings", // Profile name
NULL, // Password
MAPI_NEW_SESSION |
MAPI_EXTENDED |
MAPI_LOGON_UI, // Logon flags
&pSession); // Resulting MAPI
session
if (FAILED(hr)) throw -1;
// Find default message store
ULONG cbDefStoreEid = 0;
LPENTRYID pDefStoreEid = NULL;
hr = HrMAPIFindDefaultMsgStore(pSession, &cbDefStoreEid,
&pDefStoreEid);
if (FAILED(hr)) throw -1;
// Open default message store
LPMDB pDefMsgStore = NULL;
hr = pSession->OpenMsgStore(0, cbDefStoreEid, pDefStoreEid,
NULL,
MDB_WRITE | MAPI_DEFERRED_ERRORS,
&pDefMsgStore);
if (FAILED(hr)) throw -1;
// Locate Inbox
ULONG cbInboxEid = 0;
LPENTRYID pInboxEid = NULL;
hr = HrMAPIFindInbox(pDefMsgStore, &cbInboxEid,
&pInboxEid);
if (FAILED(hr)) throw -1;
// Try to open the Inbox
ULONG ulObjType = 0;
LPMAPIFOLDER pInbox = NULL;
hr = pDefMsgStore->OpenEntry(cbInboxEid,
pInboxEid,
NULL,
MAPI_BEST_ACCESS,
&ulObjType,
(LPUNKNOWN *) &pInbox);
if (FAILED(hr)) throw -1;
// Get contents table...
LPMAPITABLE pContentsTable = NULL;
hr = pInbox->GetContentsTable(0, &pContentsTable);
if (FAILED(hr)) throw -1;
// Get row count
ULONG ulRows = 0;
hr = pContentsTable->GetRowCount(0, &ulRows);
if (FAILED(hr)) throw -1;
assert(ulRows > 0);
// Get all rows
SRowSet * pRowSet = NULL;
hr = pContentsTable->QueryRows(ulRows, 0, &pRowSet);
assert(ulRows == pRowSet->cRows);
// Scan all rows to locate source and target messages
SRow row;
ULONG cbEid = 0;
LPENTRYID pEid = NULL;
LPUNKNOWN pSourceMsg = NULL;
LPUNKNOWN pTargetMsg = NULL;
for (ULONG ul = 0; ul < ulRows; ul++)
{
row = pRowSet->aRow[ul];
for (ULONG ulIndex = 0; ulIndex
< row.cValues; ulIndex++)
{
if (PR_SUBJECT == row.lpProps[ulIndex].ulPropTag)
{
char * pszCurSubject = row.lpProps[ulIndex].Value.lpszA;
int iRes = memcmp(pszSourceMsgSubject,
pszCurSubject,
strlen(pszSourceMsgSubject));
if (0 == iRes)
{
// We have found the source message!
// Get PR_ENTRYID
SBinary bin;
ZeroMemory(&bin, sizeof(bin));
for (ULONG ulNewIndex = 0; ulNewIndex < row.cValues; ulNewIndex++)
{
if (PR_ENTRYID == row.lpProps[ulNewIndex].ulPropTag)
{
bin = row.lpProps[ulNewIndex].Value.bin;
break;
}
}
assert(bin.cb);
// Open the source message
hr = pDefMsgStore->OpenEntry(bin.cb,
(LPENTRYID) bin.lpb,
NULL,
MAPI_BEST_ACCESS,
&ulObjType,
&pSourceMsg);
if (FAILED(hr)) throw -1;
}
iRes = memcmp(pszTargetMsgSubject,
pszCurSubject,
strlen(pszTargetMsgSubject));
if (0 == iRes)
{
// We have found the target message!
// Get PR_ENTRYID
SBinary bin;
ZeroMemory(&bin, sizeof(bin));
for (ULONG ulNewIndex = 0; ulNewIndex < row.cValues; ulNewIndex++)
{
if (PR_ENTRYID == row.lpProps[ulNewIndex].ulPropTag)
{
bin = row.lpProps[ulNewIndex].Value.bin;
break;
}
}
assert(bin.cb);
// Open the target message
hr = pDefMsgStore->OpenEntry(bin.cb,
(LPENTRYID) bin.lpb,
NULL,
MAPI_BEST_ACCESS,
&ulObjType,
&pTargetMsg);
if (FAILED(hr)) throw -1;
}
break;
}
}
}
// At this point we should have the source and target
messages open...
assert(pSourceMsg);
assert(pTargetMsg);
SPropTagArray tagArray;
tagArray.cValues = 1;
// Copy PR_SUBJECT property from source message to
target.
/*
* Be careful what you copy. Some properties
such as PR_BODY
* are computed. The CopyProps still succeeds.
*/
tagArray.aulPropTag[0] = PR_SUBJECT;
hr = ((LPMAPIPROP) pSourceMsg)->CopyProps(&tagArray,
NULL, NULL,
&IID_IMAPIProp, pTargetMsg, 0, NULL);
if (FAILED(hr)) throw -1;
// Save changes
hr = ((LPMAPIPROP) pTargetMsg)->SaveChanges(0/*KEEP_OPEN_READWRITE*/);
if (FAILED(hr)) throw -1;
// Cleanup
if (pTargetMsg)
pTargetMsg->Release();
if (pSourceMsg)
pSourceMsg->Release();
if (pRowSet)
MAPIFreeBuffer(pRowSet);
if (pContentsTable)
pContentsTable->Release();
if (pInbox)
pInbox->Release();
if (pInboxEid)
MAPIFreeBuffer(pInboxEid);
if (pDefMsgStore)
pDefMsgStore->Release();
if (pDefStoreEid)
MAPIFreeBuffer(pDefStoreEid);
if (pSession)
pSession->Release();
::MAPIUninitialize();
return 0;
}
There is one thing that you should know about. Some of message properties
are computed from others. For example, I have tried to modify PR_BODY,
and program did not fail at any point. However, when I opened the target
message in Outlook, I did not see my changes. This is because my message
had RTF content, and PR_BODY is in fact calculated from one of PR_RTF_...
properties. Everything should work fine with PR_SUBJECT. The program assumes
that messages with "Source" and "Target" subjects exist in the profile
mailbox.
[ Contents |
Home
]
Send comments and suggestions to niko@wrconsulting.com
Copyright © 1997-1998 by Nik Okuntseff
|