Open hteumeuleu opened 8 years ago
Nice to see the historical bugs, though hard to figure out the "state of things" now (as it always is with email). Usually I think it's a losing battle, but in this case the context is great.
It really seems like recommending scoped styles is just the way to go, what could we possible aim to accomplish if that works?
I agree that scoped styles is a great recommandation. However, given the current support for scoped (it only works in Firefox), it should only be applied as an extra way to secure styles.
So my main interrogation regarding prefixing is: should we recommend a way to prefix? (for example "add a class before each rule" or "prefer using ids", etc.)
I think that the way to go in order to get rid of these bugs is to render emails in a sandboxed iframe.
const render = (email, target) => {
const iframe = document.createElement("iframe")
iframe.sandbox = ""
iframe.style.width = "100%"
iframe.style.height = "0"
let timer
const tick = () => {
iframe.style.border = "none"
iframe.style.height = iframe.contentDocument.documentElement.scrollHeight + "px"
timer = requestAnimationFrame(tick)
}
iframe.onload = () => {
timer = requestAnimationFrame(tick)
}
target.appendChild(iframe)
iframe.contentDocument.open()
iframe.contentDocument.write("<html></html>")
iframe.contentDocument.documentElement.innerHTML = email
iframe.contentDocument.close()
return () => {
cancelAnimationFrame(timer)
iframe.remove()
}
}
@bloodyowl It's an interesting idea, and I've been wondering why not more webmails were using iframes. (From my tests, only La Poste and AOL, both on desktop, use them.)
The first thing that came to my mind is that I think iframes usually provide a poor user experience. They spawn weird behaviors with double scrollbars. And it appears the implementation can be tricky in a responsive context. (La Poste does this extremely bad for example. And in your code example, requiring requestAnimationFrame
to adjust the iframe height seems like a bad performance idea.) But this is mostly technical stuff, and nothing that couldn't be fixed ultimately.
However, a lot of webmails like to include contextual tools within an HTML email. For example, Gmail includes dynamic buttons that appear over big images without links.
This is typically injected right within the email itself. So this means there needs to be prefixing to prevent a developer to maliciously target this code.
Google has rolled out a new update for Gmail with support for media queries, classes and ids. This changes prefixing a little bit. Here's the result now.
<style>
div.m156faf23324c98b3 html,
div.m156faf23324c98b3 body { background:red; font:1em sans-serif }
div.m156faf23324c98b3 html~* { background:red }
div.m156faf23324c98b3 .m_7791551661652896834foo,
div.m156faf23324c98b3 .m_7791551661652896834bar { background:green; color:#fff }
div.m156faf23324c98b3 .m_7791551661652896834foo:hover { background:#000!important }
@media only screen and (min-width:30em) {
div.m156faf23324c98b3 .m_7791551661652896834foo { background:green }
div.m156faf23324c98b3 .m_7791551661652896834bar { background:green }
}
</style>
<div id=":9m" class="a3s aXjCH m156faf23324c98b3">
<u></u>
<div>
<div class="m_7791551661652896834foo m_7791551661652896834bar">Hello World.</div>
</div>
</div>
With the risk of broadening the scope (no pun intended) of this issue, there may be other incentives for email clients to utilize iframes (as suggested in https://github.com/W3CGHtmail/html-email-spec/issues/1#issuecomment-247652582) besides style scoping. Below are examples of 2 email clients, where Client A
does not utilize iframes for email messages, whereas Client B
does:
<html> <!-- Email client's document -->
<meta http-equiv="Content-Security-Policy" content="..."> <!-- Client's strict CSP -->
<div>
<!-- Email message -->
</div>
</html>
id
, class
, name
, for
, aria-labelledby
/aria-controls
/aria-owns
(etc.) attribute values.The
<audio>
element is supported, but the audio can not play due to a strict Content Security Policy
The
<video>
element is supported, but the video can not play due to a strict Content Security Policy
<html> <!-- Email client's document -->
<meta http-equiv="Content-Security-Policy" content="..."> <!-- Client's strict CSP -->
<iframe>
#document
<meta http-equiv="Content-Security-Policy" content="..."> <!-- Client's relaxed CSP -->
<div>
<!-- Email message -->
</div>
</iframe>
</html>
policy
attribute)allow
attribute)sandbox
directive or iframe sandbox
attribute)While iframes help with encapsulation, issues may still arise from clients inserting their own elements into the email (for example buttons that appear over images as noted in https://github.com/W3CGHtmail/html-email-spec/issues/1#issuecomment-250957300). In this case Shadow DOM encapsulation seems like a good solution. For example, a client's inserted button placed over an image could be placed in a Shadow root that resets any inheritable styles.
re https://github.com/W3CGHtmail/html-email-spec/issues/1#issuecomment-245066812:
There is a new proposal for scoping/namespacing with re-designed CSS @scope
rule.
In order to prevent HTML and CSS to impact a webmail's UI, webmails need to include styles safely and avoid conflicts. This is important in two ways:
.button
and an HTML email uses the same class name, the webmail's styles shouldn't apply.MarkAsSpamButton
of a webmail and hide it with a#MarkAsSpamButton
rule.Here's a comparison of how webmails procede nowadays. For these tests, I will use the following code example.
Gmail
Gmail has various support of CSS, but for the versions that support
<style>
tags (for example the public desktop webmail), here's what happens.The
<style>
is moved inside the<head>
of the webmail. The HTML is wrapped by a<div>
with a dynamic class (ex:m123ab45c6d7ef89g
). Every CSS rule is prefixed bydiv.m123ab45c6d7ef89g
.Known bugs
Recently, I realized Gmail didn't prefix
@keyframes
declarations names. So you could override Gmail's own UI animations from an email. This was reported to Google and fixed in July.Outlook.com (old version)
The old version of Outlook.com (still available in France for some accounts) wraps the HTML with a
<div class="ExternalClass">
. Everyclass
orid
attributes in HTML is prefixed byecx
. Every CSS rule is prefixed byExternalClass
.Known bugs
The old Outlook.com is famous for two major bugs in its prefixing:
Outlook.com (and Office 365)
In the new Outlook.com (and Office 365), the HTML is wrapped with a
<div class="rps_4efd">
(where the last four characters are dynamic). Everyclass
orid
attributes in HTML is prefixed byx_
.Yahoo
The desktop webmail of Yahoo wraps the HTML with a
<div id="yiv2779339103">
(with a dynamic identifier). Everyclass
orid
attributes in HTML is prefixed byyiv2779339103
(dynamic as well). Every CSS rule is prefixed by#yiv2779339103
.Known bugs
Yahoo wrongly prefixes nested media queries. The following code…
…is transformed by Yahoo into:
Even though use cases for nested media queries is still pretty rare, the parsing/prefixing bug causes the code to have a different meaning. This used to happen for regular media queries as well until Yahoo fixed it in 2015.
Orange
The desktop webmail of french ISP Orange wraps the HTML with a
<div id="message">
. Every CSS rule is prefixed by#message
.Known bugs
The first CSS rule in a media query isn't prefixed. This creates specificity issues, as all other rules are prefixed with an
id
, except this one.Orange Pro
Orange also has a brand new webmail for professionals released this summer. It wraps the HTML with a
<div id="sandBox">
. Everyclass
orid
attributes in HTML is suffixed by_sandBox
. Every CSS rule is prefixed by#sandBox
and suffixed by_sandBox
.Known bugs
The whole thing is pretty terrible. Not a single CSS rule is prefixed correctly. The suffix
_sandBox
is added even for HTML tag names or media queries. And it's added with a space before it, so it's not even correct for class names.SFR
The desktop webmail of french ISP SFR uses a similar webmail as Orange's. It wraps the HTML with a
<div id="message">
. Every CSS rule is prefixed by#message
.Known bugs
The same bug as Orange's happens.
La Poste
The desktop webmail of french ESP La Poste embeds the HTML within an
<iframe>
. It applies a class on the body of the iframe (<body class="MsgBody">
). No CSS rule is prefixed.AOL
The desktop webmail of AOL embeds the HTML within an
<iframe>
. It wraps the HTML with a<div class="aolReplacedBody">
. Every CSS rule is prefixed by.aolReplacedBody
. Theclass
orid
attributes in HTML are not prefixed. AOL uses ascoped
attribute on the<style>
element.Yandex
The desktop webmail of Yandex doesn't seem to support
<style>
tags, norclass
orid
attributes in HTML.Main takeaways
@keyframes
example or Orange's unprefixed first rule in media query bug). This can cause specificity issue in CSS or security issue for the webmail's UI.<style>
block unapplicable (see the old Outlook.com's mobile example, or Orange Pro's prefixing).scoped
attribute on a<style>
tag.Do you have more examples ? I feel that the email specification should address prefixing by providing guidelines as to how to prefix CSS rules, and what types of rules and declarations need prefixing.