Are you a world traveler? ZoneTick is a cool utility that'll help you stay in touch over multiple time zones!
 
Deleting Messages from Folders  
Nik Okuntseff  MS Exchange Server Programming 

Deleting Messages from Folders

To delete all messages from a particular folder the following algorithm and sample code (Folders/Delete) may be used:

#include <afxwin.h>
#include <edk.h>

int main()
{
    /*
     * Algorithm:
     *  1. Logon to MAPI and open message store.
     *  2. Locate and open the desired folder.
     *  3. Get contents table.
     *  4. Scan through it by extracting PR_ENTRYID for each
     *   message and calling the IMAPIFolder::DeleteMessages.
     */

    // Change if necessary
    char * pszFolder = "@PR_IPM_SUBTREE_ENTRYID\\Deleted Items";
 
    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
    SRow row;
    ULONG cbEid = 0;
    LPENTRYID pEid = NULL;
    LPUNKNOWN pCurrentMsg = NULL;
 
    for (ULONG ul = 0; ul < ulRows; ul++)
    {
        row = pRowSet->aRow[ul];

        for (ULONG ulIndex = 0; ulIndex < row.cValues; ulIndex++)
        {
            if (PR_ENTRYID == row.lpProps[ulIndex].ulPropTag)
            {
                SBinary bin;
                bin = row.lpProps[ulIndex].Value.bin;
                assert(bin.cb);
 
                // Construct ENTRYLIST
                ENTRYLIST list;
                list.cValues = 1;
                list.lpbin = &bin;

                // Call IMAPIFolder::DeleteMessages method
                hr = pFolder->DeleteMessages(&list,
                         NULL,
                         NULL,
                         0);
                if (FAILED(hr)) throw -1;
                break;
            }
        }
    }

    // Cleanup
    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;
}

Here I locate and open the default message store for a profile, then locate the desired folder in it by using the HrMAPIOpenFolderEx function. This is a convenient EDK function because you can specify folder by name. Normally MAPI would require doing some additional steps like scanning contents table under the Root folder and checking each subfolder's display name. Notice strange formatting details of the desired folder display name string. One nice thing about this function is that we can specify folder name many levels below the Root, for example:

    char * pszFolder = "@PR_IPM_SUBTREE_ENTRYID\\Deleted Items\\MyNewFolder";
After the folder is opened, I get its contents table. For each row found in it I construct an ENTRYLIST structure consisting of only one entry and call the IMAPIFolder::DeleteMessages function.
 
[ Contents | Home ]

Send comments and suggestions to niko@wrconsulting.com
Copyright © 1997-1998 by Nik Okuntseff