tags:

views:

776

answers:

6

The use case is simple. At a certain point of time, I need to be able to show the user his familiar compose email dialog (Outlook or other) with

  • fields like from, to, Subject already filled up with certain application determined values.
  • The email would also have an attachment along with it.

The mail should not be sent unless the user explicitly okays it.

I did this once back in the ol' VB6 days.. can't figure out how now.. I just remember that it was quite easy.

Managed app, C#, .net 3.0+

Update#1: Yeah seems like mailto removed support for attachments (as a security risk?). I tried

You need to include ShellExecute signature as described here. All I got from this was a 5 SE_ERR_ACCESSDENIED and a 2 just for some variety

string sMailToLink = @"mailto:[email protected]?subject=Hey&body= yeah yeah yeah";
IntPtr result = ShellExecute(IntPtr.Zero, "open", sMailToLink, "", "", ShowCommands.SW_SHOWNORMAL);
Debug.Assert(result.ToInt32() > 32, "Shell Execute failed with return code " + result.ToInt32());

The same MailtoLink works perfectly with Process.Start... but as long as thou shalt not mention attachments.

System.Diagnostics.Process.Start(sMailToLink);

The other options are using the Outlook Object model to do this.. but I've been told that this requires you to add assembly references based to the exact version of Outlook installed. Also this would blow up if the user doesn't prefer MS for email.

The next option are Mapi and something called Mapi33.. Status still IN PROGRESS. Ears still open to suggestions.

+2  A: 

It's probably not the most efficient or elegant way, but shelling a "mailto:" link will do what you want, I think.

EDIT: Sorry, left out a very important "not".

gkrogers
yeah found this via googling. However ShellExecute doesnt want to talk to me right now. :)
Gishu
+1  A: 

Could it be that you used the mailto: protocol?

Almost all of what you highlight can be done, but I am quite sure, that you cant do attachments.

Microsoft MailTo Documentation

Rihan Meij
yeah looks like it. a bit OT... w.r.t to this example, Somehow it was much easier in VB6 than in .net.
Gishu
+8  A: 

You can create a process object and have it call "mailto:[email protected]?subject=My+New+Subject". This will cause the system to act on the mailto with its default handler, however, while you can set subjects and such this wont handle adding an attachment. I'll freely admit im not entirely sure how you'd go about forcing an attachment without writing some mail plugin.

The process code is:

System.Diagnostics.Process.Start("mailto:[email protected]?subject=My+New+Subject");
Wolfwyrd
thx but no attachment :(
Gishu
+2  A: 

Since mailto does not support attachments, and since MAPI is not supported within managed code, your best bet is to write (or have someone write) a small non-managed program to call MAPI functions that you can call with command-line arguments. Pity that .NET does not have a cleaner alternative.

See also : MAPI and managed code experiences?

Ishmaeel
Yeah I was thinking the same thing.. i mean the almighty .net framework can't get a Send Email dialog up. How hard could it be? :) that was an hour ago.
Gishu
A: 

You're making the assumption that they will have an email client installed, of course.

The option I've taken in the past (in a corporate environment where everyone has at least one version of Outlook installed) was to use the Outlook interop - you only need to reference the earliest version you need to support.

You could look at P/Invoking MAPISendDocuments (which I'd try and avoid, personally), or the other option would be to create your own "compose" form and use the objects from the System.Net.Mail namespace.

Rowland Shaw
Rolling an own compose form is the first step down a very long and tricky road. Could be OK for a web app, but on the desktop, demands will rightfully be made for many things. Multiple mail addresses, address book support, message copies in outboxes, account management, and I'm out of chars.
Ishmaeel
A: 

Starting process with mailto: arguments is the simplest approach. Yet, it does not allow anything more or less complex.

Slightly different approach involves creating email template and then feeding it to the Process.Start:

var client = new SmtpClient();

var folder = new RandomTempFolder();
client.DeliveryMethod = 
  SmtpDeliveryMethod.SpecifiedPickupDirectory;

client.PickupDirectoryLocation = folder.FullName;

var message = new MailMessage("[email protected]",
  "[email protected]", "Subject","Hi and bye");

// add attachments here, if needed
// need this to open email in Edit mode in OE
message.Headers.Add("X-Unsent", "1");

client.Send(message);

var files = folder.GetFiles();

Process.Start(files[0].FullName);

Scenarios for the default email handler:

  • Outlook express opens
  • Windows: Outlook - does not handle by default, Outlook Express is called instead
  • Windows: The Bat! - message is opened for viewing, hit Shift-F6 and Enter to send

I've also tested with Mono and it worked more or less.

Additional details are available in this post: Information integration - simplest approach for templated emails

PS: in the end I went for slightly more complex scenario:

  • Defined interface IEmailIntegraton
  • Code above went into the DefaultEmailIntegration
  • Added implementations for OutlookEmailIntegration (automation) and theBat! email integration (using their template format).
  • Allowed users of the SmartClient to select their scenario from the drop-down (alternatively this could've been implemented as "Check the system for the default email handler and decide automatically")
Rinat Abdullin