如何使用用户的默认电子邮件客户端弹出撰写/创建邮件对话框?

用例很简单。 在某个时间点,我需要能够向用户显示他熟悉的撰写电子邮件对话框(Outlook或其他)

  • 像from,to,Subject这样的字段已经填满了某些应用程序确定的值。
  • 电子邮件也会随附一个附件。

除非用户明确表示,否则不应发送邮件。

我曾经在OL’VB6时代做过这件事……现在不知道怎么回事……我只记得那很容易。

托管应用,C#,。net 3.0+

更新#1 :是的,似乎mailto删除了对附件的支持(作为安全风险?)。 我试过了

您需要包含ShellExecute签名,如此处所述 。 我从中得到的只是一个5 SE_ERR_ACCESSDENIED和一个2只是为了一些变化

 string sMailToLink = @"mailto:some.address@gmail.com?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()); 

同样的MailtoLink与Process.Start完美配合……但只要您不提及附件

 System.Diagnostics.Process.Start(sMailToLink); 

其他选项使用Outlook对象模型来执行此操作..但我被告知这需要您根据安装的Outlook的确切版本添加程序集引用。 如果用户不喜欢MS用于电子邮件,这也会爆炸。

下一个选项是Mapi和一个名为Mapi33的东西。状态仍在进行中。 耳朵仍然接受建议。

您可以创建一个流程对象,并将其命名为“mailto:user@example.com?subject = My + New + Subject”。 这将导致系统使用其默认处理程序对mailto执行操作,但是,您可以设置主题,这样就不会处理添加附件。 我会很自然地承认,如果不编写一些邮件插件,我就不会完全确定如何强制附件。

流程代码是:

 System.Diagnostics.Process.Start("mailto:user@example.com?subject=My+New+Subject"); 

它可能不是最有效或最优雅的方式,但我认为炮轰“mailto:”链接会做你想要的。

编辑:对不起,遗漏了一个非常重要的“不”。

由于mailto不支持附件,并且由于托管代码中不支持MAPI,因此最好的办法是编写(或让某人编写)一个小的非托管程序来调用可以使用命令行参数调用的MAPI函数。 可惜.NET没有更清洁的选择。

另请参阅: MAPI和托管代码体验?

可能是你使用mailto:协议?

你所强调的几乎所有内容都可以完成,但我很确定,你不能做附件。

Microsoft MailTo文档

使用mailto:arguments启动进程是最简单的方法 。 然而,它不允许任何或多或少的复杂。

略有不同的方法包括创建电子邮件模板,然后将其提供给Process.Start

 var client = new SmtpClient(); var folder = new RandomTempFolder(); client.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory; client.PickupDirectoryLocation = folder.FullName; var message = new MailMessage("to@no.net", "from@no.net", "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); 

默认电子邮件处理程序的方案:

  • Outlook Express打开
  • Windows:Outlook – 默认情况下不处理,而是调用Outlook Express
  • Windows:蝙蝠! – 打开消息进行查看,按Shift-F6和Enter发送

我也用Mono进行了测试,它或多或少都有效。

本文还提供了其他详细信息: 信息集成 – 模板化电子邮件的最简单方法

PS:最后我去了一个稍微复杂的场景:

  • 定义接口IEmailIntegraton
  • 上面的代码进入了DefaultEmailIntegration
  • 添加了OutlookEmailIntegration(自动化)和theBat的实现! 电子邮件集成(使用其模板格式)。
  • 允许SmartClient用户从下拉列表中选择他们的场景(或者这可以实现为“检查系统是否为默认电子邮件处理程序并自动决定”)

当然,您假设他们将安装电子邮件客户端。

我过去采用的选项(在每个人都安装了至少一个版本的Outlook的企业环境中)是使用Outlook互操作 – 您只需要引用您需要支持的最早版本。

您可以查看P /调用MAPISendDocuments (我个人试图避免),或者另一个选项是创建自己的“compose”表单并使用System.Net.Mail命名空间中的对象。

如果您打算使用Outlook,您可以使用技巧[此代码基于outlook 2010 [v14.0.0。]]如果用户打开文件(.msg),则创建Outlook MailItem并传输文件(即下载)撰写消息对话框打开自动

这是代码……

  Microsoft.Office.Interop.Outlook.Application outapp = new Application(); try { _NameSpace np = outapp.GetNamespace("MAPI"); MailItem oMsg = (MailItem)outapp.CreateItem(OlItemType.olMailItem); oMsg.To = "a@b.com"; oMsg.Subject = "Subject"; //add detail oMsg.SaveAs("C:\\Doc.msg", OlSaveAsType.olMSGUnicode);//your path oMsg.Close(OlInspectorClose.olSave); } catch (System.Exception e) { status = false; } finally { outapp.Quit(); } 

然后传输你创建的文件说“Doc.msg”

  string filename ="Doc.msg";//file name created previously path = "C:\\" + filename; //full path ; Response.ContentType="application/outlook"; Response.AppendHeader("Content-Disposition", "filename=\"" + filename + "\""); FileInfo fl = new FileInfo(path); Response.AddHeader("Content-Length", fl.Length.ToString()); Response.TransmitFile(path,0,fl.Length); Response.End();