The communications platform that puts data protection first.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
Rocket.Chat/app/mailer/server/api.js

116 lines
3.8 KiB

import { Meteor } from 'meteor/meteor';
import { Email } from 'meteor/email';
import { TAPi18n } from 'meteor/rocketchat:tap-i18n';
import _ from 'underscore';
import s from 'underscore.string';
import juice from 'juice';
import { settings } from '../../settings';
let contentHeader;
let contentFooter;
let body;
let Settings = {
get: () => {},
};
// define server language for email translations
// @TODO: change TAPi18n.__ function to use the server language by default
let lng = 'en';
settings.get('Language', (key, value) => {
lng = value || 'en';
});
export const replacekey = (str, key, value = '') => str.replace(new RegExp(`(\\[${ key }\\]|__${ key }__)`, 'igm'), value);
export const translate = (str) => str.replace(/\{ ?([^\} ]+)(( ([^\}]+))+)? ?\}/gmi, (match, key) => TAPi18n.__(key, { lng }));
export const replace = function replace(str, data = {}) {
if (!str) {
return '';
}
const options = {
Site_Name: Settings.get('Site_Name'),
Site_URL: Settings.get('Site_Url'),
Site_URL_Slash: Settings.get('Site_Url').replace(/\/?$/, '/'),
...data.name && {
fname: s.strLeft(data.name, ' '),
lname: s.strRightBack(data.name, ' '),
},
...data,
};
return Object.entries(options).reduce((ret, [key, value]) => replacekey(ret, key, value), translate(str));
};
export const replaceEscaped = (str, data = {}) => replace(str, {
Site_Name: s.escapeHTML(settings.get('Site_Name')),
Site_Url: s.escapeHTML(settings.get('Site_Url')),
...Object.entries(data).reduce((ret, [key, value]) => {
ret[key] = s.escapeHTML(value);
return ret;
}, {}),
});
export const wrap = (html, data = {}) => 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 = '';
Settings.get(template, (key, value) => {
html = value || '';
fn(escape ? inlinecss(html) : html);
});
Settings.get('email_style', () => {
fn(escape ? inlinecss(html) : html);
});
};
export const getTemplateWrapped = (template, fn) => {
let html = '';
const wrapInlineCSS = _.debounce(() => fn(wrap(inlinecss(html))), 100);
Settings.get('Email_Header', () => html && wrapInlineCSS());
Settings.get('Email_Footer', () => html && wrapInlineCSS());
Settings.get('email_style', () => html && wrapInlineCSS());
Settings.get(template, (key, value) => {
html = value || '';
return html && wrapInlineCSS();
});
};
export const setSettings = (s) => {
Settings = s;
getTemplate('Email_Header', (value) => {
contentHeader = replace(value || '');
body = inlinecss(`${ contentHeader } {{body}} ${ contentFooter }`);
}, false);
getTemplate('Email_Footer', (value) => {
contentFooter = replace(value || '');
body = inlinecss(`${ contentHeader } {{body}} ${ contentFooter }`);
}, false);
body = inlinecss(`${ contentHeader } {{body}} ${ contentFooter }`);
};
export const rfcMailPatternWithName = /^(?:.*<)?([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)(?:>?)$/;
export const checkAddressFormat = (from) => rfcMailPatternWithName.test(from);
export const sendNoWrap = ({ to, from, replyTo, subject, html, headers }) => {
if (!checkAddressFormat(to)) {
return;
}
Meteor.defer(() => Email.send({ to, from, replyTo, subject, html, 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 checkAddressFormatAndThrow = (from, func) => {
if (checkAddressFormat(from)) {
return true;
}
throw new Meteor.Error('error-invalid-from-address', 'Invalid from address', {
function: func,
});
};
export const getHeader = () => contentHeader;
export const getFooter = () => contentFooter;