feat(mailing): send transactional message instead of campaign
This commit is contained in:
parent
7c5074098c
commit
ea28e6306d
1 changed files with 36 additions and 100 deletions
|
@ -1,10 +1,10 @@
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
|
|
||||||
// Function to handle form submission and interact with Listmonk
|
// Function to handle form submission and send transactional email via Listmonk
|
||||||
export async function submitToListmonk(req, res) {
|
export async function submitToListmonk(req, res) {
|
||||||
const { name, email, message } = req.body;
|
const { name, email, message } = req.body;
|
||||||
|
|
||||||
const listmonkUrl = process.env.LISTMONK_URL;
|
const listmonkSubscriberUrl = process.env.LISTMONK_URL;
|
||||||
const listmonkUsername = process.env.LISTMONK_USERNAME;
|
const listmonkUsername = process.env.LISTMONK_USERNAME;
|
||||||
const listmonkPassword = process.env.LISTMONK_PASSWORD;
|
const listmonkPassword = process.env.LISTMONK_PASSWORD;
|
||||||
const listmonkBaseUrl = process.env.LISTMONK_BASE_URL;
|
const listmonkBaseUrl = process.env.LISTMONK_BASE_URL;
|
||||||
|
@ -13,7 +13,7 @@ export async function submitToListmonk(req, res) {
|
||||||
// Encode username and password as base64
|
// Encode username and password as base64
|
||||||
const auth = Buffer.from(`${listmonkUsername}:${listmonkPassword}`).toString('base64');
|
const auth = Buffer.from(`${listmonkUsername}:${listmonkPassword}`).toString('base64');
|
||||||
|
|
||||||
console.log(`Sending request to Listmonk with URL: ${listmonkUrl}`);
|
console.log(`Sending request to Listmonk with URL: ${listmonkSubscriberUrl}`);
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
email,
|
email,
|
||||||
|
@ -23,7 +23,7 @@ export async function submitToListmonk(req, res) {
|
||||||
fields: { message }
|
fields: { message }
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('Sending request to Listmonk with payload:', payload);
|
console.log('Sending subscriber to Listmonk with payload:', payload);
|
||||||
|
|
||||||
async function fetchWithRetry(url, options, retries = 3) {
|
async function fetchWithRetry(url, options, retries = 3) {
|
||||||
for (let i = 0; i < retries; i++) {
|
for (let i = 0; i < retries; i++) {
|
||||||
|
@ -42,7 +42,7 @@ export async function submitToListmonk(req, res) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Add subscriber
|
// Add subscriber
|
||||||
const response = await fetchWithRetry(listmonkUrl, {
|
const response = await fetchWithRetry(listmonkSubscriberUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
|
@ -59,95 +59,31 @@ export async function submitToListmonk(req, res) {
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
console.log('Subscriber added successfully:', result);
|
console.log('Subscriber added successfully:', result);
|
||||||
|
|
||||||
// Create a new campaign for the subscriber
|
// Send transactional email
|
||||||
const createCampaign = async (subject, body) => {
|
const transactionalUrl = `${listmonkBaseUrl}/tx`;
|
||||||
const createCampaignUrl = `${listmonkBaseUrl}/campaigns`;
|
const txPayload = {
|
||||||
const campaignPayload = {
|
template_id: parseInt(process.env.PRESET_CAMPAIGN_ID, 10),
|
||||||
name: `Welcome email for ${email}`,
|
subscriber_emails: [ email ],
|
||||||
subject: subject,
|
|
||||||
from_email: "Janek <janek@melonion.me>",
|
from_email: "Janek <janek@melonion.me>",
|
||||||
body: body,
|
data: { name, message }
|
||||||
type: "regular",
|
|
||||||
to_emails: [email],
|
|
||||||
lists: [listId],
|
|
||||||
content_type: "richtext",
|
|
||||||
status: "scheduled",
|
|
||||||
schedule: new Date().toISOString()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await fetch(createCampaignUrl, {
|
const txResponse = await fetchWithRetry(transactionalUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': `Basic ${auth}`,
|
'Authorization': `Basic ${auth}`
|
||||||
},
|
},
|
||||||
body: JSON.stringify(campaignPayload),
|
body: JSON.stringify(txPayload)
|
||||||
});
|
}, 12);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!txResponse.ok) {
|
||||||
const errorBody = await response.text();
|
const errorBody = await txResponse.text();
|
||||||
throw new Error(`Listmonk API error (Create Campaign): ${response.statusText}. Response body: ${errorBody}`);
|
throw new Error(`Listmonk TX error: ${txResponse.statusText}. ${errorBody}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await response.json();
|
const dispatchResult = await txResponse.json();
|
||||||
return result.data.id;
|
console.log('tx dispatched successfully:', dispatchResult);
|
||||||
};
|
|
||||||
|
|
||||||
// Campaign subject and body content
|
|
||||||
const subject = "👋 Welcome to the Progodyssey Family!";
|
|
||||||
const body = `
|
|
||||||
<h1>👋 Welcome to the Progodyssey Family, {{ .Subscriber.Name }}!</h1>
|
|
||||||
|
|
||||||
<p>We’re thrilled to have you as part of the Progodyssey Traineeship journey! 🎉
|
|
||||||
This program is designed to equip you with the skills, experience, and network to thrive in the tech world and beyond.</p>
|
|
||||||
|
|
||||||
<p>Here’s what you can expect in the coming weeks:</p>
|
|
||||||
<ul>
|
|
||||||
<li>1️⃣ <strong>Learning Opportunities:</strong> Access to tutorials, and hands-on projects to sharpen your skills.</li>
|
|
||||||
<li>2️⃣ <strong>Mentorship:</strong> Personal Guidance to help you navigate your journey.</li>
|
|
||||||
<li>3️⃣ <strong>Community:</strong> A supportive group of peers and mentors working together towards success.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p>To kick things off, go through the Progodyssey handbook, pick a course and submit your reflection essay to <a href="mailto:reflection@progodyssey.com">reflection@progodyssey.com</a>.</p>
|
|
||||||
<p>Janek’s Blog could also have some insight for you.</p>
|
|
||||||
|
|
||||||
<p><em>Encouragement:</em><br>
|
|
||||||
<em>"Success is the sum of small efforts repeated day in and day out."</em> – <cite>Robert Collier</cite></p>
|
|
||||||
|
|
||||||
<p>Let’s take the first step together!<br>
|
|
||||||
If you have any questions or need assistance, feel free to reply to this email or contact us at <a href="mailto:hello@progodyssey.com">hello@progodyssey.com</a></p>
|
|
||||||
|
|
||||||
<p>Looking forward to seeing you thrive,<br>
|
|
||||||
<strong>The Progodyssey Team</strong></p>
|
|
||||||
`;
|
|
||||||
|
|
||||||
// 1. Create campaign
|
|
||||||
const newCampaignId = await createCampaign(subject, body);
|
|
||||||
console.log(`Created new campaign with ID: ${newCampaignId}`);
|
|
||||||
|
|
||||||
// 2. Dispatch campaign
|
|
||||||
const dispatchUrl = `${listmonkBaseUrl}/campaigns/${newCampaignId}/status`;
|
|
||||||
const dispatchPayload = {
|
|
||||||
status: 'running'
|
|
||||||
};
|
|
||||||
|
|
||||||
const dispatchResponse = await fetch(dispatchUrl, {
|
|
||||||
method: 'PUT',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': `Basic ${auth}`,
|
|
||||||
},
|
|
||||||
body: JSON.stringify(dispatchPayload),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!dispatchResponse.ok) {
|
|
||||||
const errorBody = await dispatchResponse.text();
|
|
||||||
console.error('Response from Listmonk (Dispatch):', errorBody);
|
|
||||||
throw new Error(`Listmonk API error (Dispatch Campaign): ${dispatchResponse.statusText}. Response body: ${errorBody}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const dispatchResult = await dispatchResponse.json();
|
|
||||||
console.log('Campaign dispatched successfully:', dispatchResult);
|
|
||||||
|
|
||||||
res.status(200).json({ message: 'Subscription and welcome email sent successfully!', result });
|
res.status(200).json({ message: 'Subscription and welcome email sent successfully!', result });
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue