More IConverter For Ya


[This is now documented here: http://msdn2.microsoft.com/en-us/library/bb821176.aspx]


Good news, everyone! We’ve decided to document some more flags and functions for IConverterSession.


Here are the new constants:

#define CCSF_USE_TNEF        0x0010 // the converter should embed TNEF in the MIME message
#define CCSF_8BITHEADERS 0x0040 // the converter should allow 8 bit headers
#define CCSF_PLAIN_TEXT_ONLY 0x1000 // the converter should just send plain text

All three of these flags are only valid for MAPI->MIME.


More interesting are the new functions. They take the place of the first and last placeholder functions in the interface. The first, SetAdrBook, allows you to pass a MAPI address book for the converter to use for name resolution. The second, SetCharSet, allows you to tell the converter which character set to use.


Here’s a newly updated header. Note that you will need to locate and include mimeole.h for this header to work – there are too many types from that header being used to try and define them all here:

#pragma once
//Class Identifiers
// {4e3a7680-b77a-11d0-9da5-00c04fd65685}
DEFINE_GUID(CLSID_IConverterSession, 0x4e3a7680, 0xb77a,
0x11d0, 0x9d, 0xa5, 0x0, 0xc0, 0x4f, 0xd6, 0x56, 0x85);

//Interface Identifiers
// {4b401570-b77b-11d0-9da5-00c04fd65685}
DEFINE_GUID(IID_IConverterSession, 0x4b401570, 0xb77b,
0x11d0, 0x9d, 0xa5, 0x0, 0xc0, 0x4f, 0xd6, 0x56, 0x85);

// Constants
#define CCSF_SMTP 0x0002 // the converter is being passed an SMTP message
#define CCSF_NOHEADERS 0x0004 // the converter should ignore the headers on the outside message
#define CCSF_USE_TNEF 0x0010 // the converter should embed TNEF in the MIME message
#define CCSF_INCLUDE_BCC 0x0020 // the converter should include Bcc recipients
#define CCSF_8BITHEADERS 0x0040 // the converter should allow 8 bit headers
#define CCSF_USE_RTF 0x0080 // the converter should do HTML->RTF conversion
#define CCSF_PLAIN_TEXT_ONLY 0x1000 // the converter should just send plain text
#define CCSF_NO_MSGID 0x4000 // don’t include Message-Id field in outgoing messages

interface IConverterSession : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE SetAdrBook(LPADRBOOK pab);
virtual HRESULT STDMETHODCALLTYPE SetEncoding(ENCODINGTYPE et);
virtual HRESULT PlaceHolder1();
virtual HRESULT STDMETHODCALLTYPE MIMEToMAPI(LPSTREAM pstm,
LPMESSAGE pmsg,
LPCSTR pszSrcSrv,
ULONG ulFlags);
virtual HRESULT STDMETHODCALLTYPE MAPIToMIMEStm(LPMESSAGE pmsg,
LPSTREAM pstm,
ULONG ulFlags);
virtual HRESULT PlaceHolder2();
virtual HRESULT PlaceHolder3();
virtual HRESULT PlaceHolder4();
virtual HRESULT STDMETHODCALLTYPE SetTextWrapping(BOOL fWrapText,
ULONG ulWrapWidth);
virtual HRESULT STDMETHODCALLTYPE SetSaveFormat(MIMESAVETYPE mstSaveFormat);
virtual HRESULT PlaceHolder5();
virtual HRESULT STDMETHODCALLTYPE SetCharset(
BOOL fApply,
HCHARSET hcharset,
CSETAPPLYTYPE csetapplytype);
};


Some notes:



  • The LPADRBOOK passed in to SetAdrBook is obviously a MAPI address book. While conversion can normally be done without logging on to a MAPI profile, if SetAdrBook is to be used you will need to log on to a profile to get an address book.
  • HCHARSET is a handle, not a constant. NULL is a valid value. For non-NULL values, you’ll need to fetch an HCHARSET using a function like MimeOleGetCodePageCharset. This means you’ll either need to link in inetcomm.lib or do the LoadLibrary/GetProcAddress thing.
  • If fApply is false, then the parameters passed in SetCharSet aren’t used. You’d do this if you wanted to set a character set for a particular message, then return to the defaults for subsequent messages.
  • In SetAdrBook, pab can be NULL. This will reset the converter to not using an address book.
  • SetAdrBook and SetCharSet always returns S_OK. But you should still check in case we later decide there’s a case where they can fail.

I think I documented the new flags correctly – if not, let me know and I’ll fix them.

