feat(listmonk): schedule weekly transactional emails
This commit is contained in:
parent
c1bd2aa9b8
commit
ffae0780e9
2 changed files with 73 additions and 19 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
.env
|
||||
node_modules/
|
||||
.qodo
|
||||
|
|
|
@ -10,6 +10,12 @@ export async function submitToListmonk(req, res) {
|
|||
const listmonkBaseUrl = process.env.LISTMONK_BASE_URL;
|
||||
const listId = parseInt(process.env.LIST_ID, 10);
|
||||
|
||||
const welcomeTemplateId = parseInt(process.env.PRESET_CAMPAIGN_ID, 10);
|
||||
const week1TemplateId = parseInt(process.env.TEMPLATE_ID_WEEK_1, 10);
|
||||
const week2TemplateId = parseInt(process.env.TEMPLATE_ID_WEEK_2, 10);
|
||||
const week3TemplateId = parseInt(process.env.TEMPLATE_ID_WEEK_3, 10);
|
||||
const week4TemplateId = parseInt(process.env.TEMPLATE_ID_WEEK_4, 10);
|
||||
|
||||
// Encode username and password as base64
|
||||
const auth = Buffer.from(`${listmonkUsername}:${listmonkPassword}`).toString('base64');
|
||||
|
||||
|
@ -40,6 +46,50 @@ export async function submitToListmonk(req, res) {
|
|||
}
|
||||
}
|
||||
|
||||
async function scheduleTransactionalEmails(email, name, message, auth, baseUrl) {
|
||||
const MAX_TIMEOUT_MS = 2147483647;
|
||||
|
||||
const SCHEDULES = [
|
||||
{ delayMs: 7 * 24 * 60 * 60 * 1000, templateId: week1TemplateId }, // 1 week
|
||||
{ delayMs: 14 * 24 * 60 * 60 * 1000, templateId: week2TemplateId }, // 2 weeks
|
||||
{ delayMs: 21 * 24 * 60 * 60 * 1000, templateId: week3TemplateId }, // 3 weeks
|
||||
{
|
||||
delayMs: Math.min(28 * 24 * 60 * 60 * 1000, MAX_TIMEOUT_MS), // 4 weeks (capped)
|
||||
templateId: week4TemplateId
|
||||
}
|
||||
];
|
||||
|
||||
for (const { delayMs, templateId } of SCHEDULES) {
|
||||
setTimeout(async () => {
|
||||
const payload = {
|
||||
template_id: templateId,
|
||||
subscriber_emails: [email],
|
||||
from_email: "Janek <janek@melonion.me>",
|
||||
data: { name, message }
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await fetch(`${baseUrl}/tx`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Basic ${auth}`
|
||||
},
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
console.error(`Error sending email with template ${templateId}:`, await res.text());
|
||||
} else {
|
||||
console.log(`Email sent with template ${templateId}`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`Error dispatching scheduled email for template ${templateId}:`, err);
|
||||
}
|
||||
}, delayMs);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Add subscriber
|
||||
const response = await fetchWithRetry(listmonkSubscriberUrl, {
|
||||
|
@ -49,7 +99,7 @@ export async function submitToListmonk(req, res) {
|
|||
'Authorization': `Basic ${auth}`
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
},12);
|
||||
}, 12);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorBody = await response.text();
|
||||
|
@ -59,33 +109,36 @@ export async function submitToListmonk(req, res) {
|
|||
const result = await response.json();
|
||||
console.log('Subscriber added successfully:', result);
|
||||
|
||||
// Send transactional email
|
||||
// Send welcome message immediately
|
||||
const transactionalUrl = `${listmonkBaseUrl}/tx`;
|
||||
const txPayload = {
|
||||
template_id: parseInt(process.env.PRESET_CAMPAIGN_ID, 10),
|
||||
subscriber_emails: [ email ],
|
||||
from_email: "Janek <janek@melonion.me>",
|
||||
data: { name, message }
|
||||
template_id: welcomeTemplateId,
|
||||
subscriber_emails: [email],
|
||||
from_email: "Janek <janek@melonion.me>",
|
||||
data: { name, message }
|
||||
};
|
||||
|
||||
const txResponse = await fetchWithRetry(transactionalUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Basic ${auth}`
|
||||
},
|
||||
body: JSON.stringify(txPayload)
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Basic ${auth}`
|
||||
},
|
||||
body: JSON.stringify(txPayload)
|
||||
}, 12);
|
||||
|
||||
if (!txResponse.ok) {
|
||||
const errorBody = await txResponse.text();
|
||||
throw new Error(`Listmonk TX error: ${txResponse.statusText}. ${errorBody}`);
|
||||
const errorBody = await txResponse.text();
|
||||
throw new Error(`Listmonk TX error: ${txResponse.statusText}. ${errorBody}`);
|
||||
}
|
||||
|
||||
const dispatchResult = await txResponse.json();
|
||||
console.log('tx dispatched successfully:', dispatchResult);
|
||||
console.log('Welcome email dispatched successfully:', dispatchResult);
|
||||
|
||||
res.status(200).json({ message: 'Subscription and welcome email sent successfully!', result });
|
||||
// Schedule the remaining follow-up emails
|
||||
await scheduleTransactionalEmails(email, name, message, auth, listmonkBaseUrl);
|
||||
|
||||
res.status(200).json({ message: 'Subscription and emails scheduled successfully!', result });
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error submitting to Listmonk:', error);
|
||||
|
|
Loading…
Add table
Reference in a new issue