FYI: Why are MAPI and CDO 1.21 not supported in managed (.NET) code?

Rate This
  • Comments 26

The issue of using MAPI or (most commonly) CDO 1.21 in managed (.NET) code is one that comes back to us a lot on the Messaging Developer Support team. Both the messaging technologies in question and the .NET framework have been around for many years at this point. As well have the KB articles that state the supportability of Outlook and Exchange APIs in managed code. There are three main contributors to steady stream of cases we see – even today – where customers are using MAPI and CDO 1.21 in managed code…

  1. More and more Windows development is done using managed code these days. The .NET Framework has taken hold – especially in the consulting industry – and most custom software consultants use the .NET Framework over C++ or VB6. Many times the decision to use .NET in a solution is an assumption from the beginning and not something evaluated based on the requirements of the application. It can be easy forget in today's environment that you can still write unmanaged code and there are situations where you might have to.
  2. Outlook and Exchange development is a niche – many ISVs and consultants have to get into messaging development to accomplish a small part of a larger application. In other words, they don't do this every day like I do. These developers simply know they need to accomplish a task be it checking an inbox, creating an appointment, or sending an email. They search the web and find a sample that seems to work for them and move on.
  3. CDO 1.21 *appears* to work just fine in managed code. Before entering the ranks of Microsoft and finding myself in this cube thinking about Exchange all day, I too, was a consultant in the wild. I found myself in the situation above – I was writing a .NET Windows Service and needed to check an Inbox. I converted some old VB6 code I had to VB.NET and moved on. Everything worked fine through testing but in production we had this nagging memory leak and an occasional Access Violation which we could never quite figure out. Turns out that many of the problems with using CDO 1.21 or MAPI in managed code didn't show up until our application was under stress or running for a while because they are mainly memory management issues. From a usability perspective, there are no initial red flags or awkwardness to warn you that you are doing something you shouldn't.

Okay, I've heard that before so why exactly is using MAPI or CDO 1.21 not supported in managed code?

MAPI has its own memory management model that conflicts with and is incompatible with the .NET runtime. This the primary reason that MAPI and CDO 1.21 are not supported running in a .NET process. The common symptoms you will see are seemingly random Access Violations and very often memory leaks (especially with CDO 1.21). There is no methodology for avoiding or managing these symptoms by using interop libraries or managing references in a particular fashion in your .NET code – it just won't work.

The trap is that CDO 1.21 and .NET can "appear" to work and you can get pretty far in your dev cycle before you run into problems. Many times we see this come up in soon after a solution is released to production, in late cycle performance testing, or in a pilot program. Opening a critical case with Microsoft when you have end users complaining of crashes or project managers short on budget is not a good time to find out that your solution is unsupportable.

Take a look at Patrick's article on what "unsupported" means. He uses MAPI and .NET as an example in this article for reason #4 that something could be deemed unsupported by Microsoft…

"It has known problems…We KNOW this is a problem, so we don't support it."

Fine, I won't use .NET and MAPI or CDO 1.21 in the same process but I still need to write this application – now what?

The simple answer is you either need to not use .NET or not use MAPI or CDO 1.21. So how do you make that decision?

First let's look at your business requirements to determine where we need to compromise. As I mentioned above a lot of time the decision to write an application in .NET is made long before in depth design has been done and even more frequently the interaction with Exchange is a minimal part of the overall solution. If you are locked into .NET then you can look into alternative APIs that are supported in managed code.

In the pre-Exchange 2007 world, the only supported APIs for managed code from Outlook and Exchange are Outlook Object Model, WebDAV, and CDOEX. Each of these has their limitations:

Outlook Object Model simply automates the Outlook.EXE process and is not supported to run from a service application (Windows Services and ASP.NET applications should not use OOM)

WebDAV is a protocol not an object model and has a steep learning curve (it also has limits on its support for calendaring)

CDOEX is built on top of ExOLEDB which is only intended to be used (and is only supported) on the Exchange server itself – not remotely.

