OSX 邮件应用渲染了两次内联图像

Inline image rendered twice by OSX mail app

我的 .NET 4.5 Web 应用程序使用 class SmtpClient 创建电子邮件消息并将其发送给不同的收件人。 每封电子邮件包含:

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



我修改了以下属性; none 其中有帮助。

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



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

我不想做的事情:

重现问题的最少代码:

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(均为电子邮件地址)。

(我在发布问题之前自己找到了这个解决方案,但还是决定发布;它可能会对其他人有所帮助。我仍然愿意接受其他解决方案!)

我设法通过使用 class 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;
}


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