Inserting Image With Inline HTML - c#

I am new to Web APIs, so sorry if I am missing information. I am trying to send an email from my web api with an image (not as an attachment), but I am having issues with the inline html.
Example (This is in the WebAPI Controller)
message Body = "<p>Here is an image</p>" + Model.Image;
Now this will not work, as it displays "System.Byte[]", so my alternative was to convert it with some inline html, such as...
message Body = "<p>Here is an image</p>" + "<img src=\"data:image/gif;base64,#System.Convert.ToBase64String{Model.Image)\" />;
This will return an empty element. What am I doing wrong? If I were to guess, I am not using quotations correctly, but I cannot find anyone trying to insert an image the way I am.
Site note - If I see what is being sent from the mobile app for the image, I am getting a huge string of text that is always the same, regardless of whether it is a different image. I thought I would use that like src="data:image/gif;base64,", but I just get a long string returned in the email.

You need to host your image somewhere else and use the full path. Example:
<img scr="https://static.makeuseof.com/wp-content/uploads/2017/12/test-html-online-670x335.jpg" />

Most email clients do not display base64 images. My solution was to attach the image to the email by using the following code.
MemoryStream ms = new MemoryStream(Model.Image);
message.Attachments.Add(new Attachment(ms, "Image.png", "image/png"));
I did not need to convert from byte to base64, as this was done on the mobile app before being sent to the API, so I just referenced the value that was stored in the model.

Related

Send a Email with an Image inside the string html body [duplicate]

