I have an HTML Mail template, with a place holder for the image. I am getting the image I need to send out of a database and saving it into a photo directory. I need to embed the image in the HTML Message.
I have explored using an AlternateView:
AlternateView htmlView = AlternateView.CreateAlternateViewFromString("<HTML> <img src=cid:VisitorImage> </HTML>");
LinkedResource VisitorImage = new LinkedResource(p_ImagePath);
VisitorImage.ContentId= "VisitorImage";
htmlView.LinkedResources.Add(VisitorImage);
Try this:
LinkedResource objLinkedRes = new LinkedResource(
Server.MapPath(".") + "\\fuzzydev-logo.jpg",
"image/jpeg");
objLinkedRes.ContentId = "fuzzydev-logo";
AlternateView objHTLMAltView = AlternateView.CreateAlternateViewFromString(
"<img src='cid:fuzzydev-logo' />",
new System.Net.Mime.ContentType("text/html"));
objHTLMAltView.LinkedResources.Add(objLinkedRes);
objMailMessage.AlternateViews.Add(objHTLMAltView);
Related
This question already has answers here:
Send inline image in email
(13 answers)
Closed 5 years ago.
I'm using the following code (C#) to embed an image into an html email:
Bitmap image = new Bitmap();
// set something to image
MemoryStream ms = new MemoryStream();
image.Save(ms, ImageFormat.Jpeg);
ContentType contentType = new ContentType(MediaTypeNames.Image.Jpeg);
ms.Seek(0, SeekOrigin.Begin);
Attachment attachment = new Attachment(ms, contentType);
attachment.ContentId = "image#email";
MailMessage mail = new MailMessage();
mail.From = new MailAddress("...");
mail.To.Add("...");
mail.Subject = "...";
mail.Body = body; // view below
mail.IsBodyHtml = true;
mail.Attachments.Add(attachment);
smtpClient.Send(mail);
ms.Close();
here the relevant part of the html body:
<img align='center' alt='' src='cid:image#email' width='100' style='padding-bottom: 0; display: inline !important; vertical-align: bottom;'>";
Viewing the email on the gmail website it looks correct: i.e. the image is embedded into the html body.
Instead, using Thunderbird the image is received as an attachment, but not recognized as jpg. The attachment is named "Part 1.2". If I double click on it the image is opened with the default image viewer installed on the computer.
What I need to add in order to correctly send embedded images in a way that is compatible with the most common email readers?
UPDATE
To name the attached image is enough to add the following:
attachment.Name = "name.jpg";
Still Thunderbird refuses to show it inside the html.
As Scarnet pointed out, this is the right way to place an embedded image into an html email:
AlternateView view = AlternateView.CreateAlternateViewFromString(body, null, MediaTypeNames.Text.Html);
LinkedResource inline = new LinkedResource(filename, MediaTypeNames.Image.Jpeg);
inline.ContentId = "image#email";
view.LinkedResources.Add(inline);
MailMessage mail = new MailMessage();
mail.From = new MailAddress(username);
mail.To.Add(address);
mail.Subject = subject;
mail.IsBodyHtml = true;
mail.AlternateViews.Add(view);
await smtpClient.SendMailAsync(mail);
I found this solution for showing an image in the body of the email:
Add image to body of an email
And it works fine but it also adds the image as an attachment to the email.
Attachment inlineLogo = new Attachment(EmailLogo.ImageUrl);
mailMsg.Attachments.Add(inlineLogo);
string contentID = "Image";
inlineLogo.ContentId = contentID;
//To make the image display as inline and not as attachment
inlineLogo.ContentDisposition.Inline = true;
inlineLogo.ContentDisposition.DispositionType = DispositionTypeNames.Inline;
//To embed image in email
mailMsg.Body = "<htm><body> <img height=\"49\" width=\"169\" src=\"cid:" + contentID + "\"> </body></html>";
There is a line of code with the comment to display as inline and not as attachment but this line isn't working because the image still gets attached to the email:
//To make the image display as inline and not as attachment
inlineLogo.ContentDisposition.Inline = true;
inlineLogo.ContentDisposition.DispositionType = DispositionTypeNames.Inline;
How can I stop the image from attaching to the email?
Use AlternateView to store your html code with image embedded as LinkedResource:
string contentID = "Image";
var inlineLogo = new LinkedResource(EmailLogo.ImageUrl, "image/png");
inlineLogo.ContentId = contentID;
var htmlView = AlternateView.CreateAlternateViewFromString(
"<html><body> <img height=\"30\" width=\"30\" src=\"cid:" + contentID + "\"> </body></html>",
Encoding.UTF8, "text/html");
htmlView.TransferEncoding = TransferEncoding.QuotedPrintable;
htmlView.LinkedResources.Add(inlineLogo);
mailMsg.AlternateViews.Add(htmlView);
P.S. Embedding image as base24 string is not very good idea, because many mail clients do not support such ability.
If you want to display an image in an email it has to exist somewhere. It is either attached as part of the message payload (regardless of whether it is "displayed inline" or as a true "attachment") - or is fetched from a remote web server when the reader reads the email (and optionally has to choose to "view images")
To not attach the image to the email payload itself:
You have to host the image on a public web server so that the reader opening the message can access it.
You have to use a fully qualified URL in your message body source, so it can find it.
Assuming you have stored the image on your web server at the following URL:
http://www.example.com/images/myimage.jpg
... then your source should simply change to reflect:
mailMsg.Body = "<html><body> <img height=\"49\" width=\"169\" src=\"http://www.example.com/images/myimage.jpg\"> </body></html>";
No need to attach it at all.
An alternative that can be used which embeds the image inline, but also isnt generally filtered by email clients is (which is generally the case today in things like junk mail) You could use a DataURL.
<img src="data:image/<type>;base64,<string>"/>
where <type> is the image type, ie jpg, gif,png, and is a base64 string. Just convert the image to a base64 string and assign it to the source using the above syntax
For example, with a jpeg...
mailMsg.Body = "<html><body> <img height=\"49\" width=\"169\" src=\"data:image/jpg;base64,<myPictureString>"\"> </body></html>";
I am using EWS to receive/send emails. I am sending embedded images in the email to navigate users to another page. However, when sending to other emails clients like gmail and yahoo, the images are not being set as html, but text. I created a console app below to demonstrate:
static void Main(string[] args)
{
var service = getExchangeService(NetworkCreds.Credentials);
// Create the HTML body with the content identifier of the attachment.
string html = #"<html>
<head>
</head>
<body>
<img width=100 height=100 id=""1"" src=""cid:Party.jpg"">
</body>
</html>";
// Create the email message.
EmailMessage email = new EmailMessage(service);
email.Subject = "Test Email";
email.Body = new MessageBody(BodyType.HTML, html);
email.ToRecipients.Add("test#gmail.com");
// Add the attachment to the local copy of the email message.
string file = #"C:\projects\Party.jpg";
email.Attachments.AddFileAttachment("Party.jpg", file);
email.Attachments[0].IsInline = true;
email.Attachments[0].ContentId = "Party.jpg";
// Save a copy of the email, add the attachment, and then send the email. This method results in three calls to EWS.
email.SendAndSaveCopy();
}
When I receive the message in outlook it works fine but in gmail it only has the following text in the body: [cid:Party.jpg] with the file attachment below. I know Gmail and other clients have extensive processing of images and that may the case of why it's not displaying correctly. My question is if inline images can be sent from exchange web services to other clients and be processed correctly?
This is how you fix this kind of thing
bodyText = bodyText.Replace("cid:" + fileAttachment.ContentId, fileAttachment.Name);
Be sure to attach the file as "Image 001.png" or whatever it is, then you can resend this e-mail with images in tact :)
I know that i am a bit late but maybe someone else will stuck at a similar problem and this could help solving the problem.
You could set the image as base64 encoded image.
In my case i wanted to load a preview of an existing email in a browser control.
Everything worked except showing the images. But replacing them to base64 encoded strings worked perfectly.
In this example following code should work as described:
EmailMessage email = new EmailMessage(service);
email.Subject = "Test Email";
email.Body = new MessageBody(BodyType.HTML, html);
email.ToRecipients.Add("test#gmail.com");
// Add the attachment to the local copy of the email message.
string file = #"C:\projects\Party.jpg";
MemoryStream stream = new MemoryStream();
email.Attachments.AddFileAttachment("Party.jpg", file).Load(stream);
byte[] imageBytes = stream.ToArray();
// Convert byte[] to Base64 String
string base64String = Convert.ToBase64String(imageBytes);
stream.close();
email.Attachments[0].IsInline = true;
email.Attachments[0].ContentId = "Party.jpg";
string html = #"<html>
<head>
</head>
<body>
<img width=100 height=100 id=""1"" src=""data: image/jpg;base64, " + base64String + """>
</body>
</html>";
I've found this link on how to using Razor Engine for email templates in asp.net and it worked great. But I've tried to have a logo in the email template with an image.
Something like this:
EmailTemplate.cshtml (this by the way is a strongly-type view)
<html>
<body>
<img src="logo.jpg" />
</body>
</html>
and when I try to submit it on email, it seems that the image path was not read, it only rendered an X in the content.
I'm thinking to pass the image path as part of the Model but it seems odd that way. Is there any way to achieve this?
Any help would be much appreciated. Thanks
To see image everywhere you can use these options:
Absolute Url
You can simply use full absolute path of image for example "http://example.com/images/logo.png"
IMO It is the most simple option and recommended for your problem.
Attachment
As mentioned by Mason in comments You can attach image to mail and then put image tag and useContentId of attachment:
//(Thanks to Mason for comment and Thanks to Bartosz Kosarzyck for sample code)
string subject = "Subject";
string body = #"<img src=""$CONTENTID$""/> <br/> Some Content";
MailMessage mail = new MailMessage();
mail.From = new MailAddress("from#example.com");
mail.To.Add(new MailAddress("to#example.com"));
mail.Subject = subject;
mail.Body = body;
mail.Priority = MailPriority.Normal;
string contentID = Guid.NewGuid().ToString().Replace("-", "");
body = body.Replace("$CONTENTID$", "cid:" + contentID);
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(body, null, "text/html");
//path of image or stream
LinkedResource imagelink = new LinkedResource(#"C:\Users\R.Aghaei\Desktop\outlook.png", "image/png");
imagelink.ContentId = contentID;
imagelink.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
htmlView.LinkedResources.Add(imagelink);
mail.AlternateViews.Add(htmlView);
SmtpClient client = new SmtpClient();
client.Host = "mail.example.com";
client.Credentials = new NetworkCredential("from#example.com", "password");
client.Send(mail);
Data Uri
you can use data uri (data:image/png;base64,....).
Not Recommended because of weak support in most of mail clients, I tested it with Outlook.com(web) and OutlookWebAccess(web) and Office Outlook(Windows) and Outlook(windows 8.1) and unfortunately it worked only on OutlookWebAccess(web).
I am using C#.Net to send out a HTML email which contains embedded images. These emails work fine in Firefox and chrome but the images do not show up in Internet Explorer (IE). I know that the IE settings are not causing the problem since embedded images sent using Blat work just fine. Am I missing some option such as character set which is causing this problem? My code is as follows
MailMessage msg = new MailMessage();
MailAddress from = new MailAddress("Myemail#MyDomain", "My Name");
msg.To.Add("Myemail#MyDomain");
msg.From = from;
msg.Subject = "My subjecct line";
AlternateView htmlView = AlternateView.CreateAlternateViewFromString("This is a sample JPG embedded image<br><img src=\"cid:image1.jpg\">", null, "text/html");
LinkedResource EmbeddedObjects1 = new LinkedResource("PathToImage\\image1.jpg");
EmbeddedObjects1.ContentId = "image1.jpg";
htmlView.LinkedResources.Add(EmbeddedObjects1);
msg.AlternateViews.Add(htmlView);
SmtpClient smtpclient = new SmtpClient("mailhost.domain.com", PortNumber);
smtpclient.Send(msg);
Maybe it helps if you create the LinkedResource with a ContentType combined with Coding Gorilla's idea of a guid as the content-id:
Guid contentId = Guid.NewGuid().ToString();
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(
"This is a sample JPG embedded image<br><img src=\"cid:" + contentId + "\">",
null, "text/html");
ContentType ct = new ContentType(MediaTypeNames.Image.Jpeg);
LinkedResource EmbeddedObjects1 = new LinkedResource("PathToImage\\image1.jpg", ct);
EmbeddedObjects1.ContentId = contentId;
htmlView.LinkedResources.Add(EmbeddedObjects1);
Try adding the following.
msg.IsBodyHtml = true;
Additionally, I usually setup my AlternateView like this.
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(html, new ContentType("text/html"));
Embedded images work by creating dataUri schemes. IE < 8 doesn't support those.