打开默认邮件客户端以及附件

Raj*_*123 22 c# email wpf

嗨,我正在使用WPF应用程序(使用c#).

我需要有一个功能,用户可以通过电子邮件将文件(音频文件)作为附件发送.我尝试使用Microsoft.Office.Interop.Outlook.Application命名空间但它打开outlook并且如果未在客户端的计算机上安装outlook,则无法工作.

我尝试使用SmtpClient()和命名空间MailMessage()类, System.Net.Mail但它没有打开电子邮件客户端.它通过预定义的服务器发送邮件(可能是一个问题,因为我不知道我的客户端的默认电子邮件域是什么.这个链接有我需要的所有东西,它的工作正常.

但是在那里他们使用了DllImport属性,并且使用这种方法可能会产生很多问题(从我能理解的).我不知道托管和非托管代码,所以我无法理解问题是什么.可以按照上面的链接中的示例进行操作.如果不是为什么?

你能说出或提供如何处理我的问题的链接

小智 51

我们可以利用大多数电子邮件客户端支持要加载的.EML文件格式这一事实.

因此,如果我们以一种可以将其作为.EML文件保存到文件系统的方式扩展System.Net.Mail.MailMessage类.可以使用Process.Start(filename)使用默认邮件客户端打开生成的文件

为了使其正常工作,我们必须在.EML文件中添加一行包含"X-Unsent:1"的行.此行告诉电子邮件客户端加载.EML文件,消息必须以"新消息"模式显示.

使用扩展方法的"addUnsentHeader"bool参数将此行添加到.EML文件中

扩展方法如下所示:

using System;
using System.IO;
using System.Net.Mail;
using System.Reflection;

namespace Fsolutions.Fbase.Common.Mail
{
    public static class MailUtility
    {
        //Extension method for MailMessage to save to a file on disk
        public static void Save(this MailMessage message, string filename, bool addUnsentHeader = true)
        {
            using (var filestream = File.Open(filename, FileMode.Create))
            {
                if (addUnsentHeader)
                {
                    var binaryWriter = new BinaryWriter(filestream);
                    //Write the Unsent header to the file so the mail client knows this mail must be presented in "New message" mode
                    binaryWriter.Write(System.Text.Encoding.UTF8.GetBytes("X-Unsent: 1" + Environment.NewLine));
                }

                var assembly = typeof(SmtpClient).Assembly;
                var mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");

                // Get reflection info for MailWriter contructor
                var mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);

                // Construct MailWriter object with our FileStream
                var mailWriter = mailWriterContructor.Invoke(new object[] { filestream });

                // Get reflection info for Send() method on MailMessage
                var sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);

                sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { mailWriter, true, true }, null);

                // Finally get reflection info for Close() method on our MailWriter
                var closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic);

                // Call close method
                closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

使用这样的扩展方法:

        var mailMessage = new MailMessage();
        mailMessage.From = new MailAddress("someone@yourdomain.com");
        mailMessage.Subject = "Your subject here";
        mailMessage.IsBodyHtml = true;
        mailMessage.Body = "<span style='font-size: 12pt; color: red;'>My HTML formatted body</span>";

        mailMessage.Attachments.Add(new Attachment("C://Myfile.pdf"));

        var filename = "C://Temp/mymessage.eml";

        //save the MailMessage to the filesystem
        mailMessage.Save(filename);

        //Open the file with the default associated application registered on the local machine
        Process.Start(filename);
Run Code Online (Sandbox Code Playgroud)

  • 这不起作用,它在行上抛出异常:sendMethod.Invoke(message,BindingFlags.Instance | ....... (4认同)
  • @derekantrican当你知道from地址时,这个方法有效,mailMessage.From必须在mailMessage.Save之前设置,所以看起来我们应该在使用这个方法时首先从默认的电子邮件客户端获取帐户? (3认同)
  • Windows 10邮件似乎不使用X-Unsent标头,只是将其作为非传出电子邮件打开 (3认同)
  • 我们尝试按原样使用此代码,但由于某种原因,我们的 Outlook 环境不允许我们发送电子邮件。我们的 Exchange 服务器出现故障,显示“除非您有权限,否则您无法代表此用户发送消息。” 如果我们在 Outlook 中手动选择发件人地址(即使 .eml 中的发件人地址相同),那么电子邮件就会通过。因此,我们的解决方案是在运行上述代码后删除 .eml 中的“发件人”行,然后电子邮件将在没有预定义“发件人”的情况下打开,并允许我们发送。 (3认同)

Gus*_*dor 10

您是否尝试过使用System.Diagnostics.Process.Start()适当的命令行?

mailto:some.guy@someplace.com?subject=an email&body=see attachment&attachment="/files/audio/attachment.mp3"
Run Code Online (Sandbox Code Playgroud)

&attachment开关允许您指定文件名.

好吧,我正在努力工作,但据称可以做到.我正在阅读这个怪物,并会回复你.

  • 我无法让我的电子邮件客户端处理`attachment`,因为我已经指出RFC 6068没有定义对附件的任何支持. (7认同)

Mar*_*age 5

您可以要求Windows shell打开mailto URL:

var url = "mailto:someone@somewhere.com";
Process.Start(url);
Run Code Online (Sandbox Code Playgroud)

你需要using System.Diagnostics.

您可以按照RFC 6068中的描述设置消息的各个部分,如主题和正文

var url = "mailto:someone@somewhere.com?subject=Test&body=Hello";
Run Code Online (Sandbox Code Playgroud)

不幸的是,即使某些电子邮件客户端可能有办法处理它,mailto协议也不支持附件.

  • 不幸的是,OP特别询问了附件. (12认同)