• Sign In
 
  • MSDN Blogs
  • Microsoft Blog Images
  • More ...

  • Advanced search options...
  • Blog Home
  • About
  • Email Blog Author
  • Share this
  • RSS for posts
  • Atom
  • RSS for comments
  • CDO (20)
  • Code Snippet (42)
  • Custom Providers (15)
  • Debugging (7)
  • DevMsgTeam (268)
  • Documentation (96)
  • DST (8)
  • EWS (7)
  • Exchange (98)
  • Gotchas (89)
  • Hotfix (26)
  • MAPI (212)
  • MAPI Download (47)
  • MFCMAPI (87)
  • MSDN (49)
  • Non Dev (11)
  • OOM (17)
  • Outlook (154)
  • Outlook 2007 Auxiliary Reference (44)
  • Outlook Integration API (11)
  • Protocol Docs (20)
  • PST/OST (21)
  • Public Folders (3)
  • Vista (12)
  • WrapPST (14)
Links:
  • Download MFCMAPI
  • MFCMAPI on Facebook
  • Troubleshooting Outlook Crashes
  • Office Update Center
  • Developer Messaging Team Blog
This site is provided "AS IS" with no warranties, and confers no rights. Use of included code samples are subject to the terms specified in the Terms of Use.
Archives
  • January 2012 (1)
  • December 2011 (3)
  • November 2011 (1)
  • October 2011 (3)
  • September 2011 (1)
  • August 2011 (1)
  • July 2011 (4)
  • June 2011 (3)
  • May 2011 (3)
  • April 2011 (3)
  • March 2011 (5)
  • February 2011 (1)
  • January 2011 (2)
  • December 2010 (1)
  • November 2010 (4)
  • October 2010 (1)
  • September 2010 (3)
  • August 2010 (5)
  • July 2010 (3)
  • June 2010 (3)
  • May 2010 (1)
  • April 2010 (3)
  • March 2010 (3)
  • February 2010 (3)
  • January 2010 (2)
  • December 2009 (3)
  • November 2009 (5)
  • October 2009 (4)
  • September 2009 (5)
  • August 2009 (5)
  • July 2009 (11)
  • June 2009 (6)
  • May 2009 (5)
  • April 2009 (3)
  • March 2009 (18)
  • February 2009 (10)
  • January 2009 (3)
  • December 2008 (2)
  • November 2008 (2)
  • October 2008 (5)
  • September 2008 (4)
  • August 2008 (10)
  • July 2008 (6)
  • June 2008 (8)
  • May 2008 (2)
  • April 2008 (4)
  • March 2008 (2)
  • February 2008 (2)
  • January 2008 (5)
  • December 2007 (3)
  • November 2007 (2)
  • October 2007 (3)
  • September 2007 (1)
  • August 2007 (4)
  • July 2007 (5)
  • June 2007 (3)
  • May 2007 (4)
  • April 2007 (1)
  • March 2007 (6)
  • February 2007 (3)
  • January 2007 (2)
  • December 2006 (4)
  • November 2006 (3)
  • October 2006 (1)
  • August 2006 (1)
  • June 2006 (5)
  • May 2006 (5)
  • December 2005 (1)
  • November 2005 (4)
  • October 2005 (2)
  • September 2005 (1)
  • April 2005 (3)
  • December 2004 (2)
  • September 2004 (2)
  • August 2004 (3)
  • July 2004 (3)

Forcing Plain Text With MAPI

MSDN Blogs > SGriffin's MAPI Internals > Forcing Plain Text With MAPI

Forcing Plain Text With MAPI

Stephen Griffin - MSFT
4 Aug 2008 3:29 PM
  • Comments 7

We had a customer recently who was sending mails with Outlook's MAPI. They wanted to know how to force the message to be plain text, like it is in Outlook when you select Send Plain Text only in the properties for the recipient:

PlainText

They were using CreateOneOff to create their recipient, and they were passing MAPI_SEND_NO_RICH_INFO. Yet, if the message they were sending contained an attachment, such as a Word document, the content type of the attachment on the received mail was always application/ms-tnef instead of application/msword. In other words, they were still getting a winmail.dat attachment. If they addressed a mail in Outlook with the Send Plain Text only option, sending the same attachment, it came across without the TNEF.

One thing to note right off the bat is that sending rich text (RTF) data and sending TNEF (winmail.dat) are actually two different concepts. RTF data describes the formatting of the text of the message, much in the same way HTML can also describe the formatting of text. TNEF is a mechanism for encapsulating MAPI properties that Exchange and Outlook do not convert natively into MIME format. One such MAPI property commonly encapsulated in TNEF is PR_RTF_COMPRESSED. But TNEF can encapsulate many more properties than just PR_RTF_COMPRESSED, such as properties dealing with certain attachments. So the presence of winmail.dat doesn't necessarily mean rich text is being transmitted. That's what's happening in this case.

If you're trying to avoid TNEF completely, MAPI_SEND_NO_RICH_INFO is a step in the right direction, but doesn't actually tell the content converter not to use TNEF - it just tells it not to use RTF. To avoid TNEF altogether, we need to set some more flags. But which flags? We can look at what CreateOneOff generates to find out. Fortunately, we don't need to reverse engineer the structure - it was recently documented in section 2.2.5.1 of the following Exchange Protocol Documentation: [MS-OXCDATA].pdf

Now - the documentation's in "bytes on the wire - what's a constant?" format, but with a little elbow grease, we can produce the following structure:

{ 
 DWORD dwFlags;
 BYTE ProviderUID[16]; 
 DWORD dwBitmask;
} ONEOFFEIDHEADER, FAR *LPONEOFFEIDHEADER;

