diff --git a/app/assets/javascripts/discourse/components/iframed-html.js.es6 b/app/assets/javascripts/discourse/components/iframed-html.js.es6
new file mode 100644
index 00000000000..a8c39e583e8
--- /dev/null
+++ b/app/assets/javascripts/discourse/components/iframed-html.js.es6
@@ -0,0 +1,19 @@
+import Component from "@ember/component";
+
+export default Component.extend({
+ tagName: "iframe",
+ html: null,
+ className: "",
+ classNameBindings: ["html:iframed-html", "className"],
+ sandbox: "allow-same-origin",
+ attributeBindings: ['sandbox:sandbox'],
+
+ didRender() {
+ this._super(...arguments);
+ const iframeDoc = this.element.contentWindow.document;
+ iframeDoc.open("text/html", "replace");
+ iframeDoc.write(this.html);
+ iframeDoc.close();
+ }
+});
+
diff --git a/app/assets/javascripts/discourse/templates/modal/raw-email.hbs b/app/assets/javascripts/discourse/templates/modal/raw-email.hbs
index 489064f1666..0a3a0eda22d 100644
--- a/app/assets/javascripts/discourse/templates/modal/raw-email.hbs
+++ b/app/assets/javascripts/discourse/templates/modal/raw-email.hbs
@@ -37,9 +37,7 @@
{{/if}}
{{#if showHtmlPart}}
-
- {{{htmlPart}}}
-
+ {{iframed-html html=htmlPart className="incoming-email-html-part"}}
{{/if}}
{{/d-modal-body}}
diff --git a/app/assets/stylesheets/common/base/modal.scss b/app/assets/stylesheets/common/base/modal.scss
index f67a36cae67..e24acf027fa 100644
--- a/app/assets/stylesheets/common/base/modal.scss
+++ b/app/assets/stylesheets/common/base/modal.scss
@@ -494,8 +494,14 @@
box-shadow: none;
}
.incoming-email-html-part {
+ width: calc(100% - 36px);
padding: 10px 4px 4px 4px;
}
+ @media screen and (max-width: 760px) {
+ .incoming-email-html-part {
+ width: calc(100% - 10px);
+ }
+ }
}
}
diff --git a/app/assets/stylesheets/common/components/iframed-html.scss b/app/assets/stylesheets/common/components/iframed-html.scss
new file mode 100644
index 00000000000..0b613852a14
--- /dev/null
+++ b/app/assets/stylesheets/common/components/iframed-html.scss
@@ -0,0 +1,4 @@
+.iframed-html {
+ background: white;
+ border: none;
+}
diff --git a/test/javascripts/components/iframed-html-test.js.es6 b/test/javascripts/components/iframed-html-test.js.es6
new file mode 100644
index 00000000000..ad7d4113f49
--- /dev/null
+++ b/test/javascripts/components/iframed-html-test.js.es6
@@ -0,0 +1,23 @@
+import componentTest from "helpers/component-test";
+
+moduleForComponent("iframed-html", { integration: true });
+
+componentTest("appends the html into the iframe", {
+ template: `{{iframed-html html="hello
" className='this-is-an-iframe'}}`,
+
+ async test(assert) {
+ const iframe = find("iframe.this-is-an-iframe");
+ assert.equal(iframe.length, 1, "inserts an iframe");
+
+ assert.ok(
+ iframe[0].classList.contains("this-is-an-iframe"),
+ "Adds className to the iframes classList"
+ );
+
+ assert.equal(
+ iframe[0].contentWindow.document.body.querySelectorAll("#find-me").length,
+ 1,
+ "inserts the passed in html into the iframe"
+ );
+ }
+});