From cbb720d530414f6813f49541567387da0db75fbc Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Tue, 24 Dec 2019 17:15:09 -0300 Subject: [PATCH 1/4] [NEW] Enforce plain text emails converting from HTML when no text version supplied --- app/mailer/server/api.js | 12 ++++-- package-lock.json | 90 +++++++++++++++++++++++++++++++++++++++- package.json | 1 + 3 files changed, 98 insertions(+), 5 deletions(-) diff --git a/app/mailer/server/api.js b/app/mailer/server/api.js index afe1908620810..bcfdec4ffe203 100644 --- a/app/mailer/server/api.js +++ b/app/mailer/server/api.js @@ -4,6 +4,7 @@ import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; import _ from 'underscore'; import s from 'underscore.string'; import juice from 'juice'; +import stripHtml from 'string-strip-html'; import { settings } from '../../settings'; @@ -93,14 +94,19 @@ export const rfcMailPatternWithName = /^(?:.*<)?([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~- export const checkAddressFormat = (from) => rfcMailPatternWithName.test(from); -export const sendNoWrap = ({ to, from, replyTo, subject, html, headers }) => { +export const sendNoWrap = ({ to, from, replyTo, subject, html, text, headers }) => { if (!checkAddressFormat(to)) { return; } - Meteor.defer(() => Email.send({ to, from, replyTo, subject, html, headers })); + + if (!text) { + text = stripHtml(html); + } + + Meteor.defer(() => Email.send({ to, from, replyTo, subject, html, text, headers })); }; -export const send = ({ to, from, replyTo, subject, html, data, headers }) => sendNoWrap({ to, from, replyTo, subject: replace(subject, data), html: wrap(html, data), headers }); +export const send = ({ to, from, replyTo, subject, html, text, data, headers }) => sendNoWrap({ to, from, replyTo, subject: replace(subject, data), text: text ? replace(text, data) : stripHtml(replace(html, data)), html: wrap(html, data), headers }); export const checkAddressFormatAndThrow = (from, func) => { if (checkAddressFormat(from)) { diff --git a/package-lock.json b/package-lock.json index 495b4f965ce09..f2ac6f7a035b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20587,8 +20587,12 @@ "is-natural-number": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", - "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=", - "dev": true + "integrity": "sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=" + }, + "is-natural-number-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number-string/-/is-natural-number-string-1.0.1.tgz", + "integrity": "sha1-0OvxwBH64tOwc02MgBFuJRKkoug=" }, "is-number": { "version": "3.0.0", @@ -21890,6 +21894,11 @@ "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" }, + "lodash.trim": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/lodash.trim/-/lodash.trim-4.5.1.tgz", + "integrity": "sha1-NkJefukL5KpeJ7zruFt9EepHqlc=" + }, "lodash.unescape": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", @@ -21906,6 +21915,11 @@ "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", "dev": true }, + "lodash.without": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.without/-/lodash.without-4.4.0.tgz", + "integrity": "sha1-PNRXSgC2e643OpS3SHcmQFB7eqw=" + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -26522,6 +26536,45 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true }, + "ranges-apply": { + "version": "3.0.46", + "resolved": "https://registry.npmjs.org/ranges-apply/-/ranges-apply-3.0.46.tgz", + "integrity": "sha512-RhumyuPWm5tm96LVcU1vLQmKpuRF1F30omdcLPOashxOxBw41ANt3RVzL6YzKeUg2vbLOXVaXukFn/ImOdmqQA==", + "requires": { + "is-natural-number-string": "^1.0.1", + "ranges-merge": "^4.2.29" + } + }, + "ranges-merge": { + "version": "4.2.29", + "resolved": "https://registry.npmjs.org/ranges-merge/-/ranges-merge-4.2.29.tgz", + "integrity": "sha512-1CeZASV8XqpQ3ItcbsuqVp4a6uqHvfUa65Y3j9AyFBH3zhjZVlP5dRGf5U5Ym8fKOQ1fZYcn6lQJ577lyojCzA==", + "requires": { + "lodash.clonedeep": "^4.5.0", + "lodash.isplainobject": "^4.0.6", + "ranges-sort": "^3.10.46" + } + }, + "ranges-push": { + "version": "3.6.13", + "resolved": "https://registry.npmjs.org/ranges-push/-/ranges-push-3.6.13.tgz", + "integrity": "sha512-HDXJUwA4xbdbkYxCzne64+mCHYoHXOnTtukQ7RwB3eFLnunU2iqTL6zuktr5iJ2Hizr8am5ZaEsM38HMm6EQGA==", + "requires": { + "is-natural-number-string": "^1.0.1", + "lodash.clonedeep": "^4.5.0", + "ranges-merge": "^4.2.29", + "string-collapse-leading-whitespace": "^2.0.10", + "string-trim-spaces-only": "^2.8.9" + } + }, + "ranges-sort": { + "version": "3.10.46", + "resolved": "https://registry.npmjs.org/ranges-sort/-/ranges-sort-3.10.46.tgz", + "integrity": "sha512-H07aLdjKQRz3tUNHCj5P9Tof1vH35J4c3atXl8T/fs3SATKgzpkjACz9MfuuKgvQsXOFau2GDvQ/hl6Szw39/Q==", + "requires": { + "is-natural-number": "^4.0.1" + } + }, "raw-body": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", @@ -29062,11 +29115,44 @@ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, + "string-collapse-leading-whitespace": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/string-collapse-leading-whitespace/-/string-collapse-leading-whitespace-2.0.10.tgz", + "integrity": "sha512-Hpm6voTLToJW8zAioRF11ertTDPIT0v7J0xsVTpcDcTFgDBLm0byln3L9XthbaBSIghAM36IIRxAnW8RW0FD/g==" + }, + "string-left-right": { + "version": "2.3.12", + "resolved": "https://registry.npmjs.org/string-left-right/-/string-left-right-2.3.12.tgz", + "integrity": "sha512-mz7bncqHVrxBWvAZn3HhHKg/tm55x+INd2BE7IRn/CRAVHZQd5fhanJjCq7hGdsWjQ0QX2lnU3bhGE6KopcAAA==", + "requires": { + "lodash.clonedeep": "^4.5.0", + "lodash.isplainobject": "^4.0.6" + } + }, + "string-strip-html": { + "version": "4.3.12", + "resolved": "https://registry.npmjs.org/string-strip-html/-/string-strip-html-4.3.12.tgz", + "integrity": "sha512-f8er5/6SQ9sABwnJZBU6o7aoIUtGMQdMNcBP1nOrRRizIN8HvxWN7doiJltMbwJ8hgewbNFP3qDh+iayqcbUtQ==", + "requires": { + "ent": "^2.2.0", + "lodash.isplainobject": "^4.0.6", + "lodash.trim": "^4.5.1", + "lodash.without": "^4.4.0", + "ranges-apply": "^3.0.46", + "ranges-push": "^3.6.13", + "string-left-right": "^2.3.12" + } + }, "string-template": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/string-template/-/string-template-1.0.0.tgz", "integrity": "sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y=" }, + "string-trim-spaces-only": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/string-trim-spaces-only/-/string-trim-spaces-only-2.8.9.tgz", + "integrity": "sha512-atfGwUCChsXQ0WEqX1Ju2YYC/6yqpnq8fL8jl2BUpjNR13b+s6q/SmmdDG10H+t4JB8/cRi9klyYuwctvgjFJg==" + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", diff --git a/package.json b/package.json index a95a9eaf9a8f5..60b138af849d7 100644 --- a/package.json +++ b/package.json @@ -203,6 +203,7 @@ "sharp": "^0.22.1", "speakeasy": "^2.0.0", "stream-buffers": "^3.0.2", + "string-strip-html": "^4.3.12", "styled-components": "^4.4.0", "tar-stream": "^1.6.2", "toastr": "^2.1.4", From 1be0e17fdd2e7b2177a80ed59a70f752daa06f1b Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Tue, 24 Dec 2019 17:33:11 -0300 Subject: [PATCH 2/4] [NEW] Setting to only send plain text emails --- app/lib/server/startup/email.js | 8 ++++++++ app/mailer/server/api.js | 12 +++++++++++- packages/rocketchat-i18n/i18n/en.i18n.json | 1 + packages/rocketchat-i18n/i18n/pt-BR.i18n.json | 1 + 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/app/lib/server/startup/email.js b/app/lib/server/startup/email.js index d31d4de65a59a..a132a4291f457 100644 --- a/app/lib/server/startup/email.js +++ b/app/lib/server/startup/email.js @@ -2,6 +2,10 @@ import { settings } from '../../../settings'; settings.addGroup('Email', function() { this.section('Style', function() { + this.add('email_plain_text_only', false, { + type: 'boolean', + }); + this.add('email_style', `html, body, .body { font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Helvetica Neue','Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol','Meiryo UI',Arial,sans-serif; } body, .body { @@ -103,6 +107,10 @@ settings.addGroup('Email', function() { multiline: true, i18nLabel: 'email_style_label', i18nDescription: 'email_style_description', + enableQuery: { + _id: 'email_plain_text_only', + value: true, + }, }); }); diff --git a/app/mailer/server/api.js b/app/mailer/server/api.js index bcfdec4ffe203..45c7f10030f31 100644 --- a/app/mailer/server/api.js +++ b/app/mailer/server/api.js @@ -50,7 +50,13 @@ export const replaceEscaped = (str, data = {}) => replace(str, { return ret; }, {}), }); -export const wrap = (html, data = {}) => replaceEscaped(body.replace('{{body}}', html), data); +export const wrap = (html, data = {}) => { + if (settings.get('email_plain_text_only')) { + return replace(html, data); + } + + return replaceEscaped(body.replace('{{body}}', html), data); +}; export const inlinecss = (html) => juice.inlineContent(html, Settings.get('email_style')); export const getTemplate = (template, fn, escape = true) => { let html = ''; @@ -103,6 +109,10 @@ export const sendNoWrap = ({ to, from, replyTo, subject, html, text, headers }) text = stripHtml(html); } + if (settings.get('email_plain_text_only')) { + html = undefined; + } + Meteor.defer(() => Email.send({ to, from, replyTo, subject, html, text, headers })); }; diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index a00e511e181ad..13baefd34eccb 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1231,6 +1231,7 @@ "email_style_label": "Email Style", "email_style_description": "Avoid nested selectors", "Email_verified": "Email verified", + "email_plain_text_only": "Send only plain text emails", "Emoji": "Emoji", "Emoji_provided_by_JoyPixels": "Emoji provided by JoyPixels", "EmojiCustomFilesystem": "Custom Emoji Filesystem", diff --git a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json index f46f8f0530dbd..be6e4022459c1 100644 --- a/packages/rocketchat-i18n/i18n/pt-BR.i18n.json +++ b/packages/rocketchat-i18n/i18n/pt-BR.i18n.json @@ -1152,6 +1152,7 @@ "Email_subject": "Assunto", "email_style_label": "Estilo do Email", "email_style_description": "Evite seletores aninhados", + "email_plain_text_only": "Enviar emails apenas em texto puro", "Email_verified": "Email verificado", "Emoji": "Emoji", "EmojiCustomFilesystem": "Sistema de arquivos do emoji customizado", From 08b377606ff36b80dff1ccd43988d95396ed856c Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Wed, 8 Jan 2020 09:57:17 -0300 Subject: [PATCH 3/4] Fix identation --- app/mailer/server/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/mailer/server/api.js b/app/mailer/server/api.js index bb105afc10148..45c7f10030f31 100644 --- a/app/mailer/server/api.js +++ b/app/mailer/server/api.js @@ -113,7 +113,7 @@ export const sendNoWrap = ({ to, from, replyTo, subject, html, text, headers }) html = undefined; } - Meteor.defer(() => Email.send({ to, from, replyTo, subject, html, text, headers })); + Meteor.defer(() => Email.send({ to, from, replyTo, subject, html, text, headers })); }; export const send = ({ to, from, replyTo, subject, html, text, data, headers }) => sendNoWrap({ to, from, replyTo, subject: replace(subject, data), text: text ? replace(text, data) : stripHtml(replace(html, data)), html: wrap(html, data), headers }); From f176e96e139b6f74536dfdafa5d6567412b58f52 Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Wed, 8 Jan 2020 10:10:06 -0300 Subject: [PATCH 4/4] Update app/lib/server/startup/email.js Co-Authored-By: Diego Sampaio --- app/lib/server/startup/email.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/server/startup/email.js b/app/lib/server/startup/email.js index a132a4291f457..852618fd1a1cb 100644 --- a/app/lib/server/startup/email.js +++ b/app/lib/server/startup/email.js @@ -109,7 +109,7 @@ settings.addGroup('Email', function() { i18nDescription: 'email_style_description', enableQuery: { _id: 'email_plain_text_only', - value: true, + value: false, }, }); });