I'm trying to send a multipart/related html email with embedded gif images. This email is generated using Oracle PL/SQL. My attempts have failed, with the image showing up as a red X (in Outlook 2007 and yahoo mail)
I've been sending html emails for some time, but my requirements are now to use several gif images in the email. I can store these on one of our web servers and just link to them, but many users email clients will not show them automatically and will need to either change settings or manually download them for each email.
So, my thoughts are to embed the image. My questions are:
What am I doing wrong here?
Is the embedding approach the correct one?
Any other options if I need to use more and more images? Attachments won't work, as the images are typically logos and icons that won't make sense out of the context of the message. Also, some elements of the email are links into an online system, so generating a static PDF and attaching won't work (to my knowledge anyway).
snippet:
MIME-Version: 1.0
To: me#gmail.com
BCC: me#yahoo.com
From: email#yahoo.com
Subject: Test
Reply-To: email#yahoo.com
Content-Type: multipart/related; boundary="a1b2c3d4e3f2g1"
--a1b2c3d4e3f2g1
content-type: text/html;
<html>
<head><title>My title</title></head>
<body>
<div style="font-size:11pt;font-family:Calibri;">
<p><IMG SRC="cid:my_logo" alt="Logo"></p>
... more html here ...
</div></body></html>
--a1b2c3d4e3f2g1
Content-Type: image/gif;
Content-ID:<my_logo>
Content-Transfer-Encoding: base64
Content-Disposition: inline
[base64 image data here]
--a1b2c3d4e3f2g1--
Many thanks.
BTW: Yes, I have verified that the base64 data is correct, as I can embed the image in the html itself (using same algo use for creating header data) and see image in Firefox/IE.
I should also note that this is NOT for spam, the emails are sent to specific clients who are expecting it daily. The content is data-driven, and not adverts.
Try to insert it directly, this way you can insert multiple images at various locations in the email.
<img src="data:image/jpg;base64,{{base64-data-string here}}" />
And to make this post usefully for others to:
If you don't have a base64-data string, create one easily at:
http://www.motobit.com/util/base64-decoder-encoder.asp from a image file.
Email source code looks something like this, but i really cant tell you what that boundary thing is for:
To: email#email.de
Subject: ...
Content-Type: multipart/related;
boundary="------------090303020209010600070908"
This is a multi-part message in MIME format.
--------------090303020209010600070908
Content-Type: text/html; charset=ISO-8859-15
Content-Transfer-Encoding: 7bit
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-15">
</head>
<body bgcolor="#ffffff" text="#000000">
<img src="cid:part1.06090408.01060107" alt="">
</body>
</html>
--------------090303020209010600070908
Content-Type: image/png;
name="moz-screenshot.png"
Content-Transfer-Encoding: base64
Content-ID: <part1.06090408.01060107>
Content-Disposition: inline;
filename="moz-screenshot.png"
[base64 image data here]
--------------090303020209010600070908--
//EDIT: Oh, i just realize if you insert the first code snippet from my post to write an email with thunderbird, thunderbird automatically changes the html code to look pretty much the same as the second code in my post.
The other solution is attaching the image as attachment and then referencing it html code using cid.
HTML Code:
<html>
<head>
</head>
<body>
<img width=100 height=100 id="1" src="cid:Logo.jpg">
</body>
</html>
C# Code:
EmailMessage email = new EmailMessage(service);
email.Subject = "Email with Image";
email.Body = new MessageBody(BodyType.HTML, html);
email.ToRecipients.Add("abc#xyz.com");
string file = #"C:\Users\acv\Pictures\Logo.jpg";
email.Attachments.AddFileAttachment("Logo.jpg", file);
email.Attachments[0].IsInline = true;
email.Attachments[0].ContentId = "Logo.jpg";
email.SendAndSaveCopy();
I don't find any of the answers here useful, so I am providing my solution.
The problem is that you are using multipart/related as the content type which is not good in this case. I am using multipart/mixed and inside it multipart/alternative (it works on most clients).
The message structure should be as follows:
[Headers]
Content-type:multipart/mixed; boundary="boundary1"
--boundary1
Content-type:multipart/alternative; boundary="boundary2"
--boundary2
Content-Type: text/html; charset=ISO-8859-15
Content-Transfer-Encoding: 7bit
[HTML code with a href="cid:..."]
--boundary2
Content-Type: image/png;
name="moz-screenshot.png"
Content-Transfer-Encoding: base64
Content-ID: <part1.06090408.01060107>
Content-Disposition: inline; filename="moz-screenshot.png"
[base64 image data here]
--boundary2--
--boundary1--
Then it will work
If it does not work, you may try one of these tools that convert the image to an HTML table (beware the size of your image though):
http://stylecampaign.com/blog/2009/12/bypass-image-blocking-by-converting-images-to-html/
http://neil.fraser.name/software/img2html/
I know this is an old post, but the current answers dont address the fact that outlook and many other email providers dont support inline images or CID images. The most effective way to place images in emails is to host it online and place a link to it in the email. For small email lists a public dropbox works fine. This also keeps the email size down.
Using Base64 to embed images in html is awesome. Nonetheless, please notice that base64 strings can make your email size big.
Therefore,
1) If you have many images, uploading your images to a server and loading those images from the server can make your email size smaller. (You can get a lot of free services via Google)
2) If there are just a few images in your mail, using base64 strings is definitely an awesome option.
Besides the choices provided by existing answers, you can also use a command to generate a base64 string on linux:
base64 test.jpg
For those who couldnt get one of these solutions working:
Send inline image in email
Following the steps laid out in the solution offered by #T30 i was able to get my inline image to display without being blocked by outlook (previous methods it was blocked). If you are using exchange like we are then also when doing:
service = new ExchangeService(ExchangeVersion);
service.AutodiscoverUrl("email#domain.com");
SmtpClient smtp = new SmtpClient(service.Url.Host);
you will need to pass it your exchange service url host. Other than that following this solution should allow you to easily send embedded imgages.
It may be of interest that both Outlook and Outlook Express can generate these multipart image email formats, if you insert the image files using the Insert / Picture menu function.
Obviously the email type must be set to HTML (not plain text).
Any other method (e.g. drag/drop, or any command-line invocation) results in the image(s) being sent as an attachment.
If you then send such an email to yourself, you can see how it is formatted! :)
FWIW, I am looking for a standalone windows executable which does inline images from the command line mode, but there seem to be none. It's a path which many have gone up... One can do it with say Outlook Express, by passing it an appropriately formatted .eml file.
You need 3 boundaries for inline images to be fully compliant.
Everything goes inside the multipart/mixed.
Then use the multipart/related to contain your multipart/alternative and your image attachment headers.
Lastly, include your downloadable attachments inside the last boundary of multipart/mixed.
There's actually a very good blog post that lists pro's and cons of three different approaches to this problem by Martyn Davies. You can read it at https://sendgrid.com/blog/embedding-images-emails-facts/.
I'd like to add a fourth approach using CSS background images.
Add
<div id="myImage"></div>
to your e-mail body and a css class like:
#myImage {
background-image: url('data:image/png;base64,iVBOR...[some more encoding]...rkggg==');
width: [the-actual-image-width];
height: [the-actual-image-height];
}
The following is working code with two ways of achieving this:
using System;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
Method1();
Method2();
}
public static void Method1()
{
Outlook.Application outlookApp = new Outlook.Application();
Outlook.MailItem mailItem = outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
mailItem.Subject = "This is the subject";
mailItem.To = "john#example.com";
string imageSrc = "D:\\Temp\\test.jpg"; // Change path as needed
var attachments = mailItem.Attachments;
var attachment = attachments.Add(imageSrc);
attachment.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x370E001F", "image/jpeg");
attachment.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001F", "myident"); // Image identifier found in the HTML code right after cid. Can be anything.
mailItem.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/id/{00062008-0000-0000-C000-000000000046}/8514000B", true);
// Set body format to HTML
mailItem.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
string msgHTMLBody = "<html><head></head><body>Hello,<br><br>This is a working example of embedding an image unsing C#:<br><br><img align=\"baseline\" border=\"1\" hspace=\"0\" src=\"cid:myident\" width=\"\" 600=\"\" hold=\" /> \"></img><br><br>Regards,<br>Tarik Hoshan</body></html>";
mailItem.HTMLBody = msgHTMLBody;
mailItem.Send();
}
public static void Method2()
{
// Create the Outlook application.
Outlook.Application outlookApp = new Outlook.Application();
Outlook.MailItem mailItem = (Outlook.MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
//Add an attachment.
String attachmentDisplayName = "MyAttachment";
// Attach the file to be embedded
string imageSrc = "D:\\Temp\\test.jpg"; // Change path as needed
Outlook.Attachment oAttach = mailItem.Attachments.Add(imageSrc, Outlook.OlAttachmentType.olByValue, null, attachmentDisplayName);
mailItem.Subject = "Sending an embedded image";
string imageContentid = "someimage.jpg"; // Content ID can be anything. It is referenced in the HTML body
oAttach.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001E", imageContentid);
mailItem.HTMLBody = String.Format(
"<body>Hello,<br><br>This is an example of an embedded image:<br><br><img src=\"cid:{0}\"><br><br>Regards,<br>Tarik</body>",
imageContentid);
// Add recipient
Outlook.Recipient recipient = mailItem.Recipients.Add("john#example.com");
recipient.Resolve();
// Send.
mailItem.Send();
}
}
}
One additional hint to Pavel Perna's post which helped me very much (cannot comment with my reputation, that's why I post this as answer): In some versions of Microsoft Exchange, the inline contents disposition is removed (see this post by Microsoft). The image is simply not part in the mail the user sees in Outlook. As a workaround, use "Content-Disposition: attachement" instead. Outlook 2016 won't show images as attachement that are used in the mail message, although they use the "Content-Disposition: attachement".
Try to resolve that with Context.Request:
<img width="150" height="60" src="#($"{Context.Request.Scheme}://{Context.Request.Host}{Context.Request.PathBase}/images/logo.png")" />
In my situation, when I used Content-ID I had that image as an attachment as well, and that was not the best solution.

