web-dev-qa-db-fra.com

Comment incorporer plusieurs images dans le corps d'un e-mail à l'aide de .NET

J'écris un programme qui envoie des courriers électroniques aux utilisateurs avec plusieurs images (diagrammes) incorporées dans le corps du message électronique (HTML).

Lorsque j’ai essayé l’échantillon situé ici .. qui a bien fonctionné lorsque je n’ai incorporé qu’une image http://www.systemnetmail.com/faq/4.4.aspx .

Mais, lorsque j'ai essayé d'incorporer plusieurs images à l'aide du code ci-dessous, aucune des images n'est en cours d'intégration, mais elles sont envoyées en tant que pièces jointes.

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

J'ai vérifié le fichier .htm, qui est également envoyé en pièce jointe à l'e-mail, et le code source HTML se présente comme suit:

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

Le Q est donc comment envoyer plusieurs images dans le corps HTML, et non en pièce jointe.

12
user330612

Donc, je pense comprendre quel est le problème réel C'est dans cette ligne

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

Comme vous pouvez le constater, mes deux vues sont spécifiées en tant que Text.Html. Par conséquent, la première position remplace la suivante et je ne vois que le texte et les images sont envoyées en tant que pièces jointes.

J'ai fait le changement suivant et cela a fonctionné comme prévu

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

L’autre façon d’incorporer des images dans un courrier électronique lors de l’utilisation de System.Net.Mail est la suivante: 

Joignez une image d'un lecteur local à un courrier électronique et affectez-lui une variable contentID, puis utilisez-la contentID dans l'URL de l'image. 

Cela peut être fait par:

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

First , vous pouvez essayer d’utiliser des URI absolus pour les images incorporées. Voici un exemple de 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="<foo3@[email protected]>"

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

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

Il vous suffit d’affecter la propriété LinkedResource.ContentLink au lieu de ContentId.

Second , vous pouvez incorporer des images directement dans votre code HTML avec le schéma d'URL "data"

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

Par ailleurs, votre balise HTML n'est pas bien formée. Vous pourriez également être intéressé par “foreach” vs “ForEach”

5
artplastika

si vous avez les images en ligne, c'est-à-dire l'envoi depuis un site hébergé, je vous suggère de référencer ces images simplement en mettant leur URL dans le fichier src.

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

la plupart des newsletters utilisent cette méthode, et j'estime qu'elle est plus légère et peut consommer moins de ressources que l'intégration.

j'espère que cela t'aides

2
black sensei

Mon alternatie:

Tout d'abord, une petite extension:

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

puis obtenez les noms d'image du dossier:

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

puis en remplaçant les noms d'images par 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);
    }

où body - est le corps HTML et, par exemple, <img src="Images/logo_shadow.png" alt="" style="width: 100%;" /> sera remplacé par <img src="cid:logo_shadow.png" alt="" style="width: 100%;" />

puis dernière action: ajouter des images à un mail:

    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

Essayez ce qui suit:

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

Ensuite, vous pouvez appeler la méthode comme suit:

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