feat: enable List-Unsubscribe
headers in campaign emails (#96)
* feat: add `precendence: bulk` header for campaign emails * feat: create and pass unsubUrl to to email queue for campaign * fix: add correct `List-Unsubscribe-Post` header value
This commit is contained in:
@@ -114,6 +114,7 @@ export async function sendEmailThroughSes({
|
|||||||
region,
|
region,
|
||||||
configurationSetName,
|
configurationSetName,
|
||||||
unsubUrl,
|
unsubUrl,
|
||||||
|
isBulk,
|
||||||
}: Partial<EmailContent> & {
|
}: Partial<EmailContent> & {
|
||||||
region: string;
|
region: string;
|
||||||
configurationSetName: string;
|
configurationSetName: string;
|
||||||
@@ -121,6 +122,7 @@ export async function sendEmailThroughSes({
|
|||||||
bcc?: string[];
|
bcc?: string[];
|
||||||
replyTo?: string[];
|
replyTo?: string[];
|
||||||
to?: string[];
|
to?: string[];
|
||||||
|
isBulk?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const sesClient = getSesClient(region);
|
const sesClient = getSesClient(region);
|
||||||
const command = new SendEmailCommand({
|
const command = new SendEmailCommand({
|
||||||
@@ -155,14 +157,21 @@ export async function sendEmailThroughSes({
|
|||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
},
|
},
|
||||||
...(unsubUrl
|
|
||||||
? {
|
|
||||||
Headers: [
|
Headers: [
|
||||||
|
// Spread in any unsubscribe headers if unsubUrl is defined
|
||||||
|
...(unsubUrl
|
||||||
|
? [
|
||||||
{ Name: "List-Unsubscribe", Value: `<${unsubUrl}>` },
|
{ Name: "List-Unsubscribe", Value: `<${unsubUrl}>` },
|
||||||
{ Name: "List-Unsubscribe-Post", Value: "One-Click" },
|
{ Name: "List-Unsubscribe-Post", Value: "List-Unsubscribe=One-Click" },
|
||||||
|
]
|
||||||
|
: []
|
||||||
|
),
|
||||||
|
// Spread in the precedence header if present
|
||||||
|
...(isBulk
|
||||||
|
? [{ Name: "Precedence", Value: "bulk" }]
|
||||||
|
: []
|
||||||
|
),
|
||||||
],
|
],
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ConfigurationSetName: configurationSetName,
|
ConfigurationSetName: configurationSetName,
|
||||||
|
@@ -270,9 +270,10 @@ export async function sendCampaignEmail(
|
|||||||
|
|
||||||
// Queue emails
|
// Queue emails
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
emails.map((email) =>
|
emails.map((email) => {
|
||||||
EmailQueueService.queueEmail(email.id, domain.region, false)
|
const unsubscribeUrl = createUnsubUrl(email.contactId, campaignId);
|
||||||
)
|
EmailQueueService.queueEmail(email.id, domain.region, false, unsubscribeUrl);
|
||||||
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -100,12 +100,13 @@ export class EmailQueueService {
|
|||||||
const queue = transactional
|
const queue = transactional
|
||||||
? this.transactionalQueue.get(region)
|
? this.transactionalQueue.get(region)
|
||||||
: this.marketingQueue.get(region);
|
: this.marketingQueue.get(region);
|
||||||
|
const isBulk = !transactional;
|
||||||
if (!queue) {
|
if (!queue) {
|
||||||
throw new Error(`Queue for region ${region} not found`);
|
throw new Error(`Queue for region ${region} not found`);
|
||||||
}
|
}
|
||||||
queue.add(
|
queue.add(
|
||||||
emailId,
|
emailId,
|
||||||
{ emailId, timestamp: Date.now(), unsubUrl },
|
{ emailId, timestamp: Date.now(), unsubUrl, isBulk },
|
||||||
{ jobId: emailId, delay }
|
{ jobId: emailId, delay }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -169,7 +170,12 @@ export class EmailQueueService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function executeEmail(
|
async function executeEmail(
|
||||||
job: Job<{ emailId: string; timestamp: number; unsubUrl?: string }>
|
job: Job<{
|
||||||
|
emailId: string;
|
||||||
|
timestamp: number;
|
||||||
|
unsubUrl?: string;
|
||||||
|
isBulk?: boolean;
|
||||||
|
}>
|
||||||
) {
|
) {
|
||||||
console.log(
|
console.log(
|
||||||
`[EmailQueueService]: Executing email job ${job.data.emailId}, time elapsed: ${Date.now() - job.data.timestamp}ms`
|
`[EmailQueueService]: Executing email job ${job.data.emailId}, time elapsed: ${Date.now() - job.data.timestamp}ms`
|
||||||
@@ -207,6 +213,7 @@ async function executeEmail(
|
|||||||
|
|
||||||
console.log(`[EmailQueueService]: Sending email ${email.id}`);
|
console.log(`[EmailQueueService]: Sending email ${email.id}`);
|
||||||
const unsubUrl = job.data.unsubUrl;
|
const unsubUrl = job.data.unsubUrl;
|
||||||
|
const isBulk = job.data.isBulk;
|
||||||
|
|
||||||
const text = email.text
|
const text = email.text
|
||||||
? email.text
|
? email.text
|
||||||
@@ -240,6 +247,7 @@ async function executeEmail(
|
|||||||
configurationSetName,
|
configurationSetName,
|
||||||
attachments,
|
attachments,
|
||||||
unsubUrl,
|
unsubUrl,
|
||||||
|
isBulk,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Delete attachments after sending the email
|
// Delete attachments after sending the email
|
||||||
|
Reference in New Issue
Block a user