wake-up-neo.net

Einbetten mehrerer Bilder in den E-Mail-Text mithilfe von .NET

Ich schreibe ein Programm, das E-Mails an Benutzer mit mehreren Bildern (Diagrammen) sendet, die im E-Mail-Nachrichtentext (HTML) eingebettet sind.

Wenn ich das hier ausgeführte Beispiel ausprobiert habe ... was gut funktioniert hat, wenn ich nur ein Bild einbetten muss (.____.) http://www.systemnetmail.com/faq/4.4.aspx .

Wenn ich jedoch versuchte, mehrere Bilder mit dem folgenden Code einzubetten, wird keines der Bilder eingebettet, sondern als Anhänge gesendet.

public MailMessage MailMessage(Metric metric, DateTime date)
{
    MailMessage msg = new MailMessage();
    msg.From = new MailAddress("[email protected]", "User1");
    msg.To.Add(new MailAddress("[email protected]"));
    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;
}

Irgendwelche Hinweise auf das, was mir fehlt? Ich habe die HTM-Datei geprüft, die ebenfalls als Anhang der E-Mail gesendet wird, und die HTML-Quelle sieht folgendermaßen aus:

<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>

Das Q ist also das Senden mehrerer Bilder im HTML-Body, nicht als Anhang.

12
user330612

Ich denke also herausgefunden, was das eigentliche Problem ist Es ist in dieser Zeile

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

Wie Sie sehen können, sind meine beiden Ansichten als Text.Html festgelegt. Daher überschreibt die erste die nächste und daher sehe ich nur Text und Bilder, die als Anhänge gesendet werden

Ich habe die folgende Änderung vorgenommen und es hat wie erwartet funktioniert

AlternateView avText = AlternateView.CreateAlternateViewFromString(metric.Name, null, **MediaTypeNames.Text.Plain**);
AlternateView avImages = AlternateView.CreateAlternateViewFromString(htmlBody, null, MediaTypeNames.Text.Html);
6
user330612

Die andere Möglichkeit, Bilder in E-Mails einzubetten, wenn Sie System.Net.Mail verwenden, ist 

Hängen Sie ein Bild aus dem lokalen Laufwerk an eine E-Mail an, weisen Sie ihm eine contentID zu und verwenden Sie diese contentID später in der Bild-URL. 

Dies kann geschehen durch:

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>";
20
Jagan

Zuerst können Sie versuchen, absolute URIs für eingebettete Bilder zu verwenden. Hier ist ein Beispiel aus RFC-2557 :

  From: [email protected]
  To: [email protected]
  Subject: A simple example
  Mime-Version: 1.0
  Content-Type: multipart/related; boundary="boundary-example";
          type="text/html"; start="<[email protected]@bar.net>"

  --boundary-example
  Content-Type: text/html;charset="US-ASCII"
  Content-ID: <[email protected]@bar.net>

  ... text of the HTML document, which might contain a URI
  referencing a resource in another body part, for example
  through a statement such as:
  <IMG SRC="http://www.ietf.cnri.reston.va.us/images/ietflogo.gif" ALT="IETF logo">

  --boundary-example
  Content-Location:
     http://www.ietf.cnri.reston.va.us/images/ietflogo.gif
  Content-Type: IMAGE/GIF
  Content-Transfer-Encoding: BASE64

  R0lGODlhGAGgAPEAAP/////ZRaCgoAAAACH+PUNvcHlyaWdodCAoQykgMTk5
  NSBJRVRGLiBVbmF1dGhvcml6ZWQgZHVwbGljYXRpb24gcHJvaGliaXRlZC4A
  etc...

  --boundary-example--

Sie müssen nur die LinkedResource.ContentLink-Eigenschaft anstelle von ContentId zuweisen.

Zweitens , Sie können Bilder direkt in Ihre HTML-Datei einbetten, indem Sie das URL-Schema "data" verwenden. 

    <IMG
    SRC="data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAw
    AAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFz
    ByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSp
    a/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJl
    ZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uis
    F81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PH
    hhx4dbgYKAAA7"
    ALT="Larry">

Übrigens: Ihr HTML-Markup ist nicht gut geformt. Möglicherweise interessieren Sie sich auch für „foreach“ vs. „ForEach“

5
artplastika

wenn Sie die Bilder online haben, was bedeutet, dass sie von einer gehosteten Site gesendet werden, empfehle ich Ihnen, diese Bilder einfach zu referenzieren, indem Sie einfach deren URL in die SRC eingeben.

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

die meisten Newsletter verwenden diese Methode, und ich glaube, sie ist leichter und kann weniger Ressourcen verbrauchen als sich selbst einzubetten.

hoffe das hilft

2
black sensei

Meine Alternative:

Zunächst eine kleine Erweiterung:

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

dann holen Sie sich Bildnamen aus dem Ordner:

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

ersetzen der Bildnamen durch 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);
    }

dabei ist body - ein HTML-Body, und <img src="Images/logo_shadow.png" alt="" style="width: 100%;" /> wird beispielsweise durch <img src="cid:logo_shadow.png" alt="" style="width: 100%;" /> ersetzt.

dann letzte Aktion: Bilder selbst zur Mail hinzufügen:

    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;
    }
2
Alex Zhukovskiy
        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="" />
1
Anup Shetty

Versuche Folgendes:

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;
}

Dann können Sie die Methode wie folgt aufrufen:

 mailMessage.AlternateViews.Add(GetEmbeddedImage(body));
0