정보: MSG 복합 파일에 메시지 저장

요약

이 문서에는 복합 문서, 특히 .msg 파일 형식을 지원하는 모든 클라이언트에서 읽을 수 있는 .msg 파일에 메시지를 저장하는 방법을 보여 주는 코드가 포함되어 있습니다.

추가 정보

아래 함수는 유효한 메시지 개체를 in 매개 변수로 사용하고 해당 속성을 사용하여 메시지의 중복을 만들고 .msg 형식을 사용하여 복합 파일에 저장합니다. 메시지의 제목 줄은 새 파일의 파일 이름으로 사용됩니다.

참고

이 함수의 in 매개 변수의 제목 줄에 특수 문자가 있으면 예기치 않은 결과가 발생할 수 있습니다. 제목 줄에서 특수 문자를 방지하기 위해 코드를 작성할 수 있지만 토픽에 대한 게르만은 아니며 이러한 코드는 의도적으로 제외됩니다.

#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;
}

모든 버전의 Outlook 및 Exchange 클라이언트 지원은 복합 문서로 CLSID_MailMessage. 다른 CLSID를 사용하는 유일한 이유는 구조적 스토리지에 메시지를 쓸 때 다른 CLISD를 사용하는 다른 클라이언트를 지원하기 위한 것입니다.

많은 수의 받는 사람 또는 첨부 파일이 있는 메시지를 저장할 때 CopyTo 작업이 MAPI_E_NOT_ENOUGH_MEMORY 함께 실패할 수 있습니다. 이는 구조화된 스토리지 및 스트림의 알려진 문제 때문입니다. 구조화된 스토리지에 저장되는 메시지에 새 첨부 파일 또는 받는 사람이 추가될 때마다 새 루트 스토리지 파일이 열립니다. 이러한 파일은 트랜잭션이 완료될 때까지 닫혀 있지 않습니다. 운영 체제는 동시에 열려 있는 루트 스토리지 파일 수에 제한을 적용하므로 알려진 해결 방법은 없습니다.