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

时间:2009-01-16 11:21:05

标签: c# email

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

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

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

我曾经在'VB6天'中做过这件事。现在不知道怎么回事......我只记得这很容易。

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

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

您需要包含ShellExecute签名as described here。我从中得到的只是一个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的东西。状态仍在进行中。耳朵仍然接受建议。

7 个答案:

答案 0 :(得分:10)

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

流程代码是:

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:2)

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

另请参阅:MAPI and managed code experiences?

答案 3 :(得分:1)

你是否使用过mailto:protocol?

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

Microsoft MailTo Documentation

答案 4 :(得分:1)

使用 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进行了测试,它或多或少都有效。

此帖中提供了其他详细信息:Information integration - simplest approach for templated emails

PS:最后我采用了稍微复杂的方案:

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

答案 5 :(得分:0)

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

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

您可以查看P / Invoking MAPISendDocuments(我个人会尝试避免),或者另一种选择是创建自己的“撰写”表单并使用{{3中的对象命名空间。

答案 6 :(得分:-1)

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

这是代码......

    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();