Send test functionality for templates and campaigns
This commit is contained in:
parent
7e52000219
commit
2c73c536b7
22 changed files with 719 additions and 69 deletions
|
@ -26,6 +26,126 @@ class CampaignSender {
|
|||
constructor() {
|
||||
}
|
||||
|
||||
static async testSend(context, listCid, subscriptionCid, campaignId, sendConfigurationId, html, text) {
|
||||
let sendConfiguration, list, fieldsGrouped, campaign, subscriptionGrouped, useVerp, useVerpSenderHeader, mergeTags, attachments;
|
||||
|
||||
await knex.transaction(async tx => {
|
||||
sendConfiguration = await sendConfigurations.getByIdTx(tx, context, sendConfigurationId, false, true);
|
||||
list = await lists.getByCidTx(tx, context, listCid);
|
||||
fieldsGrouped = await fields.listGroupedTx(tx, list.id);
|
||||
|
||||
useVerp = config.verp.enabled && sendConfiguration.verp_hostname;
|
||||
useVerpSenderHeader = this.useVerp && config.verp.disablesenderheader !== true;
|
||||
|
||||
subscriptionGrouped = await subscriptions.getByCid(context, list.id, subscriptionCid);
|
||||
mergeTags = fields.getMergeTags(fieldsGrouped, subscriptionGrouped);
|
||||
|
||||
if (campaignId) {
|
||||
campaign = await campaigns.getByIdTx(tx, context, campaignId, false, campaigns.Content.WITHOUT_SOURCE_CUSTOM);
|
||||
} else {
|
||||
// This is to fake the campaign for getMessageLinks, which is called inside formatMessage
|
||||
campaign = {
|
||||
cid: '[CAMPAIGN_ID]'
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const encryptionKeys = [];
|
||||
for (const fld of fieldsGrouped) {
|
||||
if (fld.type === 'gpg' && mergeTags[fld.key]) {
|
||||
encryptionKeys.push(mergeTags[fld.key].trim());
|
||||
}
|
||||
}
|
||||
|
||||
attachments = [];
|
||||
// replace data: images with embedded attachments
|
||||
html = html.replace(/(<img\b[^>]* src\s*=[\s"']*)(data:[^"'>\s]+)/gi, (match, prefix, dataUri) => {
|
||||
const cid = shortid.generate() + '-attachments';
|
||||
attachments.push({
|
||||
path: dataUri,
|
||||
cid
|
||||
});
|
||||
return prefix + 'cid:' + cid;
|
||||
});
|
||||
|
||||
html = tools.formatMessage(campaign, list, subscriptionGrouped, mergeTags, html, false, true);
|
||||
|
||||
text = (text || '').trim()
|
||||
? tools.formatMessage(campaign, list, subscriptionGrouped, mergeTags, text)
|
||||
: htmlToText.fromString(html, {wordwrap: 130});
|
||||
|
||||
|
||||
const mailer = await mailers.getOrCreateMailer(sendConfiguration.id);
|
||||
|
||||
const getOverridable = key => {
|
||||
return sendConfiguration[key];
|
||||
}
|
||||
|
||||
const campaignAddress = [campaign.cid, list.cid, subscriptionGrouped.cid].join('.');
|
||||
|
||||
const mail = {
|
||||
from: {
|
||||
name: getOverridable('from_name'),
|
||||
address: getOverridable('from_email')
|
||||
},
|
||||
replyTo: getOverridable('reply_to'),
|
||||
xMailer: sendConfiguration.x_mailer ? sendConfiguration.x_mailer : false,
|
||||
to: {
|
||||
name: tools.formatMessage(campaign, list, subscriptionGrouped, mergeTags, list.to_name, false, false),
|
||||
address: subscriptionGrouped.email
|
||||
},
|
||||
sender: this.useVerpSenderHeader ? campaignAddress + '@' + sendConfiguration.verp_hostname : false,
|
||||
|
||||
envelope: this.useVerp ? {
|
||||
from: campaignAddress + '@' + sendConfiguration.verp_hostname,
|
||||
to: subscriptionGrouped.email
|
||||
} : false,
|
||||
|
||||
headers: {
|
||||
'x-fbl': campaignAddress,
|
||||
// custom header for SparkPost
|
||||
'x-msys-api': JSON.stringify({
|
||||
campaign_id: campaignAddress
|
||||
}),
|
||||
// custom header for SendGrid
|
||||
'x-smtpapi': JSON.stringify({
|
||||
unique_args: {
|
||||
campaign_id: campaignAddress
|
||||
}
|
||||
}),
|
||||
// custom header for Mailgun
|
||||
'x-mailgun-variables': JSON.stringify({
|
||||
campaign_id: campaignAddress
|
||||
}),
|
||||
'List-ID': {
|
||||
prepared: true,
|
||||
value: libmime.encodeWords(list.name) + ' <' + list.cid + '.' + getPublicUrl() + '>'
|
||||
}
|
||||
},
|
||||
list: {
|
||||
unsubscribe: null
|
||||
},
|
||||
subject: tools.formatMessage(campaign, list, subscriptionGrouped, mergeTags, getOverridable('subject'), false, false),
|
||||
html,
|
||||
text,
|
||||
|
||||
attachments,
|
||||
encryptionKeys
|
||||
};
|
||||
|
||||
|
||||
let response;
|
||||
try {
|
||||
const info = await mailer.sendMassMail(mail);
|
||||
response = info.response || info.messageId;
|
||||
} catch (err) {
|
||||
response = err.response || err.message;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
async init(settings) {
|
||||
this.listsById = new Map(); // listId -> list
|
||||
this.listsByCid = new Map(); // listCid -> list
|
||||
|
@ -51,14 +171,14 @@ class CampaignSender {
|
|||
}
|
||||
|
||||
if (campaign.source === CampaignSource.TEMPLATE) {
|
||||
this.template = await templates.getByIdTx(tx, contextHelpers.getAdminContext(), this.campaign.data.sourceTemplate, false);
|
||||
this.template = await templates.getByIdTx(tx, contextHelpers.getAdminContext(), campaign.data.sourceTemplate, false);
|
||||
}
|
||||
|
||||
const attachments = await files.listTx(tx, contextHelpers.getAdminContext(), 'campaign', 'attachment', this.campaign.id);
|
||||
const attachments = await files.listTx(tx, contextHelpers.getAdminContext(), 'campaign', 'attachment', campaign.id);
|
||||
for (const attachment of attachments) {
|
||||
this.attachments.push({
|
||||
filename: attachment.originalname,
|
||||
path: files.getFilePath('campaign', 'attachment', this.campaign.id, attachment.filename)
|
||||
path: files.getFilePath('campaign', 'attachment', campaign.id, attachment.filename)
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -111,7 +231,7 @@ class CampaignSender {
|
|||
if (replaceDataImgs) {
|
||||
// replace data: images with embedded attachments
|
||||
html = html.replace(/(<img\b[^>]* src\s*=[\s"']*)(data:[^"'>\s]+)/gi, (match, prefix, dataUri) => {
|
||||
const cid = shortid.generate() + '-attachments@' + campaign.address.split('@').pop();
|
||||
const cid = shortid.generate() + '-attachments';
|
||||
attachments.push({
|
||||
path: dataUri,
|
||||
cid
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue