I'm trying to send an email, with HTML content that includes an image tag,
for example:
<img ng-src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEU...gAAASwAAAAmCC" />
unfortunately none of the mail client i'm using support this kind of "src" on image tag.
tried to Google it, it seems as known issue, but none of the answers was good for me.
by the way, i'm using AngularJS to bind the model to the html content, then pass it as an html string
to the WebApi controller, and then send it with an Smtp client.
Hope someone can help me solved this somehow,
Thanks,
Nadav S.
Yes, that is correct. Most clients do not support the "data:" url and even if they do, the size of the binary you can embed is very limited. Barely enough for a thumbnail, not enough for a real picture.
The correct way to do this is with mime multipart/related and the "cid:" url. Then one part contains the HTML and the other part contains the base64 encoded picture. The image part contains a header with a field called "Content-ID". The value is any unique string surrounded by <>. For example:
Content-ID: <xxxyyy>
In your HTML you use the following code:
<img src="cid:xxxyyy"/>
See rfc-2392 for the full specification.
Related
I'm using a mix of ejs and emailjs to send out emails in my node.js app when various events happen. I'd like to embed a base64 image (a small logo) into the email when it sends, but both Outlook and Gmail (plus Inbox by Google) fail to render the image.
I'm using this bit of code to find the mime type of the image and put together the base64 string:
MyApp.prototype.ImageToBase64 = function(image) {
var mime = require("mime")
file = fs.readFileSync(__dirname + "/images/" + image, { encoding: 'base64'})
return 'data:' + mime.lookup(image) + ';base64,' + file;
}
That works great, because I'm able to copy and paste that resulting string right into my browser and see the image. But when I send the email via emailjs, Outlook converts the +s to +. When I "View Original" in Gmail, the base64 is split up into 'chunks'. Each chunk is on a newline and each line ends with a =. If I take Gmail's version and remove the = and newline then paste it into my browser, the whole picture loads perfectly, but it just refuses to load anywhere else, regardless of whether the user is in my contact list or not.
Here's the code I'm using to send the email:
// Host, username, password and SSL (false) all set above here
server.send({
text: myTemplate,
from: "me#example.com",
to: "someone#example.com",
subject: "Testing",
attachment: [
{data:myTemplate, alternative:true}
]
})
And the template looks like this (truncated, as the other bits aren't important):
<body>
<p><img src="<%- ImageToBase64("logo.png") %>"></p>
<h1><%= Name %> has been triggered</h1>
<p><%= Name %> has been triggered. It was triggered on <%= TheDate %></p>
Any hints?
EDIT: I tried setting the headers in the "attachment" property, but with no luck
Outlook uses Word to render the images, and Word does not support embedded (src="data:image") images.
You need to attach the image as a file and set the Content-ID MIME header to the value matching the cid attribute on the image (<img src="cid:xyz">) in the HTML body.
Okay, so even though this answer is from 2013, it seems like the wisdom still holds true, in that base64 image support sucks in email clients.
Basically the only mail clients that still support inline images are either older ones (e.g. Office 2007), or Apple / Android's default mail apps.
While that's a bit disappointing, it's not the end of the world, as the email will only be seen by people on the same network as my app, so I can just point to the image hosted on the web portion of the app.
But for anyone else trying this, host your image on an image sharing site like Imgur or on your own server and use a regular ol' <image> tag to display it.
So much for self-contained emails, right?
I'm trying to remove a link totally from an email body. I have no idea how by treating body as MIME entity. But I did try for a while in the body as rich text. Here is part of my codes:
RichTextNavigator nav = body.createNavigator();
RichTextRange range = body.createRange();
nav.findFIrstString("theLinkToBeRemoved");
range.setBegin(nav);
range.setEnd(nav);
range.remove();
But only the body inside anchor tags has been removed. For example:
google
actually becomes
after processing and sending email.
My question is how to remove the anchor tags completely. Thanks!
Did you also try with the FindFirstElement method of the RichTextNavigator class, looking for an element of type RichTextItem.RTELEM_TYPE_DOCLINK ?
Hmmm... I wonder, why do you need to remove links... It sounds like a managerial issue that's solved programmatically.
I found a beautiful solution: code.google.com/p/lnrt2html
It achieves the trick of conversion from rich text to html, rather than dxl/xml. And then we have many options to parse html data, such as Jsoup. After that, use this method to input your html string stream to MIMEEntity and send: MIMEEntity - setContentFromText
I am trying to produce a PDF file using WKHTMLTOPDF library in NODE for a large HTML file. I need to be able to stuff in some content in the Header and Footer on every page. But the content on the header changes on every page for e.g, have custom numbering in a format like BX008761. The number should increment on every page.
First page will be BX008761, second page BX008762, third BX008763 so on..
I could find a thread which is related..
WKHTMLTOPDF -- Is possible to display dynamic headers?
the above thread states:
"you can feed --header-html almost anything :) Try the following to see my point:
wkhtmltopdf.exe --margin-top 30mm --header-html isitchristmas.com google.fi x.pdf
So isitchristmas.com could be www.yoursite.com/magical/ponies.php"
does the source value provided for --header-html option be called for every page of the PDF rendered or it is called just once for every PDF..?
Appreciate your support.Thank you.
EDIT : I have tried a sample program and confirmed that it will process the value provided for --header-html option on every page rendered with in PDF. I am using a remote service to return the HTML string as a response to the url.
Now it is displaying the html string as is, instead of decoding it.
when the service returns below string:
<html> <body> <span style="color:red" > 123 :: 0 :: 3000025 :: 634943551338828720</span> <body> <html>
then the header on every page is also same as above instead of displaying the text in red color. how do i make the wkhtmltohtml understand that the content it received from service need to be decoded.
appreciate if any one can suggest a workaround.
Thank you.
EDIT : I have used another work around to return a HTML page for the header content. I used essentially a HTTPHandler in asp.net to return a valid response and the issue looks to have addressed the core issue of having a dynamic header on every page.
I have questions on preventing XSS attacks.
1) Question:
I have an HTML template as Javascript string (trusted) and insert content coming from a server request (untrusted). I replace placeholders within that HTML template strings with that untrusted content and output it to the DOM using innerHTML/Text.
In particular I insert texts that I output in <div> and <p> tags that are already present in the template HTML string and form element values, i.e. texts in input tag's value attribute, select option and textarea tags.
Do I understand correctly that I can treat every inserted text mentioned above as HTML subcontext thus I only encode like so: encodeForJavascript( encodeForHTML( inserted_text ) ). Or do I have to encode the texts that I insert into value attributes of the input fields for the HTML Attribute subcontext?
After reading up on this issue on OWASP I am inclined to think that latter is only necessary in case I set the attribute with unstrusted content via Javascript like so: document.forms[ 0 ].elements[ 0 ].value = encodeForHTMLAttribute, is that correct?
2) Question:
What is the added value of server side encoding server responses that enter the client side via Ajax and get handled anyway (like in question 1). In addition, don't we risk problems when double encoding the content?
Thanks
You need to encode for the context in question, so to data inserted into html context needs to be encoded for html, and data inserted into html attributes, should be html attribute encoded. This is addition to the javascript encoding you mentioned.
I would javascript encode for transfer and then encode for the correct context client side, where I know which context is the right one.
Using Microsoft's AntiXssLibrary, how do you handle input that needs to be edited later?
For example:
User enters:
<i>title</i>
Saved to the database as:
<i>title</i>
On an edit page, in a text box it displays something like:
<i>title</i> because I've encoded it before displaying in the text box.
User doesn't like that.
Is it ok not to encode when writing to an input control?
Update:
I'm still trying to figure this out. The answers below seem to say to decode the string before displaying, but wouldn't that allow for XSS attacks?
The one user who said that decoding the string in an input field value is ok was downvoted.
Looks like you're encoding it more than once. In ASP.NET, using Microsoft's AntiXss Library you can use the HtmlAttributeEncode method to encode untrusted input:
<input type="text" value="<%= AntiXss.HtmlAttributeEncode("<i>title</i>") %>" />
This results in
<input type="text" value="<i>title</i>" /> in the rendered page's markup and is correctly displayed as <i>title</i> in the input box.
Your problem appears to be double-encoding; the HTML needs to be escaped once (so it can be inserted into the HTML on the page without issue), but twice leads to the encoded version appearing literally.
You can call HTTPUtility.HTMLDecode(MyString) to get the text back to the unencoded form.
If you are allowing users to enter HTML that will then be rendered on the site, you need to do more than just Encode and Decode it.
Using AntiXss prevents attacks by converting script and markup to text. It does not do anything to "clean" markup that will be rendered directly. You're going to have to manually remove script tags, etc. from the user's input to be fully protected in that scenario.
You'll need to strip out script tags as well as JavaScript attributes on legal elements. For example, an attacker could inject malicious code into the onclick or onmouseover attributes.
Yes, the code inside input boxes is safe from scripting attacks and does not need to be encoded.