INFO: Uložení zprávy do složeného souboru MSG

Souhrn

Tento článek obsahuje kód, který ukazuje, jak uložit zprávu do složeného dokumentu, konkrétně .msg souboru, který je čitelný všemi klienty, kteří podporují formát souboru .msg.

Další informace

Následující funkce přebírá platný objekt zprávy jako parametr in a používá jeho vlastnosti k vytvoření duplikátu zprávy a jeho uložení do složeného souboru ve formátu .msg. Řádek předmětu zprávy se použije jako název souboru nového souboru.

Poznámka

Speciální znaky v řádku předmětu parametru in této funkce mohou způsobit neočekávané výsledky. I když je možné kód napsat tak, aby se zabránilo speciálním znakům v řádku předmětu, není to pro téma němčina a takový kód je záměrně vynecháný.

#define INITGUID
#include <objbase.h>

#define USES_IID_IMessage

#include <mapix.h>
#include <mapitags.h>
#include <mapidefs.h>
#include <mapiutil.h>
#include <mapiguid.h>
#include <imessage.h>

// {00020D0B-0000-0000-C000-000000000046}
DEFINE_GUID(CLSID_MailMessage,
0x00020D0B,
0x0000, 0x0000, 0xC0, 0x00, 0x0, 0x00, 0x0, 0x00, 0x00, 0x46);

HRESULT SaveToMSG ( LPMESSAGE pMessage )
{
 HRESULT hRes = S_OK;
 LPSPropValue pSubject = NULL;
 LPSTORAGE pStorage = NULL;
 LPMSGSESS pMsgSession = NULL;
 LPMESSAGE pIMsg = NULL;
 SizedSPropTagArray ( 7, excludeTags );
 char szPath[_MAX_PATH];
 char strAttachmentFile[_MAX_PATH];
 LPWSTR lpWideCharStr = NULL;
 ULONG cbStrSize = 0L;

// create the file name in the directory where "TMP" is defined
 // with subject as the filename and ".msg" extension.

// get temp file directory
 GetTempPath(_MAX_PATH, szPath);

// get subject line of message to copy. This will be used as the
 // new file name.
 HrGetOneProp( pMessage, PR_SUBJECT, &pSubject );

// fuse path, subject, and suffix into one string
 strcpy ( strAttachmentFile, szPath );
 strcat ( strAttachmentFile, pSubject->Value.lpszA );
 strcat ( strAttachmentFile, ".msg");

// get memory allocation function
 LPMALLOC pMalloc = MAPIGetDefaultMalloc();

// Convert new file name to WideChar
 cbStrSize = MultiByteToWideChar (CP_ACP,
 MB_PRECOMPOSED,
 strAttachmentFile,
 -1, lpWideCharStr, 0);

MAPIAllocateBuffer ( cbStrSize * sizeof(WCHAR),
 (LPVOID *)&lpWideCharStr );

MultiByteToWideChar (CP_ACP,
 MB_PRECOMPOSED,
 strAttachmentFile,
 -1, lpWideCharStr, cbStrSize );

// create compound file
 hRes = ::StgCreateDocfile(lpWideCharStr,
 STGM_READWRITE |
 STGM_TRANSACTED |
 STGM_CREATE, 0, &pStorage);

// Open an IMessage session.
 hRes = ::OpenIMsgSession(pMalloc, 0, &pMsgSession);

// Open an IMessage interface on an IStorage object
 hRes = ::OpenIMsgOnIStg(pMsgSession,
 MAPIAllocateBuffer,
 MAPIAllocateMore,
 MAPIFreeBuffer,
 pMalloc,
 NULL,
 pStorage,
 NULL, 0, 0, &pIMsg);

// write the CLSID to the IStorage instance - pStorage. This will
 // only work with clients that support this compound document type
 // as the storage medium. If the client does not support
 // CLSID_MailMessage as the compound document, you will have to use
 // the CLSID that it does support.
 hRes = WriteClassStg(pStorage, CLSID_MailMessage );

// Specify properties to exclude in the copy operation. These are
 // the properties that Exchange excludes to save bits and time.
 // Should not be necessary to exclude these, but speeds the process
 // when a lot of messages are being copied.
 excludeTags.cValues = 7;
 excludeTags.aulPropTag[0] = PR_ACCESS;
 excludeTags.aulPropTag[1] = PR_BODY;
 excludeTags.aulPropTag[2] = PR_RTF_SYNC_BODY_COUNT;
 excludeTags.aulPropTag[3] = PR_RTF_SYNC_BODY_CRC;
 excludeTags.aulPropTag[4] = PR_RTF_SYNC_BODY_TAG;
 excludeTags.aulPropTag[5] = PR_RTF_SYNC_PREFIX_COUNT;
 excludeTags.aulPropTag[6] = PR_RTF_SYNC_TRAILING_COUNT;

// copy message properties to IMessage object opened on top of
 // IStorage.
 hRes = pMessage->CopyTo(0, NULL,
 (LPSPropTagArray)&excludeTags,
 NULL, NULL,
 (LPIID)&IID_IMessage,
 pIMsg, 0, NULL );

// save changes to IMessage object.
 pIMsg -> SaveChanges ( KEEP_OPEN_READWRITE );

// save changes in storage of new doc file
 hRes = pStorage -> Commit(STGC_DEFAULT);

// free objects and clean up memory
 MAPIFreeBuffer ( lpWideCharStr );
 pStorage->Release();
 pIMsg->Release();
 CloseIMsgSession ( pMsgSession );

pStorage = NULL;
 pIMsg = NULL;
 pMsgSession = NULL;
 lpWideCharStr = NULL;

return hRes;
}

Všechny verze outlooku a klienta Exchange podporují CLSID_MailMessage jako složený dokument. Jediným důvodem pro použití jiného identifikátoru CLSID je podpora jiných klientů, kteří při psaní zpráv do strukturovaného úložiště používají jiný identifikátor CLISD.

Při ukládání zpráv, které mají velký počet příjemců nebo příloh, je možné, že operace CopyTo selže s MAPI_E_NOT_ENOUGH_MEMORY. Důvodem je známý problém se strukturovaným úložištěm a datovými proudy. Pokaždé, když se do zprávy uložené ve strukturovaném úložišti přidá nová příloha nebo příjemce, se otevře nový soubor kořenového úložiště. Tyto soubory nejsou uzavřeny, dokud transakce není dokončena. Vzhledem k tomu, že operační systém omezuje počet současně otevřených souborů kořenového úložiště, neexistuje žádné známé alternativní řešení.