INFO: メッセージを 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で失敗する可能性があります。 これは、構造化されたストレージとストリームに関する既知の問題が原因です。 構造化ストレージに保存されているメッセージに新しい添付ファイルまたは受信者が追加されるたびに、新しいルート ストレージ ファイルが開きます。 これらのファイルは、トランザクションが完了するまで閉じません。 オペレーティング システムでは、同時に開いているルート ストレージ ファイルの数に制限があるため、既知の回避策はありません。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示