Implemented basic transactional emails API
This commit is contained in:
parent
913c7dc337
commit
4a521a8f0f
4 changed files with 107 additions and 1 deletions
|
@ -348,7 +348,7 @@ function createApp(appType) {
|
||||||
data: []
|
data: []
|
||||||
};
|
};
|
||||||
|
|
||||||
return status(err.status || 500).json(resp);
|
return res.status(err.status || 500).json(resp);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (err instanceof interoperableErrors.NotLoggedInError) {
|
if (err instanceof interoperableErrors.NotLoggedInError) {
|
||||||
|
|
|
@ -8,6 +8,10 @@ const fs = require('fs-extra-promise');
|
||||||
const tryRequire = require('try-require');
|
const tryRequire = require('try-require');
|
||||||
const posix = tryRequire('posix');
|
const posix = tryRequire('posix');
|
||||||
|
|
||||||
|
// process.getuid and process.getgid are not supported on Windows
|
||||||
|
process.getuid = process.getuid || (() => 100);
|
||||||
|
process.getgid = process.getuid || (() => 100);
|
||||||
|
|
||||||
function _getConfigUidGid(userKey, groupKey, defaultUid, defaultGid) {
|
function _getConfigUidGid(userKey, groupKey, defaultUid, defaultGid) {
|
||||||
let uid = defaultUid;
|
let uid = defaultUid;
|
||||||
let gid = defaultGid;
|
let gid = defaultGid;
|
||||||
|
|
75
server/lib/template-sender.js
Normal file
75
server/lib/template-sender.js
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const contextHelpers = require('./context-helpers');
|
||||||
|
const mailers = require('./mailers');
|
||||||
|
const templates = require('../models/templates');
|
||||||
|
|
||||||
|
class TemplateSender {
|
||||||
|
constructor({ templateId, maxMails = 100 } = {}) {
|
||||||
|
if (!templateId) {
|
||||||
|
throw new Error('Cannot create template sender without templateId');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.templateId = templateId;
|
||||||
|
this.maxMails = maxMails;
|
||||||
|
}
|
||||||
|
|
||||||
|
async send(options) {
|
||||||
|
this._validateMailOptions(options);
|
||||||
|
|
||||||
|
const [mailer, template] = await Promise.all([
|
||||||
|
mailers.getOrCreateMailer(),
|
||||||
|
templates.getById(
|
||||||
|
contextHelpers.getAdminContext(),
|
||||||
|
this.templateId,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
|
||||||
|
const html = this._substituteVariables(
|
||||||
|
template.html,
|
||||||
|
options.variables
|
||||||
|
);
|
||||||
|
return mailer.sendTransactionalMail(
|
||||||
|
{
|
||||||
|
to: options.email,
|
||||||
|
subject: options.subject
|
||||||
|
},
|
||||||
|
{
|
||||||
|
html: { template: html },
|
||||||
|
locale: options.locale
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_validateMailOptions(options) {
|
||||||
|
let { email, locale } = options;
|
||||||
|
|
||||||
|
if (!email || email.length === 0) {
|
||||||
|
throw new Error('Missing email');
|
||||||
|
}
|
||||||
|
if (typeof email === 'string') {
|
||||||
|
email = email.split(',');
|
||||||
|
}
|
||||||
|
if (email.length > this.maxMails) {
|
||||||
|
throw new Error(
|
||||||
|
`Cannot send more than ${this.maxMails} emails at once`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!locale) {
|
||||||
|
throw new Error('Missing locale');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_substituteVariables(html, variables) {
|
||||||
|
if (!variables) return html;
|
||||||
|
return Object.keys(variables).reduce((res, key) => {
|
||||||
|
return res.replace(
|
||||||
|
new RegExp(`\\[${key}\\]`, 'gmi'),
|
||||||
|
variables[key]
|
||||||
|
);
|
||||||
|
}, html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = TemplateSender;
|
|
@ -16,6 +16,7 @@ const contextHelpers = require('../lib/context-helpers');
|
||||||
const shares = require('../models/shares');
|
const shares = require('../models/shares');
|
||||||
const slugify = require('slugify');
|
const slugify = require('slugify');
|
||||||
const passport = require('../lib/passport');
|
const passport = require('../lib/passport');
|
||||||
|
const TemplateSender = require('../lib/template-sender');
|
||||||
const campaigns = require('../models/campaigns');
|
const campaigns = require('../models/campaigns');
|
||||||
|
|
||||||
class APIError extends Error {
|
class APIError extends Error {
|
||||||
|
@ -285,5 +286,31 @@ router.getAsync('/rss/fetch/:campaignCid', passport.loggedIn, async (req, res) =
|
||||||
return res.json();
|
return res.json();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.postAsync('/templates/:templateId/send', async (req, res) => {
|
||||||
|
const input = {};
|
||||||
|
Object.keys(req.body).forEach(key => {
|
||||||
|
input[
|
||||||
|
(key || '')
|
||||||
|
.toString()
|
||||||
|
.trim()
|
||||||
|
.toUpperCase()
|
||||||
|
] = req.body[key] || '';
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const templateSender = new TemplateSender({
|
||||||
|
templateId: req.params.templateId
|
||||||
|
});
|
||||||
|
const info = await templateSender.send({
|
||||||
|
email: input.EMAIL,
|
||||||
|
subject: input.SUBJECT,
|
||||||
|
locale: req.locale,
|
||||||
|
variables: input.VARIABLES
|
||||||
|
});
|
||||||
|
res.status(200).json({ data: info });
|
||||||
|
} catch (e) {
|
||||||
|
throw new APIError(e.message, 400);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue