Accessing Message Attachments
| Nik Okuntseff |
MS Exchange Server Programming |
Accessing Message Attachments
How can we access message attachments? Let's suppose we need to save a
message attachment as a file. This is how it may be accomplished:
#include <afxwin.h>
#include <edk.h>
int main()
{
/*
* Algorithm:
* 1. Open the message.
* 2. Open its attachment.
* 3. Create a file and store PR_ATTACH_DATA_BIN
in it.
*/
// Change if necessary
char * pszFolder = "@PR_IPM_SUBTREE_ENTRYID\\Drafts";
char * pszMsgSubject = "Message with Attachment";
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;
// Open the desired folder
LPMAPIFOLDER pFolder = NULL;
hr = HrMAPIOpenFolderEx(pDefMsgStore,
'\\',
pszFolder,
&pFolder);
if (FAILED(hr)) throw -1;
// Get contents table.
LPMAPITABLE pContentsTable = NULL;
hr = pFolder->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 until we have our source message
SRow row;
LPUNKNOWN pMsg = NULL;
ULONG ulObjType = 0;
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(pszMsgSubject, pszCurSubject, strlen(pszMsgSubject));
if (0 == iRes)
{
// We have found our 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 message
hr = pDefMsgStore->OpenEntry(bin.cb,
(LPENTRYID) bin.lpb,
NULL,
MAPI_BEST_ACCESS,
&ulObjType,
&pMsg);
if (FAILED(hr)) throw -1;
}
}
}
}
// At this point we have the message open...
// Open its attachment
LPMAPITABLE pAttachTbl = NULL;
hr = ((LPMESSAGE) pMsg)->GetAttachmentTable(0, &pAttachTbl);
if (FAILED(hr)) throw -1;
// Get row count
hr = pAttachTbl->GetRowCount(0, &ulRows);
if (FAILED(hr)) throw -1;
assert(1 == ulRows);
// Get all rows
if (pRowSet)
MAPIFreeBuffer(pRowSet);
pRowSet = NULL;
hr = pAttachTbl->QueryRows(ulRows, 0, &pRowSet);
assert(ulRows == pRowSet->cRows);
// Get PR_ATTACH_NUM
row = pRowSet->aRow[0];
LPATTACH pAttach = NULL;
ULONG ulAttachNum = 0;
for (ULONG ulIndex = 0; ulIndex < row.cValues;
ulIndex++)
{
if (PR_ATTACH_NUM == row.lpProps[ulIndex].ulPropTag)
{
// Open the attachment.
ulAttachNum = row.lpProps[ulIndex].Value.l;
hr = ((LPMESSAGE) pMsg)->OpenAttach(ulAttachNum,
NULL,
MAPI_BEST_ACCESS,
&pAttach);
if (FAILED(hr)) throw -1;
break;
}
}
// At this point we should have the attachment open
// Get PR_ATTACH_DATA_BIN property
SPropTagArray tagArray;
tagArray.cValues = 1;
tagArray.aulPropTag[0] = PR_ATTACH_DATA_BIN;
ULONG ulValues = 0;
LPSPropValue pAttachDataBin = NULL;
hr = pAttach->GetProps(&tagArray,
0,
&ulValues,
&pAttachDataBin);
if (FAILED(hr)) throw -1;
assert(pAttachDataBin);
// Create a file to write data to
HANDLE hFile = CreateFile("C:\\AttachData.txt",
GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
assert(hFile != INVALID_HANDLE_VALUE);
// Save data
DWORD dwBytesWritten = 0;
BOOL b = WriteFile(hFile, // Handle to the file
pAttachDataBin->Value.bin.lpb, // Pointer
to data to write to file
pAttachDataBin->Value.bin.cb, // Number
of bytes to write
&dwBytesWritten,
// Number of bytes written
NULL);
// Pointer to OVERLAPPED structure
assert(b && (dwBytesWritten == pAttachDataBin->Value.bin.cb));
// Cleanup
if (hFile)
CloseHandle(hFile);
if (pAttachDataBin)
MAPIFreeBuffer(pAttachDataBin);
if (pAttach)
pAttach->Release();
if (pAttachTbl)
pAttachTbl->Release();
if (pMsg)
pMsg->Release();
if (pRowSet)
MAPIFreeBuffer(pRowSet);
if (pContentsTable)
pContentsTable->Release();
if (pFolder)
pFolder->Release();
if (pDefMsgStore)
pDefMsgStore->Release();
if (pDefStoreEid)
MAPIFreeBuffer(pDefStoreEid);
if (pSession)
pSession->Release();
::MAPIUninitialize();
return 0;
}
The algorithm is straightforward. I assume that the message resides
in the Drafts folder, has "Message with Attachment" subject, and in fact
contains 1 attachment.
[ Contents |
Home
]
Send comments and suggestions to niko@wrconsulting.com
Copyright © 1997-1998 by Nik Okuntseff
|