Work in progress on refactoring all mail sending to use the message sender an sender workers. No yet finished.

This commit is contained in:
Tomas Bures 2019-06-29 23:19:56 +02:00
parent 355e03900a
commit 4e9f6bd57b
22 changed files with 811 additions and 444 deletions

View file

@ -3,8 +3,6 @@
const log = require('./log');
const config = require('config');
const Handlebars = require('handlebars');
const util = require('util');
const nodemailer = require('nodemailer');
const aws = require('aws-sdk');
const openpgpEncrypt = require('nodemailer-openpgp').openpgpEncrypt;
@ -14,13 +12,21 @@ const builtinZoneMta = require('./builtin-zone-mta');
const contextHelpers = require('./context-helpers');
const settings = require('../models/settings');
const tools = require('./tools');
const htmlToText = require('html-to-text');
const bluebird = require('bluebird');
const transports = new Map();
class SendConfigurationError extends Error {
constructor(sendConfigurationId, ...args) {
super(...args);
this.sendConfigurationId = sendConfigurationId;
Error.captureStackTrace(this, SendConfigurationError);
}
}
async function getOrCreateMailer(sendConfigurationId) {
let sendConfiguration;
@ -73,25 +79,18 @@ function _addDkimKeys(transport, mail) {
async function _sendMail(transport, mail, template) {
_addDkimKeys(transport, mail);
let tryCount = 0;
const trySend = (callback) => {
tryCount++;
transport.sendMail(mail, (err, info) => {
if (err) {
log.error('Mail', err);
if (err.responseCode && err.responseCode >= 400 && err.responseCode < 500 && tryCount <= 5) {
// temporary error, try again
log.verbose('Mail', 'Retrying after %s sec. ...', tryCount);
return setTimeout(trySend, tryCount * 1000);
}
return callback(err);
}
return callback(null, info);
});
};
try {
return await transport.sendMailAsync(mail);
const trySendAsync = bluebird.promisify(trySend);
return await trySendAsync();
} catch (err) {
if ( (err.responseCode && err.responseCode >= 400 && err.responseCode < 500) ||
(err.code === 'ECONNECTION' && err.errno === 'ECONNREFUSED')
) {
throw new SendConfigurationError(transport.mailer.sendConfiguration.id, 'Cannot connect to service specified by send configuration ' + transport.mailer.sendConfiguration.id);
}
throw err;
}
}
async function _sendTransactionalMail(transport, mail) {
@ -103,39 +102,6 @@ async function _sendTransactionalMail(transport, mail) {
return await _sendMail(transport, mail);
}
async function _sendTransactionalMailBasedOnTemplate(transport, mail, template) {
const sendConfiguration = transport.mailer.sendConfiguration;
mail.from = {
name: sendConfiguration.from_name,
address: sendConfiguration.from_email
};
const htmlRenderer = await tools.getTemplate(template.html, template.locale);
if (htmlRenderer) {
mail.html = htmlRenderer(template.data || {});
}
const preparedHtml = await tools.prepareHtml(mail.html);
if (preparedHtml) {
mail.html = preparedHtml;
}
const textRenderer = await tools.getTemplate(template.text, template.locale);
if (textRenderer) {
mail.text = textRenderer(template.data || {});
} else if (mail.html) {
mail.text = htmlToText.fromString(mail.html, {
wordwrap: 130
});
}
return await _sendTransactionalMail(transport, mail);
}
async function _createTransport(sendConfiguration) {
const mailerSettings = sendConfiguration.mailer_settings;
const mailerType = sendConfiguration.mailer_type;
@ -222,6 +188,7 @@ async function _createTransport(sendConfiguration) {
}
const transport = nodemailer.createTransport(transportOptions, config.nodemailer);
transport.sendMailAsync = bluebird.promisify(transport.sendMail.bind(transport));
transport.use('stream', openpgpEncrypt({
signingKey: configItems.pgpPrivateKey,
@ -267,8 +234,7 @@ async function _createTransport(sendConfiguration) {
transport.mailer = {
sendConfiguration,
throttleWait: bluebird.promisify(throttleWait),
sendTransactionalMail: async (mail, template) => await _sendTransactionalMail(transport, mail),
sendTransactionalMailBasedOnTemplate: async (mail, template) => await _sendTransactionalMailBasedOnTemplate(transport, mail, template),
sendTransactionalMail: async (mail) => await _sendTransactionalMail(transport, mail),
sendMassMail: async (mail, template) => await _sendMail(transport, mail)
};
@ -286,3 +252,4 @@ class MailerError extends Error {
module.exports.getOrCreateMailer = getOrCreateMailer;
module.exports.invalidateMailer = invalidateMailer;
module.exports.MailerError = MailerError;
module.exports.SendConfigurationError = SendConfigurationError;