17

我正在编写一个程序,该程序向用户发送电子邮件,并在电子邮件正文 (HTML) 中嵌入了多个图像(图表)。

当我尝试位于此处的示例时..当我只需要嵌入一个图像 http://www.systemnetmail.com/faq/4.4.aspx时效果很好。

但是,当我尝试使用以下代码嵌入多个图像时,没有任何图像被嵌入,而是作为附件发送。

public MailMessage MailMessage(Metric metric, DateTime date)
{
    MailMessage msg = new MailMessage();
    msg.From = new MailAddress("test@gmail.com", "User1");
    msg.To.Add(new MailAddress("test@gmail.com"));
    msg.Subject = "Trend for metric: " + metric.Name;
    msg.IsBodyHtml = true;

    // Generate the charts for the given metric
    var charts = this.GenerateCharts(metric, date);
    int i = 0;
    string htmlBody = "<html><body>";
    List<LinkedResource> resources = new List<LinkedResource>();
    foreach (var chart in charts)
    {
        string imageTag = string.Format("<img src=cid:chart{0} /><br>", i);
        htmlBody += imageTag;
        LinkedResource graph = new LinkedResource(chart.Value, "image/jpeg");
        graph.ContentId = "chart" + i;
        resources.Add(graph);
        i++;
    }

    htmlBody += "</body></html>";

    // Alternate view for embedded images
    AlternateView avText = AlternateView.CreateAlternateViewFromString(metric.Name, null, MediaTypeNames.Text.Html);
    AlternateView avImages = AlternateView.CreateAlternateViewFromString(htmlBody, null, MediaTypeNames.Text.Html);

    // Add all the images as linked resources
    resources.ForEach(x => avImages.LinkedResources.Add(x));

    // Add the views for image
    msg.AlternateViews.Add(avText);
    msg.AlternateViews.Add(avImages);


    return msg;
}

任何线索,因为我错过了什么?我检查了 .htm 文件,该文件也作为电子邮件附件发送,html 源代码如下所示:

<html>><body><img src=cid:chart0 /><br><img src=cid:chart1 /><br><img src=cid:chart2/><br><img src=cid:chart3 /><br><img src=cid:chart4 /><br></body></html>

所以 Q 是如何在 html body 中发送多个图像,而不是作为附件。

4

7 回答 7

24

使用时在电子邮件中嵌入图像的另一种方法System.Net.Mail

将图像从本地驱动器附加到电子邮件并为其分配一个contentID,然后contentID在图像 URL 中使用它。

这可以通过以下方式完成:

var contentID = "Image";
var inlineLogo = new Attachment(@"C:\Desktop\Image.jpg");
inlineLogo.ContentId = contentID;
inlineLogo.ContentDisposition.Inline = true;
inlineLogo.ContentDisposition.DispositionType = DispositionTypeNames.Inline;

msg.IsBodyHtml = true;
msg.Attachments.Add(inlineLogo);
msg.Body = "<htm><body> <img src=\"cid:" + contentID + "\"> </body></html>";
于 2013-10-02T14:18:13.487 回答
6
于 2011-08-13T06:37:03.267 回答
6

所以,我想弄清楚了这一行的实际问题是什么

// Alternate view for embedded images
    AlternateView avText = AlternateView.CreateAlternateViewFromString(metric.Name, null, MediaTypeNames.Text.Html);
    AlternateView avImages = AlternateView.CreateAlternateViewFromString(htmlBody, null, MediaTypeNames.Text.Html);

如您所见,我的两个视图都指定为 Text.Html,因此第一个视图覆盖了下一个视图,因此我只看到文本和图像作为附件发送

我做了以下更改,它按预期工作

AlternateView avText = AlternateView.CreateAlternateViewFromString(metric.Name, null, **MediaTypeNames.Text.Plain**);
AlternateView avImages = AlternateView.CreateAlternateViewFromString(htmlBody, null, MediaTypeNames.Text.Html);
于 2011-08-13T18:19:08.303 回答
4

我的替代品:

首先,一点扩展:

public static class RegexExtensions
{
    public static string GetPattern(this IEnumerable<string> valuesToSearch)
    {
        return string.Format("({0})", string.Join("|", valuesToSearch));
    }
}

然后从文件夹中获取图像名称:

    private string[] GetFullNamesOfImages()
    {
        string images = Path.Combine(_directoryName, "Images");
        if (!Directory.Exists(images))
            return new string[0];
        return Directory.GetFiles(images);
    }

