[INFO] MSG 複合ファイルへのメッセージの保存

サポート期間が終了した「サポート技術情報」資料に関する免責事項
この資料は、マイクロソフトでサポートされていない製品について記述したものです。そのため、この資料は現状ベースで提供されており、今後更新されることはありません。
概要
この資料では、.msg ファイル形式をサポートしているクライアントから読み取り可能な複合ドキュメント (.msg ファイル) にメッセージを保存する方法を示すサンプル コードを紹介します。
詳細
以下の関数では、有効なメッセージ オブジェクトを入力パラメータとして取得し、メッセージ オブジェクトのプロパティを使用してメッセージの複製を作成し、.msg 形式を使用する複合ファイルに保存します。メッセージの件名が、新しいファイルのファイル名として使用されます。

注 : この関数の入力パラメータの件名に特殊文字が含まれていると、予期しない結果になることがあります。件名に特殊文字を使用しないようにするコードの作成も可能ですが、この資料の目的からは外れるため、ここではそのようなコードは取り上げません。

注 : メッセージが大きすぎる場合、以下のコードの pMessage->CopyTo で MAPI_E_NOT_ENOUGH_MEMORY が返されることがあります。非常に多くの受信者や添付ファイルが含まれている場合も同じ結果になる可能性があります。このメッセージは、コードを実行しているコンピュータに、処理を完了するための十分な空き容量がないことを示します。他のプログラムを終了してメモリを解放するか、コンピュータにメモリを追加すると、この問題は解決されます。
#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;    // "TMP" が定義されているディレクトリに、    //  件名と .msg 拡張子から成るファイル名を作成します。    // 一時ファイルのディレクトリを取得します。    GetTempPath(_MAX_PATH, szPath);    // コピーするメッセージの件名を取得します。    // この件名が新しいファイル名として使用されます。    HrGetOneProp( pMessage, PR_SUBJECT, &pSubject );    // パス、件名、および拡張子を 1 つの文字列に統合します。    strcpy ( strAttachmentFile, szPath );    strcat ( strAttachmentFile, pSubject->Value.lpszA  );    strcat ( strAttachmentFile, ".msg");    // メモリ割り当て関数を取得します。    LPMALLOC pMalloc = MAPIGetDefaultMalloc();    // 新しいファイル名を 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 );    // 複合ファイルを作成します。    hRes = ::StgCreateDocfile(lpWideCharStr,                              STGM_READWRITE |                              STGM_TRANSACTED |                              STGM_CREATE, 0, &pStorage);    // IMessage セッションを開きます。    hRes = ::OpenIMsgSession(pMalloc, 0, &pMsgSession);    // IStorage オブジェクト上で IMessage インターフェイスを開きます。    hRes = ::OpenIMsgOnIStg(pMsgSession,                            MAPIAllocateBuffer,                            MAPIAllocateMore,                            MAPIFreeBuffer,                            pMalloc,                            NULL,                            pStorage,                            NULL, 0, 0, &pIMsg);    // CLSID を IStorage インスタンス - pStorage に書き込みます。この処理は、    // ストレージ メディアとしてこの種類の複合ドキュメントをサポートしている    // クライアントでのみ機能します。クライアントが CLSID_MailMessage を    // 複合ドキュメントとしてサポートしていない場合、そのクライアントが    // サポートしている CLSID を使用する必要があります。    hRes = WriteClassStg(pStorage, CLSID_MailMessage );    // コピー操作から除外するプロパティを指定します。Exchange でこれらのプロパティを    // 除外することにより、必要なビット数と処理時間を節約します。    // これらのプロパティを除外しなくてもかまいませんが、大量のメッセージをコピーする    // 場合は除外した方が処理が速くなります。    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;    // IStorage の一番上の、開かれた IMessage オブジェクトにメッセージ プロパティを    // コピーします。    hRes = pMessage->CopyTo(0, NULL,                            (LPSPropTagArray)&excludeTags,                            NULL, NULL,                            (LPIID)&IID_IMessage,                            pIMsg, 0, NULL );    // IMessage オブジェクトに変更を保存します。    pIMsg -> SaveChanges ( KEEP_OPEN_READWRITE );    // 新しいドキュメント ファイルのストレージに変更を保存します。    hRes = pStorage -> Commit(STGC_DEFAULT);    // オブジェクトを解放してメモリをクリーンアップします。    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 が返されることがあります。この現象は、構造化ストレージおよびストリームの既知の問題によって発生します。構造化ストレージに保存されているメッセージに新しい添付ファイルまたは受信者を追加するごとに、新しいルート ストレージ ファイルが開きます。これらのファイルは、トランザクションが完了するまで閉じられません。オペレーティング システムによって同時に開くストレージ ファイルの数が制限されるため、この問題を回避する方法は確認されていません。関連情報を参照するには、以下の「サポート技術情報」 (Microsoft Knowledge Base) をクリックしてください。
163202 Limit of the Number of Simultaeously Open Root Storage Files
163202 [NT]同時オープン ルートストレージ ファイル数の限界
Outlook のすべてのバージョンもこの制限の影響を受けます。
関連情報
この資料は米国 Microsoft Corporation から提供されている Knowledge Base の Article ID 171907 (最終更新日 2001-12-07) をもとに作成したものです。

この資料に含まれているサンプル コード/プログラムは英語版を前提に書かれたものをありのままに記述しており、日本語環境での動作は確認されておりません。
プロパティ

文書番号:171907 - 最終更新日: 08/25/2005 18:04:37 - リビジョン: 2.3

Microsoft Messaging Application Programming Interface, Microsoft Exchange Client 5.0, Microsoft Exchange Client 5.5, Microsoft Exchange Client 4.0, Microsoft Exchange Client 5.0

  • kbinfo kbmsg KB171907
フィードバック