INTRODUCTION
The Microsoft Outlook object model provides access to the body of an e-mail message in native format. This access is accomplished by checking the
BodyFormat property to determine what format that the e-mail message is in. Then, the appropriate body property is accessed. However, Microsoft Office XP Service Pack 3 and Microsoft Office 2003 introduced tighter security features that cause warning dialog boxes to appear when an application or a Microsoft Outlook add-in tries to access the body of the e-mail message.
The dialog boxes can be avoided by using Extended MAPI to access the body of the e-mail message instead of using the Outlook object model. However, Extended MAPI cannot always access the body of the e-mail message in its native format. When the body of the e-mail message is stored in PR_RTF_COMPRESSED format, the body of the e-mail message must be in Rich Text Format (RTF). Otherwise, the format is undocumented and is therefore unavailable to you.
To address this limitation, we have added a new, exported function that is named
WrapCompressedRTFStreamEx to the implementation of Extended MAPI, also known as Msmapi32.dll, in Outlook 2002 and in Outlook 2003. The
WrapCompressedRTFStreamEx function lets you access the native body stream that is encapsulated in PR_RTF_COMPRESSED format and then determine what format the stream is in.
This feature is available in the latest service pack for Office 2003. For more information, click the following article number to view the article in the Microsoft Knowledge Base:
870924 How to obtain the latest service pack for Office 2003
MORE INFORMATION
Function definition
HRESULT __stdcall WrapCompressedRTFStreamEx(
LPSTREAM lpCompressedRTFStream,
CONST RTF_WCSINFO * pWCSInfo,
LPSTREAM * lppUncompressedRTFStream,
RTF_WCSRETINFO * pRetInfo
);
ParameterslpCompressedRTFStream[in] This is a pointer to a stream that is opened on the
PR_RTF_COMPRESSED property of a message.
pWCSInfo[in] This is a pointer to a RTF_WCSINFO structure that contains options for the function. See the "New flags and structures" section for additional details about this structure.
lppUncompressedRTFStream[out] This is a pointer to the location where the
WrapCompressedRTFStream function returns a stream for the decompressed RTF.
pRetInfo[out] This is a pointer to a RTF_WCSRETINFO structure that contains information about the format of the returned decompressed stream. See the "New flags and structures" section for additional details about this structure.
Return ValuesS_OK | The call succeeded and returned the expected value or values. |
MAPI_E_INVALID_PARAMETER | This is returned if the MAPI_NATIVE_BODY flag is combined with the MAPI_MODIFY flag in ulFlags. |
RemarksTo use the
WrapCompressedRTFStreamEx function, you must load Msmapi32.dll by using the
LoadLibrary function. Then, retrieve a function pointer to the
WrapCompressedRTFStreamEx function by using the
GetProcAddress function.
Because the MAPI_NATIVE_BODY flag cannot be combined with the MAPI_MODIFY flag, you can only access the native body stream in read-only mode.
To access the native body stream in read/write mode, we recommend that you use the
WrapCompressedRTFStream function.
For additional information about the
WrapCompressedRTFStream function, visit the following Microsoft Developer Network (MSDN) Web site:
New flags and structures
The
WrapCompressedRTFStreamEx function uses the following new flags that are not defined in the current version of Mapidefs.h:
#define MAPI_NATIVE_BODY 0x00010000
#define MAPI_NATIVE_BODY_TYPE_RTF 0x00000001
#define MAPI_NATIVE_BODY_TYPE_HTML 0x00000002
#define MAPI_NATIVE_BODY_TYPE_PLAINTEXT 0x00000004
RTF_WCSINFO structureThe RTF_WCSINFO structure is defined as follows:
typedef struct {
ULONG size;
ULONG ulFlags;
ULONG ulInCodePage;
ULONG ulOutCodePage;
} RTF_WCSINFO;
MemberssizeThis is the size of the RTF_WCSINFO structure.
ulFlagsThis is the bitmask of option flags for the function. The following flags can be set:
MAPI_MODIFY | This indicates whether the client intends to read or to write the wrapped stream interface that is returned. |
STORE_UNCOMPRESSED_RTF | This indicates whether the decompressed RTF is supposed to be written to the stream that is pointed to by the lpCompressedRTFStream pointer. |
MAPI_ NATIVE_BODY | This indicates whether the decompressed stream is additionally converted to the native body before returning the stream.
Important This cannot be combined with the MAPI_MODIFY flag. |
ulInCodePageThis is the code page value of the message. Typically, this value is obtained from the
PR_INTERNET_CPID property on the message. This value is only used when the MAPI_NATIVE_BODY flag is passed in ulFlags. Otherwise, this value is ignored.
ulOutCodePageThis is the code page value of the returned decompressed stream that you want. If this is set to a non-zero value, the
WrapCompressedRTFStreamEx function converts the stream to the specified code page. If this is set to a zero value, MAPI decides which code page to use. This value is only used when the MAPI_NATIVE_BODY flag is passed in ulFlags, and the body format is not RTF. Otherwise, this value is ignored.
RTF_WCSRETINFO structureThe RTF_WCSRETINFO structure is defined as follows:
typedef struct {
ULONG size;
ULONG ulStreamFlags;
} RTF_WCSRETINFO;
MemberssizeThis is the size of the RTF_WCSRETINFO structure.
ulStreamFlagsThis is a value that indicates the format of the native body. This value is only valid if the MAPI_NATIVE_BODY flag is passed in the ulFlags parameter of the RTF_WCSINFO structure that is passed to the
WrapCompressedRTFStreamEx function. This can be one of the following values:
MAPI_NATIVE_BODY_TYPE_RTF | This value is only used if ulFlags includes the MAPI_NATIVE_BODY flag, and the body is RTF. |
MAPI_NATIVE_BODY_TYPE_PLAIN_TEXT | This value is only used if ulFlags includes the MAPI_NATIVE_BODY flag, and the body is plain text format.
|
MAPI_NATIVE_BODY_TYPE_HTML | This value is only used if ulFlags includes the MAPI_NATIVE_BODY flag, and the body is HTML format. |
Sample code
The following sample code shows you how to use the
WrapCompressedRTFStreamEx function:
//These are definitions for the WrapCompressedRTFStreamEx function.
typedef HRESULT (STDMETHODCALLTYPE WRAPCOMPRESSEDRTFSTREAMEX) (
LPSTREAM lpCompressedRTFStream, CONST RTF_WCSINFO * pWCSInfo, LPSTREAM * lppUncompressedRTFStream, RTF_WCSRETINFO * pRetInfo);
typedef WRAPCOMPRESSEDRTFSTREAMEX *LPWRAPCOMPRESSEDRTFSTREAMEX;
HRESULT TestWrapCompressedRTFStreamEx(LPMESSAGE lpMsg)
{
HRESULT hRes = S_OK;
LPSTREAM lpCompressed = NULL;
LPSTREAM lpUncompressed = NULL;
char szBody[1024] = {0};
ULONG ulRead = 0;
RTF_WCSINFO wcsinfo = {0};
RTF_WCSRETINFO retinfo = {0};
LPSPropValue lpPropCPID = NULL;
retinfo.size = sizeof(RTF_WCSRETINFO);
wcsinfo.size = sizeof(RTF_WCSINFO);
wcsinfo.ulFlags = MAPI_NATIVE_BODY;
wcsinfo.ulOutCodePage = 0;
// Retrieve the value of the Internet code page.
// Pass this value to the WrapCompressedRTFStreamEx function.
// If the property is not found, the default is 0.
if(SUCCEEDED(hRes = HrGetOneProp(lpMsg, PR_INTERNET_CPID, &lpPropCPID)))
{
wcsinfo.ulInCodePage = lpPropCPID->Value.l;
}
// Open the compressed RTF stream.
if(SUCCEEDED(hRes = lpMsg->OpenProperty(PR_RTF_COMPRESSED,
&IID_IStream,
STGM_READ | STGM_DIRECT,
0,
(LPUNKNOWN*)&lpCompressed)))
{
// Notice that the WrapCompressedRTFStreamEx function has been loaded
// by using the GetProcAddress function into pfnWrapEx.
// Call the WrapCompressedRTFStreamEx function.
if(SUCCEEDED(hRes = pfnWrapEx(lpCompressed,
&wcsinfo,
&lpUncompressed,
&retinfo)))
{
printf("Body's native type is: ");
// Check what the native body type is.
switch(retinfo.ulStreamFlags)
{
case MAPI_NATIVE_BODY_TYPE_RTF:
printf("MAPI_NATIVE_BODY_TYPE_RTF\n");
break;
case MAPI_NATIVE_BODY_TYPE_HTML:
printf("MAPI_NATIVE_BODY_TYPE_HTML\n");
break;
case MAPI_NATIVE_BODY_TYPE_PLAINTEXT:
printf("MAPI_NATIVE_BODY_TYPE_PLAINTEXT\n");
break;
default:
printf("UNKNOWN\n");
}
// Read the first 1,000 characters out of the stream.
if(SUCCEEDED(hRes = lpUncompressed->Read(szBody, 1024, &ulRead)))
{
printf("First %d characters of the native body stream:\n%s\n", ulRead, szBody);
}
}
}
MAPIFreeBuffer(lpPropCPID);
if(lpUncompressed)lpUncompressed->Release();
if(lpCompressed)lpCompressed->Release();
return hRes;
}
REFERENCES
For more information about how to obtain this new function for Outlook 2002, click the following article number to view the article in the Microsoft Knowledge Base:
883924
Description of the Outlook 2002 post-Service Pack 3 hotfix package: August 26, 2004
For more information about how to determine the path of Msmapi32.dll, click the following article number to view the article in the Microsoft Knowledge Base:
229700
How to locate the correct path to the Mapisvc.inf file in Microsoft Outlook
For more information about the security changes in Outlook 2002 that are introduced in Office XP Service Pack 3, click the following article number to view the article in the Microsoft Knowledge Base:
838871
Description of the developer-related security changes in Outlook 2002 Service Pack 3