然后用 cid 替换图像名称:

    private string InsertImages(string body)
    {
        var images = GetFullNamesOfImages().Select(Path.GetFileName).ToArray();
        return Regex.Replace(body, "(Images/)?" + images.GetPattern(), "cid:$2", RegexOptions.IgnoreCase | RegexOptions.Compiled);
    }

其中 body - 是 HTML 正文,例如,<img src="Images/logo_shadow.png" alt="" style="width: 100%;" />将替换为<img src="cid:logo_shadow.png" alt="" style="width: 100%;" />

然后最后一个动作:将图像本身添加到邮件中:

    private MailMessage CreateMail(SmtpClient smtp, string toAddress, string body)
    {
        var images = GetFullNamesOfImages();

        string decodedBody = WebUtility.HtmlDecode(body);
        var text = AlternateView.CreateAlternateViewFromString(decodedBody, null, MediaTypeNames.Text.Plain);
        var html = AlternateView.CreateAlternateViewFromString(body, null, MediaTypeNames.Text.Html);
        foreach (var image in images)
        {
            html.LinkedResources.Add(new LinkedResource(image, new ContentType("image/png"))
                                     {
                                         ContentId = Path.GetFileName(image)
                                     });
        }


        var credentials = (NetworkCredential) smtp.Credentials;

        var message = new MailMessage(new MailAddress(credentials.UserName), new MailAddress(toAddress))
                      {
                          Subject = "Some subj",
                          Body = decodedBody
                      };
        message.AlternateViews.Add(text);
        message.AlternateViews.Add(html);
        return message;
    }
于 2014-10-28T10:04:30.663 回答
3

如果您有在线图像,即从托管站点发送,我建议您只需将它们的 url 放在 src 中即可引用这些图像。

<!-- using artplastika  examples -->
<IMG SRC="http://www.ietf.cnri.reston.va.us/images/ietflogo.gif" ALT="IETF logo" />

大多数时事通讯都使用这种方法,我相信它比嵌入本身更轻巧,消耗的资源更少。

希望这可以帮助

于 2011-08-13T22:27:48.543 回答
2
        AlternateView avHtml = AlternateView.CreateAlternateViewFromString(body, null, MediaTypeNames.Text.Html);
        LinkedResource inline = new LinkedResource(System.Web.HttpContext.Current.Server.MapPath("~/Images/e1.jpg"), MediaTypeNames.Image.Jpeg);
        inline.ContentId = "1";
        inline.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
        avHtml.LinkedResources.Add(inline);

        LinkedResource inline1 = new LinkedResource(System.Web.HttpContext.Current.Server.MapPath("~/CImages/2.jpg"), MediaTypeNames.Image.Jpeg);
        inline1.ContentId = "2";
        inline1.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
        avHtml.LinkedResources.Add(inline1);

        LinkedResource inline2 = new LinkedResource(System.Web.HttpContext.Current.Server.MapPath("~/Images/3.jpg"), MediaTypeNames.Image.Jpeg);
        inline2.ContentId = "3";
        inline2.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
        avHtml.LinkedResources.Add(inline2);

        LinkedResource inline3 = new LinkedResource(System.Web.HttpContext.Current.Server.MapPath("~/Content/Images/4.jpg"), MediaTypeNames.Image.Jpeg);
        inline3.ContentId = "4";
        inline3.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
        avHtml.LinkedResources.Add(inline3);

        MailMessage mail = new MailMessage();
        mail.AlternateViews.Add(avHtml);

HTML:

       <img src="cid:1" alt="" />
       <img src="cid:2" alt="" />
       <img src="cid:3" alt="" /`
       <img src="cid:4" alt="" />
于 2016-06-07T10:23:20.750 回答
0

尝试以下操作:

private static ICollection<LinkedResource> GetLinkedResources()
{
    var linkedResources = new List<LinkedResource>();

    linkedResources.Add(new LinkedResource(@"imagepath")
    {
        ContentId = "HeaderId",
        TransferEncoding = TransferEncoding.Base64
    });

    linkedResources.Add(new LinkedResource(@"imagepath")
    {
        ContentId = "MapId",
        TransferEncoding = TransferEncoding.Base64
    });

    return linkedResources;
}

然后您可以按如下方式调用该方法:

 mailMessage.AlternateViews.Add(GetEmbeddedImage(body));
于 2019-01-16T16:52:24.310 回答