which we can map our entry ID to so we can check which flags are set. The following flags are valid (determined by matching the docs up to MAPI's headers):

#define MAPI_SEND_NO_RICH_INFO          ((ULONG) 0x00010000)
#define ENCODING_PREFERENCE             ((ULONG) 0x00020000)
#define ENCODING_MIME                   ((ULONG) 0x00040000)
#define BODY_ENCODING_HTML              ((ULONG) 0x00080000)
#define BODY_ENCODING_TEXT_AND_HTML     ((ULONG) 0x00100000)
#define MAC_ATTACH_ENCODING_UUENCODE    ((ULONG) 0x00200000)
#define MAC_ATTACH_ENCODING_APPLESINGLE ((ULONG) 0x00400000)
#define MAC_ATTACH_ENCODING_APPLEDOUBLE ((ULONG) 0x00600000)
#define OOP_DONT_LOOKUP                 ((ULONG) 0x10000000)

With this, we can see that setting the Plain Text Only option in Outlook translates to setting the ENCODING_PREFERENCE and ENCODING_MIME flags. Unfortunately, the CreateOneOff function doesn't let you pass those flags. If you try, you'll get MAPI_E_UNKNOWN_FLAGS. We won't let that stop us though - we can use our structure to set the flags as well as read them!

Here's how we can put this all together and get a one-off entry ID which will send without TNEF:

{ 
    DWORD dwFlags; 
    BYTE ProviderUID[16]; 
    DWORD dwBitmask; 
} ONEOFFEIDHEADER, FAR *LPONEOFFEIDHEADER; 

hr = lpAddrBook->CreateOneOff( 
    lpszName, 
    lpszAdrType, 
    lpszAddress, 
    MAPI_SEND_NO_RICH_INFO, 
    &cbEntryID, 
    &lpEntryID); 
if (HR_SUCCEEDED(hr)) 
{ 
    LPONEOFFEIDHEADER lp1Off = (LPONEOFFEIDHEADER) (ENTRYID*) lpEntryID; 
    if ((lp1Off->dwBitmask & MAPI_SEND_NO_RICH_INFO)) 
    { 
        lp1Off->dwBitmask |= (ENCODING_PREFERENCE | ENCODING_MIME); 
    } 
}

[Update: 8/4/2008 5:45 - rewrote the RTF/TNEF paragraph to make it clearer]
[Update: 8/4/2008 9:36 - realized I hadn't proofread the code - fixed it]

  • 7 Comments
Outlook, MAPI, Code Snippet, Documentation, Protocol Docs, DevMsgTeam
Comments
  • Zool
    4 Aug 2008 4:59 PM

    ---snip---

    MIME doesn't have a native way to encapsulate RTF data, so we use TNEF to encapsulate it

    ---snap---

    Sorry, WHAT?! Just use text/rtf or a multipart/mixed containing the text/rtf.

    Sigh ...

  • Stephen Griffin - MSFT
    4 Aug 2008 5:41 PM

    Zool - Maybe text/rtf *could* be used, but I couldn't even find a standard covering it. However, that's beside the point - Outlook and Exchange use TNEF to encode MAPI properties that they don't convert directly to MIME headers, and that includes PR_RTF_COMPRESSED.

  • Rick C.
    10 Oct 2008 6:33 PM

    Is there any way to get at the flags when using CDO 1.21?  I can't find a way to eliminate TNEF when the CDO-created message has an attached file.  Any suggestions?

  • Stephen Griffin - MSFT
    11 Oct 2008 11:06 AM

    Rick - Probably not, but you're welcome to hack at it - report back if you find a way to do it.

  • Rick C.
    11 Oct 2008 3:21 PM

    O.K. I found a solution.  I experimented with Simple MAPI VBA code and found that if you set the recipient's Name property to address@company.com and use MAPIResolveName, the Address property is set to SMTP:address@company.com and there is no TNEF block in an email with an attachment.  But if you set the Name property to a display name and set Address to SMTP:address@company.com and don't use MAPIResolveName you will get the TNEF and winmail.dat.

    There is a similar solution in CDO.  This excerpt gets a TNEF block:

    Set objRecipient = objMessage.Recipients.Add

    objRecipient.Name = "John Doe"

    objRecipient.Address = "SMTP:address@company.com"

    objRecipient.Resolve False

    But this CDO code does not:

    Set objRecipient = objMessage.Recipients.Add

    objRecipient.Name = "address@company.com"

    objRecipient.Resolve True

    I lose the display name in the outgoing email but no longer have a TNEF block.  So, using MAPIResolveName and its equivalent in CDO is the solution.

  • Eriq VanBibber
    13 Oct 2008 9:10 AM

    Have you tried encapsulating your address in [square brackets?]

    I seem to remember for several microsoft products that this forces resolution to a different method.

    I know that in exchange i have to wrap X500 address this way [/o=org/ou=site/cn=recipients/cn=user], otherwise resolution will fail.

    Perhaps try some combination like this:

    [address@domain.com]  - no smtp moniker

    [SMTP:address@domain.com]

    SMTP:[address@domain.com]

    Let us know your results.

    -Eriq

  • Rick C.
    13 Oct 2008 7:39 PM

    The brackets did not help but I can get the display name back by setting it after calling CDO's Resolve method:

    Set objRecipient = objMessage.Recipients.Add

    objRecipient.Name = "address@company.com"

    objRecipient.Resolve True

    objRecipient.Name = "My Name <address@company.com>"

    That works and I've eliminated the TNEF block.

Page 1 of 1 (7 items)
Leave a Comment
  • Please add 5 and 4 and type the answer here:
  • Post
  • © 2012 Microsoft Corporation.
  • Terms of Use
  • Trademarks
  • Privacy Statement
  • Report Abuse
  • 5.6.131.143