The second thing to consider is why you needed to use MAPI or CDO 1.21 in the first place. MAPI provides a very raw view of the message store without much business logic so you might want to use that to work with item properties or hidden items not available to the other APIs. CDO 1.21 provides a hefty amount of business logic for working with appointments and meetings. Without any noticeable problems upfront when you try to use CDO 1.21 from .NET code, it might seem worth the risk given the options above. If you really feel that CDO 1.21 or MAPI is your best option based on the business requirements of what your application must do then by all means use CDO 1.21 – just plan to use it *out of process* from your .NET code.

  • PingBack from http://web-design.dailygeektoy.com/?p=104

  • For anyone needing CDO 1.21 functionality in a .Net application, I would highly advise them to check out the Redemption library by Dmitry Streblechenko -- specifically the Redemption Data Objects (RDO).  RDO is designed to be a functional replacement for CDO plus has some nice extras.

  • Observations about the software industry today Mobile E-Mail For Business: How Five Platforms Compare

  • So Microsoft knows that many (most?) business apps will have a requirement of some sort of connectivity to Exchange data stores, yet after four versions of the framework, we STILL do not have any managed classes in the framework to handle this every day requirement.  How many THOUSANDS of hours of developer productivity have been lost trying to bypass this obvious and unforgivable omission? Utterly Ridiculous.

  • Sorry you feel so strongly that we have let you down.  I'm not sure you will ever see the .NET Framework ship classes for accessing Exchange.  

    Exchange APIs are shipped with the product themselves and are updated as the product is updated because they contain business logic specific to that version.  Shipping them in the Framework would take away our ability to update them with the Exchange product updates and would tie them to the Framework instead of the product they are built to work with - seems like a bad idea to me.

    In Exchange 2007 we have made a HUGE investment in .NET - maybe the biggest of any product group thus far.  A large majority of the new product code for 2007 is C#.  ALL of the new API scenarios (Exchange Web Services, Transport Agents, Powershell, etc.) is geared towards .NET development.

    Even in Exchange 2003 you do have options - it isn't like you can't write a .NET application that works with Exchange data.  CDOEX provides a robust interface to Exchange.  For remote applications - WebDAV is a decent option although it doesn't do everything, it does many of the basic functions needed for an Exchange application.

  • Hi, I believe this configuration should be supported, correct me if I'm wrong:

    - C++ unmanaged process calling an inprocess COM-interop'ed .NET code in a DLL.

    - the same C++ unmanaged process using MAPI for some other purpose.

  • No this wouldn't be supported - we don't support any scenario of CDO 1.21 or MAPI being loaded in the same process as the CLR.

  • I take it things such as mapi33 don't work either (though it appears to in our testing)?  Any suggestions on how we would confirm that we have a problem?

    If you could somehow run the mapi stuff in a different app domain, would that reduce the memory corruption risk (i.e. limit the corruption to the temporary app domain)?

    As someone mentioned above, it is stunning that in this connected age, no .Net API for mail exists.  Is anything coming in 3.5?  Seems like a hole/opportunity - I'm surprised it hasn't been fixed.

    Can you point us at the Exchange API's

  • In general principle third party APIs aren't supported by Microsoft, you would have to follow up with the vendor to get their support policy.

    To reiterate my point to the other commenter about adding Exchange APIs to the .NET Framework, it just isn't the place for it at all.  The .NET Framework's class libraries provide classes for doing basic operations - it is not the end-all-be-all for interoperability and is not intended to be.  There are no Sharepoint APIs in the Framework, there are no Biztalk APIs in the Framework, and there are no SQL Management APIs in the Framework.  Just like Exchange APIs - *product specific* business logic will not end up in the .NET Framework because it needs to be shipped with the product itself and most likely be version specific.

    Please check out Exchange Web Services for managed code interoperability with Exchange...

    http://msdn2.microsoft.com/en-us/library/bb402321.aspx

  • Thanks for the link and thanks for the post - please don't think we are shooting the messenger, info like this is invaluable.

    I do understand that .Net can't have an API for every external system - but email is far more ubiquitous than Sharepoint, Biztalk or SQL Management.  If I had a dollar for every app that tries to send email...I'd be as rich as your boss.  I guess I think of email more like file system API's or maybe LINQ - common enough to deserve more attention.  Of course, maybe email is too mundane or old fashioned.  

  • Definitely no hard feelings - this is a good discussion and one of the longest ever on my blog so I'm all for it :)

    Now if you limit your request to purely *sending* email, the Framework does have classes for that System.Net.Mail which uses SMTP.  While sending email via SMTP is common and useful enough to incorporate into the Framework, I'm not sure that reading or processing mail is.  I guess the arguement could be made for POP or IMAP classes but that would give you much.  All of the interesting business logic - that is always going to be product specific - is the APIs for Exchange only like CDO 1.21, CDOEX, and Exchange Web Services.

  • Just a comment on where we're coming from (I work for DEcclestone :-)

    We use MAPI in our app just to send email right now.  The nice thing about it as opposed to SMTP is that we can (optionally) have the compose email UI available to our app, as well as things like the address book, login validation, etc.  With SMTP we'll have to implement our own UI to allow the user to compose and attach files.

    We may have to utilize the Outlook object model for cases when we want a UI and SMTP for cases when we want no UI.

    The nice thing (in theory anyways) about MAPI is that other providers (Notes, etc) could support it and we wouldn't have to have different implementations for each email client.  Some sort of a generic open messaging API for .NET would be a nice feature.

  • What it sounds like you are asking is that we provide some Simple API functionality in the .NET Framework being that it is "standardized" and would not be specific to clients.  However, keep in mind that Simple MAPI is just an interface implemented by mail clients.  Some mail clients might implement it in such a way that is supportable by them in managed code.  Outlook implements Simple MAPI in MAPI32 as part of its Extended MAPI implementation.  This is the component that isn't supported in managed code - it is kind of a chicken or the egg problem at this point.

  • Sorry for the inflammatory comment earlier, it was born of frustration.  It seems that we are coming from two different worlds.  In my world, I work for a company of 60000+ employees, with developer groups (like mine) scattered all over the globe.  We develop business apps that will probably be used by 10,000 or so users.  We have no special access to the Exchange servers in our company.  We don't even know what country they are in!  All of our corporate level IT functions like Exchange are outsourced (Anderson, Compaq, IBM, HP - pick your flavor-of-the-year) and are hosted in huge data centers "in the sky" (Canada, New York, Houston, depends on the vendor).

    The chances of any interaction with the Exchange administration group is ZERO.  Yet… we still have to write our applications.  All I require is a simple .NET class (don't care if it is a separate download vs. included in the framework) to let me perform "Outlook like" functions from my programs, particularly services that run unattended.  I would like to be able to write a simple .NET service application that can send/received emails from a dedicated (function) Exchange account.  If my user sends an email with an attached license request, it would be nice if I could easily extract it.  Here is a challenge for you – post some .NET (Csharp) code that can read an exchange folder full of bounce messages (NDR) and tell me which messages bounced as a result of a full mailbox and which are the result of an invalid email address.  See you in a couple of years….

    I think you will find (if you look) that in most organizations of any significant size, developers are expected to write applications with Outlook-like functions, while requiring only the same credentials that are required for using Outlook.  Actually, that is EXACTLY what I (and probably 90% of all developers) want - a .NET class that lets me do everything I can do from the Outlook user interface, using no other credentials/access/privileges other than what I need to run Outlook.  Because the one thing I CAN get from the Exchange Nazis is a functional  (special purpose) email account – given that I provide the business case.  This is the huge gaping hole that developers are trying to fill with the likes of CDO 1.21 and MAPI.  Haven’t you ever asked yourself why so many folks are trying to make libraries like MAPI33, Redemption, etc. work from .NET?  Do your customers a simple courtesy – take a poll and ask how many write applications that need to access the exchange data store from a client app (100%) vs. how many are writing code that runs ON the Exchange server itself (maybe 5%?).  Then perhaps you will understand which API you need to be working on.

    You made the comparison to SQL Server, so I will take it one step further.  What if they had taken the same attitude as the Exchange group?  What if they provided  “SQL Server Data Browser” (ala Outlook) as part of MS Office – but no way to access data in a SQL database from .NET code.   Do you think they could just say, “Well, we have a lot of APIs that will work from .NET on the SQL Server host machine, you really don’t need to access the data from a client app, do you?  If you really need to access SQL Server data, you should just use VB6 or unmanaged C++.  Yeah, right.

  • I assure you we are not coming from two different worlds.  I have spent more time as a software developer outside of Microsoft then I have inside Microsoft.  I'm not the product team.  I don't create the product - I support developers like you who use Exchange APIs.  I know all about the hardships of using .NET with Exchange Server 2000/2003.  You are 100% right that CDOEX is not the answer in that it must run on the Exchange server.  WebDAV is the only remote option for writing .NET code to run remotely against an Exchange 2003 Server.  Please don't assume that I don't understand where you are coming from - it is why I write this blog, continue to post & answer your comments, and do the job I do.

    Additionally (as I have pointed out before) the product team does listen and they do see this as an area to improve, in Exchange 2007 they have addressed your main concern...

    "All I require is a simple .NET class (don't care if it is a separate download vs. included in the framework) to let me perform "Outlook like" functions from my programs"

    ...The answer here is Exchange 2007 Web Services - no download required.  Fully supported in .NET and any other language that can submit formatted text to port 80.

Page 1 of 2 (26 items) 12