OSX邮件应用

时间:2016-04-18 12:35:20

标签: asp.net smtp .net-4.5 smtpclient

我的.NET 4.5 Web应用程序使用类SmtpClient来创建电子邮件并将其发送给各个收件人。 每封电子邮件都包含:

  • HTML邮件正文
  • 嵌入式内嵌图片(JPeg或PNG或GIF)
  • 附件(PDF)

示例代码如下。它工作正常,但OSX用户有一个抱怨。 Apple的标准邮件应用程序渲染图像两次;一旦在邮件正文中内联,并再次跟随邮件正文,则在PDF附件的预览旁边。

Screenshot Apple Mail, faulty message

我修改了以下属性;没有一个会有所帮助。

  • SmtpClient的DeliveryFormat
  • MailMessage的IsBodyHtml和BodyTransferEncoding
  • Attachment的MimeType,Inline,DispositionType,ContentId,FileName,Size,CreationDate,ModificationDate

如果我在MS Outlook中撰写类似的电子邮件并将其发送给Apple用户,则会在邮件正文中内嵌一次图像;正如我希望的那样。所以显然 是可能的。 阅读this后,我检查了原始MIME数据,并注意到Outlook使用multipart/related将邮件正文和图片组合在一起。

Screenshot Apple Mail, message from Outlook

我的问题: 如何使用System.Net.Mail中的类来模仿Outlook的行为?

我不想做的事情:

  • 使用外部图像而不是嵌入式图像(许多电子邮件客户端最初阻止这些图像以保护收件人的隐私)。
  • 使用第三方库(避免法律纠纷)。我发现here的SmtpDirect类似乎解决了这个问题(虽然我得到了一个服务器异常)但是我很难接受完全重写MS的SmtpClient实现对于这种微妙的改变是必要的。 / LI>
  • 将电子邮件发送到提取文件夹,操作生成的.eml文件,将文件推送到Exchange服务器。

重现问题的最小代码:

using System.IO;
using System.Net.Mail;
using System.Net.Mime;

namespace SendMail
{
    class Program
    {
        const string body = "Body text <img src=\"cid:ampersand.gif\" /> image.";

        static Attachment CreateGif()
        {
            var att = new Attachment(new MemoryStream(Resource1.ampersand), "ampersand.gif")
            {
                ContentId = "ampersand.gif",
                ContentType = new ContentType(MediaTypeNames.Image.Gif)
            };
            att.ContentDisposition.Inline = true;
            return att;
        }

        static Attachment CreatePdf()
        {
            var att = new Attachment(new MemoryStream(Resource1.Hello), "Hello.pdf")
            {
                ContentId = "Hello.pdf",
                ContentType = new ContentType(MediaTypeNames.Application.Pdf)
            };
            att.ContentDisposition.Inline = false;
            return att;
        }

        static MailMessage CreateMessage()
        {
            var msg = new MailMessage(Resource1.from, Resource1.to, "The subject", body)
            {
                IsBodyHtml = true
            };
            msg.Attachments.Add(CreateGif());
            msg.Attachments.Add(CreatePdf());
            return msg;
        }

        static void Main(string[] args)
        {
            new SmtpClient(Resource1.host).Send(CreateMessage());
        }
    }
}

要实际构建并运行它,您需要一个额外的资源文件Resource1.resx,其中包含两个附件(ampersandHello)和三个字符串host(SMTP服务器),fromto(两者都是电子邮件地址)。

1 个答案:

答案 0 :(得分:0)

(在我发布问题之前,我自己找到了这个解决方案,但无论如何都决定发布;它可能有助于其他人。我仍然愿意接受替代解决方案!)

我设法通过使用课程AlternateView获得了预期的效果。

static MailMessage CreateMessage()
{
    var client = new SmtpClient(Resource1.host);
    var msg = new MailMessage(Resource1.from, Resource1.to, "The subject", "Alternative message body in plain text.");
    var view = AlternateView.CreateAlternateViewFromString(body, System.Text.Encoding.UTF8, MediaTypeNames.Text.Html);
    var res = new LinkedResource(new MemoryStream(Resource1.ampersand), new ContentType(MediaTypeNames.Image.Gif))
    {
        ContentId = "ampersand.gif"
    };
    view.LinkedResources.Add(res);
    msg.AlternateViews.Add(view);
    msg.Attachments.Add(CreatePdf());
    return msg;
}

Screenshot Apple Mail, fixed message

作为副作用,消息现在还包含正文的纯文本版本(对于拒绝HTML的偏执Web客户端)。虽然它有点负担(“纯文本中的替代消息体”需要改进),但它确实可以让您更好地控制消息在不同安全设置下的呈现方式。