Get Solvemedia image using RestSharp

I'm developing an application which needs to make a query on a website to extract certain data, such as the user's name, points / remaining balance etc.
I present a problem in the login, the client needs to solve a captcha solvemedia to be able to enter the website, I would like to extract the image of this captcha and show it to the client but I am having problems to extract it, i'm trying to do it through http requests with RestSharp, the reason I do not do it with a webbrowser or selenium is that it spends a lot more resources.
i try this:
RestClient restClient = new RestClient(#"//api-secure.solvemedia.com/papi/media?c=2#gAB09NHSertXLv3TnpobmKDxvkjsaT4m#X4wLMdkN.u0ENU8bgrS3KH9APTC4lJjokJaIfZePPIgNLL84QkOaQlXcxzHvOVTTU98Of7mo8BoC0QQuiH1RMqMrGof6BbL-tReeY8AHhPA7-nwvQKLqUEXQwTL4HhLXfZVre9jccpqQxFGIRYZH1ZQoAKCV5k1TGCLXXP9vMVsJFntDNz6Ozik02MANT1siBJRYTNIpGcj6p6Gbq5j0HvQChz7jtgdzwlj7nee0BdZphpg27ikQlVB5IUelMvSjzNNvPZawB9YbC9v6zyJngNQaJIJku2SPJkhFXIK0uoA;w=300;h=150;fg=000000;bg=f8f8f8");
var fileBytes = restClient.DownloadData(new RestRequest("#", Method.GET));
File.WriteAllBytes(Path.Combine(directory, "poster-got.jpg"), fileBytes);
The problem with this is that I only get an image that says "Media Error", Is there any way to get the image that is sent when you request the login page? Can it be done with restsharp? , if not with what library could I do it?
For downloading image I use https://github.com/jgiacomini/Tiny.RestClient
But when I try to view your image in in my browser I have a media error. I think you use a wrong url.
In your case
using Tiny.RestClient;
var client = new TinyRestClient(new HttpClient(), "#"http//api-secure.solvemedia.com");
FileInfo fileInfo = await client.
GetRequest("papi/media").
AddQueryParameter("2#gAB09NHSertXLv3TnpobmKDxvkjsaT4m#X4wLMdkN.u0ENU8bgrS3KH9APTC4lJjokJaIfZePPIgNLL84QkOaQlXcxzHvOVTTU98Of7mo8BoC0QQuiH1RMqMrGof6BbL-tReeY8AHhPA7-nwvQKLqUEXQwTL4HhLXfZVre9jccpqQxFGIRYZH1ZQoAKCV5k1TGCLXXP9vMVsJFntDNz6Ozik02MANT1siBJRYTNIpGcj6p6Gbq5j0HvQChz7jtgdzwlj7nee0BdZphpg27ikQlVB5IUelMvSjzNNvPZawB9YbC9v6zyJngNQaJIJku2SPJkhFXIK0uoA;w=300;h=150;fg=000000;bg=f8f8f8").
DownloadFileAsync("c:\"poster-got.jpg");

German characters sending data using POST method from ASP page to PHP page

I have a problem with sending data from ASP with the POST Method to a PHP page.
I would like to send mail with names. And since I live in Austria the names are in German and we have some Special characters. These characters don't arrive write.
I'm still pretty new to programming with C# btw. I had the Website before in Java-Script but I had to connect it with a database and therefore I switched to C# and now I'm like a "babe in the woods".
this.hdnDaten.Value = "ÄÖÜ|äöü|ß|é|#";
// mit POST versuchen
using (var client = new WebClient())
{
var postData = new System.Collections.Specialized.NameValueCollection();
postData.Add("von", this.hdnVon.Value);
postData.Add("an", this.hdnAn.Value);
postData.Add("betreff", this.hdnBetreff.Value);
postData.Add("daten", this.hdnDaten.Value);
byte[] response = client.UploadValues("http://xxxxxx.php", "POST", postData);
var responsebody = Encoding.UTF8.GetString(response);
}
And this is how the characters (in this.hdnDaten.Value) from above arrive in the mail-body:
ÄÖÜ|äöü|ß|é|#
Does anybody know what I can do to get the same characters in the end?
Edit 20143013: I think I have a clue: I have to encode the postData into ANSI (Codepage 1252). I tried do do this, but it doesn't work. Does anybody have an Idea how I could do this?
Edit 20140320: I don't even dare to give you the answer: I was looking all the time in the wrong place (somewhat like MH370): The problem was with the receiving side of the mail (I was using a POP3-Viewer for testing); when I downloaded the mail to Outlook everything was OK. The funny thing was that this didn't happen in the original (Javascript) Version that's why I was looking at the wrong place.
Thanks
Eddie
Try setting client.Encoding to UTF-8 before calling UploadValues. Also ensure that you read the text as UTF-8 on the server.
Try this.hdnDaten.Value = HttpUtility.UrlEncode("ÄÖÜ|äöü|ß|é|#"); on your post parameters.
on PHP you'll need to decode the parameters via html_entity_decode

ASP MVC How to pass in-memory byte stream to Java Applet?

I need to pass an image (currently a byte stream) to a Java Applet in an ASP MVC 3.0 web site.
The docs for the applet says the file can be generated dynamically by a HTTP GET.
What should the Controller action that gets the dynamic content return?
Also, how do I specify the Url in the Html for the applet?
I've tried returning a File result from the controller, and embedding a "Html.RenderAction" call where the file name should go, but I get this error (on the Html fragment included below)
CS1502: The best overloaded method match for
'System.Web.WebPages.WebPageExecutingBase.Write(System.Web.WebPages.HelperResult)'
has some invalid arguments
HTML fragment
<param name="Filename" value="#Html.RenderAction("DownLoadImage", "Document", new { DocumentId = Model.DocumentId, Page = Model.Page })">
Controller Action
public ActionResult DownloadImage(string DocumentId, int PageNo)
{
byte[] bytes = documentProvider.GetImage(DocumentId, PageNo);
return File(bytes, "image/tiff");
}
The DownloadImage action works when I use it in a "download image" ActionLink.
Please let me know if you need anything else.
Apologies if I'm doing something dumb, or missing something very obvious. I know very little about Web Development, this is my first ASP MVC application, and the first time I've used a Java Applet . . . please be gentle
Thanks.
The synatx error is from Razor -- it renders differently than the old WebForms viewmodels which is used the Writer. But that is a bit of a red herring here -- you actually don't want to do it this way anyhow -- this is trying to drop the bytes of image data you are streaming into the HTML.
What I think you want to do is pass the applet a URL to the controller action that is rendering the image. It will read it off the wire then do it's thing. Your code should probably look like:
<param name="Filename" value="#Url.Action("DownLoadImage", "Document", new { DocumentId = Model.DocumentId, Page = Model.Page })">
Have no seat time with the applet so I'm not sure if that will do the trick. You might need to make it an absolute URI, or you might have some challenges with authentication depending on how things work under the hood.

Sending a mail as both HTML and Plain Text in .net

I'm sending mail from my C# Application, using the SmtpClient. Works great, but I have to decide if I want to send the mail as Plain Text or HTML. I wonder, is there a way to send both? I think that's called multipart.
I googled a bit, but most examples essentially did not use SmtpClient but composed the whole SMTP-Body themselves, which is a bit "scary", so I wonder if something is built in the .net Framework 3.0?
If not, is there any really well used/robust Third Party Library for sending e-Mails?
The MSDN Documentation seems to miss one thing though, I had to set the content type manually, but otherwise, it works like a charm :-)
MailMessage msg = new MailMessage(username, nu.email, subject, body);
msg.BodyEncoding = Encoding.UTF8;
msg.SubjectEncoding = Encoding.UTF8;
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(htmlContent);
htmlView.ContentType = new System.Net.Mime.ContentType("text/html");
msg.AlternateViews.Add(htmlView);
What you want to do is use the AlternateViews property on the MailMessage
http://msdn.microsoft.com/en-us/library/system.net.mail.mailmessage.alternateviews.aspx
Just want to add that you can use defined constants MediaTypeNames.Text.Html and MediaTypeNames.Text.Plain instead of "text/html" and "text/plain", which is always a preferable way. It's in System.Net.Mime namespace.
So in the example above, it would be:
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(htmlContent, null, MediaTypeNames.Text.Html);
I'm just going to put a note here for anyone that's having problems and finds their way to this page - sometimes, Outlook SMTP servers will reconvert outgoing email. If you're seeing your plain-text body vanish entirely, and nothing but base64-encoded attachments, it might be because your server is reencoding the email. Google's SMTP server does not reencode email - try sending through there and see what happens.
On top of using AlternateViews views to add both the html and the plain text view, make sure you are not also setting the body of the Mail Message object.
// do not do this:
var msg = new MailMessage(model.From, model.To);
msg.Body = compiledHtml;
As it will make your email contain the html content in both views, overriding the alternative views.
For the people(like me) who've had the problem of gmail displaying the plaintext part instead of the html part.
Gmail seems to always display the last part in your message.
So if you've added the html part before your plain text part chances are gmail will always show the plain text variant.
To fix this you can simply add the plain text part before your html part.
For anyone who bumped into this issue you might want to check if you have preheader tags in your html.
In my html I've added a tag with a phrase of "Activate your client admin account by clicking the link.".
It seems like gmail is flagging the phrase "clicking the link" after removing it, all my emails that has been sent, are going straight to the inbox.

Categories