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.
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);
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>";
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”
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
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;
}
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="" />
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));