mirror of
https://github.com/wassname/talk.git
synced 2026-06-30 03:13:58 +08:00
149 lines
3.5 KiB
JavaScript
149 lines
3.5 KiB
JavaScript
const debug = require('debug')('talk:services:mailer');
|
|
const nodemailer = require('nodemailer');
|
|
const kue = require('./kue');
|
|
const i18n = require('./i18n');
|
|
const path = require('path');
|
|
const fs = require('fs-extra');
|
|
const _ = require('lodash');
|
|
const { TEMPLATE_LOCALS } = require('../middleware/staticTemplate');
|
|
|
|
const {
|
|
SMTP_HOST,
|
|
SMTP_USERNAME,
|
|
SMTP_PORT,
|
|
SMTP_PASSWORD,
|
|
SMTP_FROM_ADDRESS,
|
|
EMAIL_SUBJECT_PREFIX,
|
|
} = require('../config');
|
|
|
|
// load all the templates as strings
|
|
const templates = {
|
|
data: {},
|
|
};
|
|
|
|
// load the templates per request during development
|
|
templates.render = async (name, format = 'txt', context) => {
|
|
if (process.env.NODE_ENV === 'production') {
|
|
// If we are in production mode, check the view cache.
|
|
const view = _.get(templates.data, [name, format], null);
|
|
if (view !== null) {
|
|
return view(context);
|
|
}
|
|
}
|
|
|
|
const filename = path.join(
|
|
__dirname,
|
|
'email',
|
|
[name, format, 'ejs'].join('.')
|
|
);
|
|
const file = await fs.readFile(filename, 'utf8');
|
|
const view = _.template(file);
|
|
|
|
if (process.env.NODE_ENV === 'production') {
|
|
// If we are in production mode, fill the view cache.
|
|
_.set(templates.data, [name, format], view);
|
|
}
|
|
|
|
return view(context);
|
|
};
|
|
|
|
const mailer = {};
|
|
|
|
// enabled is true when the required configuration is available. When testing
|
|
// is enabled, we will be simulating that emails are being sent, because in a
|
|
// production system, emails should and would be sent.
|
|
mailer.enabled =
|
|
Boolean(SMTP_HOST && SMTP_USERNAME && SMTP_PASSWORD && SMTP_FROM_ADDRESS) ||
|
|
process.env.NODE_ENV === 'test';
|
|
|
|
if (mailer.enabled) {
|
|
const options = {
|
|
host: SMTP_HOST,
|
|
auth: {
|
|
user: SMTP_USERNAME,
|
|
pass: SMTP_PASSWORD,
|
|
},
|
|
};
|
|
|
|
if (SMTP_PORT) {
|
|
try {
|
|
options.port = parseInt(SMTP_PORT);
|
|
} catch (e) {
|
|
throw new Error('TALK_SMTP_PORT is not an integer');
|
|
}
|
|
} else {
|
|
options.port = 25;
|
|
}
|
|
|
|
mailer.transport = nodemailer.createTransport(options);
|
|
}
|
|
|
|
/**
|
|
* Create the new Task kue.
|
|
*/
|
|
mailer.task = new kue.Task({
|
|
name: 'mailer',
|
|
});
|
|
|
|
/**
|
|
* send will create a new message and send it.
|
|
*/
|
|
mailer.send = async options => {
|
|
if (!mailer.enabled) {
|
|
const err = new Error(
|
|
'sending email is not enabled because required configuration is not available'
|
|
);
|
|
console.warn(err);
|
|
return;
|
|
}
|
|
|
|
// Create the new locals object and attach the static locals and the i18n
|
|
// framework.
|
|
const locals = _.merge({}, options.locals, TEMPLATE_LOCALS, { t: i18n.t });
|
|
|
|
// Render the templates.
|
|
const [html, text] = await Promise.all(
|
|
['html', 'txt'].map(fmt => {
|
|
return templates.render(options.template, fmt, locals);
|
|
})
|
|
);
|
|
|
|
// Create the job to send the email later.
|
|
return mailer.task.create({
|
|
title: 'Mail',
|
|
message: {
|
|
to: options.to,
|
|
subject: `${EMAIL_SUBJECT_PREFIX} ${options.subject}`,
|
|
text,
|
|
html,
|
|
},
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Start the queue processor for the mailer job.
|
|
*/
|
|
mailer.process = () => {
|
|
debug(`Now processing ${mailer.task.name} jobs`);
|
|
|
|
return mailer.task.process(({ id, data }, done) => {
|
|
debug(`Starting to send mail for Job[${id}]`);
|
|
|
|
// Set the `from` field.
|
|
data.message.from = SMTP_FROM_ADDRESS;
|
|
|
|
// Actually send the email.
|
|
mailer.transport.sendMail(data.message, err => {
|
|
if (err) {
|
|
debug(`Failed to send mail for Job[${id}]:`, err);
|
|
return done(err);
|
|
}
|
|
|
|
debug(`Finished sending mail for Job[${id}]`);
|
|
return done();
|
|
});
|
|
});
|
|
};
|
|
|
|
module.exports = mailer;
|