views:

955

answers:

7

Using MAPI functions from within managed code is officially unsupported. Apparently, MAPI uses its own memory management and it crashes and burns within managed code (see here and here)

All I want to do is launch the default e-mail client with subject, body, AND one or more attachments.

So I've been looking into MAPISendDocuments and it seems to work. But I haven't been able to gather courage to actually use the function in production code.

Has anybody used this function a lot? Do you have any horror stories?

PS. No, I won't shellExecute Outlook.exe with command line arguments for attachments.

PPS. Attachment support is a requirement , so Mailto: solutions do not cut it for me.

+1  A: 

Calling process.Start on the Mailto: protocol (as shown below) will give you basic functionality but not attachments.

Process.Start("mailto:[email protected]?subject=TestCode&Body=Test Text");

You can do this approach with attachment paths but this option only works with some old version of outlook such as 98. I assume this is due to the potential securty risk.

If anyone does use outlook.exe it will give security warnings under outlook 2003 (and 2007 Dependant on settings).

John
+1  A: 

You should be able to make an unmanaged DLL that performs the operations you want using MAPI, and then invoke that DLL from your managed code. I wouldn't write a straight MAPI wrapper, but something that performs all of the functionality you require of MAPI contained in that unmanaged DLL. That would probably be the safest way to use MAPI from managed code.

Chris
+1  A: 

You could also use Outlook Redemption, which is supported from managed code; I'm not immediately sure if it has a simple MAPISendDocuments replacement, but Dmitry's helpful if you have questions.

As for "crashes and burns", here's another quote from an MS support guy, here

It's the sort of thing that'll mostly work. It'll work while you're writing it. Then it'll work while you're testing it. It'll work while your customer is evaluating it. Then as soon as the customer deploys it - BAM! That's when it'll decide to start having problems. And Microsoft ain't gonna help you with it, since we told you not to do it in the first place. :)

Dan Mitchell
+1  A: 

I have done this using the MAPISendMail function and several internal classes to wrap some of the other MAPI related structures. As long as this is the only use, it is possible although not trivial to do safely as it requires a very close attention to the various unmanaged data types and memory allocation/deallocation and GC. While it still isn't supported, I am using this in production code (although it hasn't shipped yet).

When I asked Matt Stehle about this, the response I received was:

I really don't know of a much better way to do this and any issues you ran into here would be probably reproducible in a supported scenario (i.e. VB6 or unmanaged C++). Just know that if you ever ran into a scenario were an issue was caused specifically by this function being called from .NET that we wouldn't have any other recommendation for you then to not use .NET.

Not exactly a blessing on using it, but also not saying there are any other options to actually do this from managed code.

Scott Dorman
+4  A: 

Have a separate helper EXE that takes command-line params (or pipe to its StandardInput) that does what is required and call that from your main app. This keeps the MAPI stuff outside of your main app's process space. OK, you're still mixing MAPI and .NET but in a very short-lived process. The assumption is that MAPI and the CLR start causing issues with longer-running processes.

We use Dmitry Streblechenko's superb Redemption Data Objects library which allows us to write such "shim" code in JScript and invoke that, which keeps the CLR and MAPI worlds in separate processes, but in a supported fashion.

@Chris Fournier re. writing an unmanaged DLL. This won't work because the issue is mixing MAPI and managed code in the same process.

Duncan Smart
A: 

For someone experienced with MAPI, it would take them less time to crank out the code to do exactly what you want from unmanaged code (read: plain C++) than typing this post and reading the response (no offense).

You're lucky the functionality you need is limited. All you need is a simple C++ utility to take the params you need on the command-line and issue the right MAPI calls. Then, you all this utility from your managed code just as you'd to execute any other process.

HTH

Ash
+1  A: 

MAPISendDocuments is depricated and might be removed. You should use MAPISendMail instread. See http://msdn.microsoft.com/nl-nl/library/dd296734(en-us,VS.85).aspx

andremo