Comments (14)

  1. John says:

    Where is this officialy documented on MSDN, given that this is just a blog?

  2. Stephen Griffin says:

    You’re right – this *is* just a blog. The Outlook team gives me permission to document things that they themselves are planning to document down the road. But doing things officially takes time – months even. So we chose to use my blog to get the information out now, where the community can comment on it, and work on the official documentation in parallel.

    This post itself is an example of how this strategy is paying off. If we had just waited until the official documentation was completed, then the information in this post never would have been documented, because by the time we got the feedback that it would be helpful, it would be too late to get it added.

  3. Tom says:

    Has anyone been able to get the CCSF_PLAIN_TEXT_ONLY flag to work with MAPIToMIMEStm. Ive tried several variations and can only seem to get MAPIToMIMEStm to work properly using TNEF which isnt what Im after.

  4. Michel says:

    Hi there,

    i am dealing with an outlook add-in, written in Visual C# (Visual Studio 2008 Professional), and I have to add some header information to the mail headers, before the email is sent. I am able to send the mail, but in MailItem I can’t find any method or property which lets me access or even see the headers before sending.

    I am thinking of using a c++ dll wich lets me convert the mapi message to mime stream. Than I plan to add my headers and reconvert the mime stream to a mapi message.

    I wonder that there is no way in the "Microsoft.Office.Interop.Outlook" – interfaces to deal with email headers. Is that right or did I just miss something?

    Regards Michel

  5. Stephen Griffin says:

    You can’t find anything for dealing with the headers because there aren’t any – these are MAPI based messages. Only after the message is submitted does the transport convert the message (assuming you’re using an SMTP transport and not Exchange). Creating a MIME message before you submit isn’t going to help.

  6. Michel says:

    Hi Stephen,

    thanks for your last post. I found a way to add a PS_INTERNET_HEADERS Property to the related MAPI object. So that problem is solved. But now I have an other one with the MAPIToMIMEStm and MIMEToMAPI methods. When I write a MAPI object to a .eml file there are some of the PR_TRANSPORT_MESSAGE_HEADERS missing after I read the .eml again. Other properties are not initialized at all (i.e. Subject). When I check the original message (IMessage) with OutlookSpy and compare it to the "reimported" message the PR_SUBJECT-property is empty. Do I need to define more flags or do I have to scan the source MIME stream and set the missing properties by myself?

    An other problem I have is, that the message appears as unsent. I saw your post "Did I send that?" and checked out the CCSF_EMBEDDED_MESSAGE flag. But that didn’t help me either.

    Do you have an idea how I can solve this?

    Regards, Michel

  7. Michel says:

    Hi Stephen,

    me again. Well, I solved all the problems right now. I works fine, when I do not pass an MailItem.MAPIOBJECT to get an IMessage-Interface. Instead I use the IMAPIFolder->CreateMessage() method.

    I use the IMessage->GetProps() and IMessage->SetProps() methods to set the correct PR_MESSAGE_FLAGS value. Than I call IMessage->SaveChanges() and everything is fine.

    Regards, Michel

  8. Swapnil Shah says:

    Hi Stephen,

    I have declared IConverterSession. i have also Define these two GUID CLSID_IConverterSession and IID_IConverterSession. but when i compile it shows following error. I think it may require any Lib file.

    error LNK2001: unresolved external symbol _CLSID_IConverterSession

    error LNK2001: unresolved external symbol _IID_IConverterSession

    How to resolve this problem.

    Thanks,

    Regards,

         Swapnil

  9. Stephen Griffin says:

    It doesn’t require a .lib file – you just need more experience with guids. 🙂 The trick is to make sure the DEFINE_GUID statements are included in a source file after initguid.h is included. So, if you’re guids are defined in guids.h, most of your source files will have just:

    #include "guids.h"

    at the top. But one of your source files needs to have:

    #include <initguid.h>

    #include "guids.h"

    at the top. The inclusion of initguid converts the DEFINE_GUID macro from a reference to a decalaration, allowing you to link.

    Take a look at guids.h and guids.cpp in the mfcmapi project for an example: http://codeplex.com/mfcmapi

  10. pritesh says:

    Is it sufficient to have Outlook 2007 installed to use the IConverterSession fucntionality ?

  11. Stephen Griffin says:

    Should be. I don’t think you need to go through any "first run" and you don’t have to have a profile if you don’t mind not having access to an address book for name lookup.

  12. Keith Halewood says:

    What is the purpose of CCSF_SMTP ? Shouldn’t it always be the case anyway that MIMEtoMAPI will be presented with a stream containing a SMTP message containing zero or more MIME parts?

  13. Stephen Griffin says:

    It does say the flag must always be set. 🙂 This API was not originally designed for public consumption, so it’s got a few quirks left over from when it was only ever used internally. This is one of them.

  14. Keith Halewood says:

    Ah, I was clutching at straws a little since the 2007 version of MIMEtoMAPI seems to throw out more MAPI_M_PARTIAL_COMPLETION warnings than the 2003 version ever did… and I wondered how significant the various flags were.