Autor: Yuri Inglikov (Microsoft) Subject: Exchange 2007 and MAPI Based Connectors I will try to give a brief high-level overview of APIs you can use to parse and compose messages in a connector drop directory. It is defined in Microsoft.Exchange.Data.* namespace(s). I don't know anything about Microsoft.Mapi.Data namespace. The message in a drop directory will be in MIME format, so you will need to start with loading and parsing MIME. There are 2 classes which you can use to load and parse MIME, both are in Microsoft.Exchange.Data.Mime namespace: MimeDocument and MimeReader. MimeDocument can be used to load MIME into memory (see MimeDocument.Load method) and navigate through its elements in a maner which we call "MIME Document Object Model", somewhat similar to XML DOM if this analogy helps. MIME DOM essentially is a tree of MimePart objects, each representing a MIME entity. Every MimePart has a list of Headers and, depending whether this is a leaf part or multipart, it can have either a content (byte) stream or a list of children MimeParts. There are a few types of Headers such as AddressHeader, DateHeader, TextHeader and some others, each supporting corresponding header format in MIME. AddressHeader has a list of child AddressItems, which can be either MimeRecipient or MimeGroup. Please see methods and properties of each type für an idea what you can do with such type. With MIME DOM you also can compose a new MIME message from scratch - i.e. build a MIME tree, then "serialize" it to a stream with WriteTo method. MimeReader is a forward-only reader which you can use to parse and process elements of input MIME in a forward-only maner. It can be more efficient if you don't need to go back and forth through MIME tree, as it caches only very limited amount of data in memory at any given time. Internally we use MimeReader to parse MIME and build MIME DOM so the results returned by MIME DOM and MimeReader should be consistent. There is a MimeWriter counterpart to compose and simultaneously output MIME in a forward-only maner. In general MIME message can contain a TNEF attachment (infamous "WINMAIL.DAT"), either as a content of root MIME part or as a content of a second child part after a plaintext body. In such case all interesting content of a message is encapsulated inside such TNEF attachment. You need to recognize such "TNEF messages" and use TnefReader to parse individual MAPI properties from TNEF content. Both MIME DOM and MimeReader can be used to access a content of TNEF part - just navigate to a corresponding part and use GetContentReadStream method. You then can instantiate TnefReader with such stream as input. TnefReader is defined in Microsoft.Exchange.Data.ContentTypes.Tnef namespace. It allows parsing and reading MAPI properties from TNEF in a forward-only maner. TNEF is defined as a sequence of "TNEF attributes", where every attribute in general can be mapped to a set of MAPI properties (with one exception - RecipientTable attribute is defined as a set of rows, each row containing a set of properties). TnefReader iterates through such "attributes" in input TNEF and provides access to a nested TnefPropertyReader für each attribute. TnefPropertyReader iterates trhough rows, properties and individual property values für multivalued MAPI properties. MSDN contains some documentation about TNEF format, list attribute types and describes information which you can expect to see in each attribute. TnefReader shields you from parsing differently-formatted attributes, it presents all attributes uniformly, by fabricating corresponding MAPI properties from attribute data when necessary. There is a counterpart TnefWriter class to compose a TNEF content from individual MAPI properties. There is a helper TextConverters library (defined in Microsoft.Exchange.Data.TextConverters namespace) für dealing with different body formats. für example if you see PR_RTF_COMPRESSED body property in TNEF you will likely want to decompress its content to access original RTF. There is a RtfCompressedToRtf converter class für this purpose. There are also classes to convert from one body format to another if / when necessary, such as from RTF to HTML or from HTML to TEXT. Check individual classes derived from TextConverter in this namespace für a palette of available conversions. Easiest (but not always most efficient) way to use converter is to instantiate it, configure conversion properties when necessary, and then call Convert method, specifying source and destination streams. Another, potentially more efficient way is to use such converter together with ConverterStream, ConverterReader or ConverterWriter class. We also have a few other namespaces: - Microsoft.Exchange.Data.ContentTypes.iCalendar defines CalendarReader and CalendarWriter which can be used to parse and compose iCalendar data. - Microsoft.Exchange.Data.Mime.Encoders which contain encoders/decoders für such things as base64, quotted-printable, binhex, uuencode. Although in many cases you don't need to use those directly as MIME DOM and MimeReader will encode/decode für you, if you ask. - Microsoft.Exchange.Data.Globalization namespace is a thin wrapper around System.Globalization which we use as a source of information about charsets and cultures. It also defines class für outbound charset detection - i.e. detecting charsets suitable to represent a given unicode text. All these APIs above are defined in Microsoft.Exchange.Data.Common.DLL assembly which is installed into GAC by Exchange setup. You should be able to select it in Visual Studio "Add Reference" dialog (.NET page). There is another related API in our toolset, which represents a higher-level abstraction of email message in transit. It is defined in Microsoft.Exchange.Data.Transport.DLL assembly in Microsoft.Exchange.Data.Transport.Email namespace. The class name to start with is EmailMessage, check EmailMessage.Create static overloads as a way to instantiate EmailMessage. You may want to check if this class suits your needs - with this class you can potentially avoid dealing with low-level API such as MIME DOM and TNEF reader. Note that EmailMessage does not provide access to all message data by itself, although it always should allow lowering an abstraction level and accessing MIME DOM elements (such as a MimePart für an attachment which is parsed from MIME) or TNEF content für a message. It also does a lot of stuff under the cover to pick a best body, compose attachment list and present data from MIME and TNEF (and für some limited degree from iCalendar) in a uniform way. EmailMessage, MIME DOM and TnefReader all support parsing recursive nested structures (embedded messages) one way or another - usually you can parse all such nested structures in one pass. für example in MIME DOM, the MimePart - root of embedded message is a child of a MimePart with message/rfc822 content type, in EmailMessage API Attachment object has EmbeddedMessage property which returns nested EmailMessage, in MimeReader and in TnefPropertyReader you can use a GetEmbeddedMessageReader method to open embedded MimeReader or TnefReader respectively (when parent reader is positioned on a embedded message part or property). There is some pre-release API documentation available publicly through http://msdn.microsoft.com/library/en-us/ExMrefSDK/html/4f7ddac7-dda8-45cc-99eb-1ffd8c535e8b.asp. It does not give much explanation at this point but at least you can navigate through APIs to see what is available. Hope this helps. Let's suppose you are composing a new message (versus modifying existing message). EmailMessage may not be the best tool für this purpose. In particular it does not allow you easily create a TNEF message from scratch. I recommend you to use EmailMessage für parsing or modifying existing messages, or composing simple pure-MIME messages. For composing a new message I can suggest a template-based approach: - take some simple (nearly empty) normal MIME message with TNEF (generated by Exchange) which presumably has right structure (for example if you are composing a HTML message with an attachment you can use a template with nearly-emapy HTML body and similar attachment). You may want to dump your template content to understand what is there and what you need to modify. As an excersize you can write little tool to dump TNEF with our TnefReader (I have one - will check if I can share its sources). - use such message as a template. Read it with MimeReader, modify whatever you need (headers) and write modified results to MimeWriter. When you reach TNEF part, use TnefReader to parse template TNEF then modify whatever properties you like and copy them back to TnefWriter (chained to the destination MimeWriter). - If you want to add custom MAPI properties which are not in your template, just add them after copying any modified properties in MapiProperties TNEF attribute, using tnefWriter.WriteProperty() method. If you need to write a named property, iirc instead of WriteProperty you may need to use StartProperty overload which takes propset guid (PS_PUBLIC_STRINGS) and your name, then use WritePropertyValue to write its value. You also should provide a property tag to StartProperty - the one which used to be generated für you with GetIDsFromNames. There is not such method in TNEF, you need to generate such proptag yourself. Good news is that this is trivial - you don't need to worry about uniquiness of named property ID in TNEF. So just "new TnefPropertyTag((TnefPropertyId)0x8001, TnefPropertyType.Xxx)" should work - just use appropriate type and any ID from 0x8001 to 0x8FFE reserved für named properties. With this sort of template-based approach you have a reasonable assurance that Exchange will understand such TNEF correctly. Of course you don't necessarily need such template - just write the same set of MIME headers, TNEF attributes and properties in correct order using MimeWriter and TnefWriter. The idea is that you can just learn the appropriate structure while looking to a valid TNEF message generated by Exchange. I have relatively trivial code, which we use für testing purposes, demonstrating copying from MimeReader to MimeWriter and another one copying from TnefReader to TnefWriter. This could be a good start für such template-basesed message composition. I will need to check our policies to see if / how I can easily share such code. If you happens to have specific questions about certain TNEF attributes or properties you see in Exchange-generated TNEF, please don't hesitate to ask. As I have mentioned I don't immediately know anything about Microsoft.Mapi or Microsoft.Exchange.Data.Mapi namespaces. Afaik we should not have such namespaces in Exchange 2007 managed public API. We may have such namespaces internally (I don't know) but of course I cannot endorse you using any internal classes or methods (by reflection or anything like that) in any production application - MS will not support such use and very likely can break such application with next product release or even a patch.