mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-22 18:31:57 +03:00
ed6a8dca76
no issue
- following on from f4fb0fcbaa
,
this commit moves around some package requires in Ghost
- these are often niche packages that do something in a subsystem of
Ghost, and are not necessarily be needed to boot the application
- these packages use non-negligible CPU and memory when they are
required, so it makes sense to lazy-require them
- the concern here is that we obscure the code too much by moving
random requires further into code, but the changes are small and the
improvements big
- this commit bring the boot time since 4.19.0 down ~31% and initial
memory usage down by a total of ~12%
123 lines
3.8 KiB
JavaScript
123 lines
3.8 KiB
JavaScript
const _ = require('lodash');
|
|
const {URL} = require('url');
|
|
const logging = require('@tryghost/logging');
|
|
const configService = require('../../../shared/config');
|
|
const settingsCache = require('../../../shared/settings-cache');
|
|
|
|
const BATCH_SIZE = 1000;
|
|
|
|
function createMailgun(config) {
|
|
const mailgun = require('mailgun-js');
|
|
const baseUrl = new URL(config.baseUrl);
|
|
|
|
return mailgun({
|
|
apiKey: config.apiKey,
|
|
domain: config.domain,
|
|
protocol: baseUrl.protocol,
|
|
host: baseUrl.hostname,
|
|
port: baseUrl.port,
|
|
endpoint: baseUrl.pathname,
|
|
retry: 5
|
|
});
|
|
}
|
|
|
|
function getInstance() {
|
|
const bulkEmailConfig = configService.get('bulkEmail');
|
|
const bulkEmailSetting = {
|
|
apiKey: settingsCache.get('mailgun_api_key'),
|
|
domain: settingsCache.get('mailgun_domain'),
|
|
baseUrl: settingsCache.get('mailgun_base_url')
|
|
};
|
|
const hasMailgunConfig = !!(bulkEmailConfig && bulkEmailConfig.mailgun);
|
|
const hasMailgunSetting = !!(bulkEmailSetting && bulkEmailSetting.apiKey && bulkEmailSetting.baseUrl && bulkEmailSetting.domain);
|
|
|
|
if (!hasMailgunConfig && !hasMailgunSetting) {
|
|
logging.warn(`Bulk email service is not configured`);
|
|
} else {
|
|
let mailgunConfig = hasMailgunConfig ? bulkEmailConfig.mailgun : bulkEmailSetting;
|
|
return createMailgun(mailgunConfig);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
// recipientData format:
|
|
// {
|
|
// 'test@example.com': {
|
|
// name: 'Test User',
|
|
// unique_id: '12345abcde',
|
|
// unsubscribe_url: 'https://example.com/unsub/me'
|
|
// }
|
|
// }
|
|
function send(message, recipientData, replacements) {
|
|
if (recipientData.length > BATCH_SIZE) {
|
|
// err - too many recipients
|
|
}
|
|
|
|
let messageData = {};
|
|
|
|
try {
|
|
const bulkEmailConfig = configService.get('bulkEmail');
|
|
const mailgunInstance = getInstance();
|
|
|
|
const messageContent = _.pick(message, 'subject', 'html', 'plaintext');
|
|
|
|
// update content to use Mailgun variable syntax for replacements
|
|
replacements.forEach((replacement) => {
|
|
messageContent[replacement.format] = messageContent[replacement.format].replace(
|
|
replacement.match,
|
|
`%recipient.${replacement.id}%`
|
|
);
|
|
});
|
|
|
|
messageData = {
|
|
to: Object.keys(recipientData),
|
|
from: message.from,
|
|
'h:Reply-To': message.replyTo || message.reply_to,
|
|
subject: messageContent.subject,
|
|
html: messageContent.html,
|
|
text: messageContent.plaintext,
|
|
'recipient-variables': recipientData
|
|
};
|
|
|
|
// add a reference to the original email record for easier mapping of mailgun event -> email
|
|
if (message.id) {
|
|
messageData['v:email-id'] = message.id;
|
|
}
|
|
|
|
const tags = ['bulk-email'];
|
|
if (bulkEmailConfig && bulkEmailConfig.mailgun && bulkEmailConfig.mailgun.tag) {
|
|
tags.push(bulkEmailConfig.mailgun.tag);
|
|
}
|
|
messageData['o:tag'] = tags;
|
|
|
|
if (bulkEmailConfig && bulkEmailConfig.mailgun && bulkEmailConfig.mailgun.testmode) {
|
|
messageData['o:testmode'] = true;
|
|
}
|
|
|
|
// enable tracking if turned on for this email
|
|
if (message.track_opens) {
|
|
messageData['o:tracking-opens'] = true;
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
|
mailgunInstance.messages().send(messageData, (error, body) => {
|
|
if (error || !body) {
|
|
return reject(error);
|
|
}
|
|
|
|
return resolve({
|
|
id: body.id
|
|
});
|
|
});
|
|
});
|
|
} catch (error) {
|
|
return Promise.reject({error, messageData});
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
BATCH_SIZE,
|
|
getInstance,
|
|
send
|
|
};
|