From ffae0780e984ad93ff7f84e9f4eddbfbf0f46a78 Mon Sep 17 00:00:00 2001 From: ryan Date: Thu, 1 May 2025 01:01:22 +0300 Subject: [PATCH] feat(listmonk): schedule weekly transactional emails --- .gitignore | 3 +- src/formHandler.js | 89 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 73 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 13dfa36..2596ec5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .env -node_modules/ \ No newline at end of file +node_modules/ +.qodo diff --git a/src/formHandler.js b/src/formHandler.js index 1eb940a..b33a7b9 100644 --- a/src/formHandler.js +++ b/src/formHandler.js @@ -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 ", + 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 ", - data: { name, message } + template_id: welcomeTemplateId, + subscriber_emails: [email], + from_email: "Janek ", + 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);