bulk unsub on complaint and bounce

This commit is contained in:
KMKoushik
2025-03-19 23:45:40 +11:00
parent aec7bbb6f1
commit 5465e2ec74
2 changed files with 80 additions and 28 deletions

View File

@@ -112,18 +112,22 @@ export async function unsubscribeContactFromLink(id: string, hash: string) {
throw new Error("Invalid unsubscribe link");
}
return await unsubscribeContact(
return await unsubscribeContact({
contactId,
campaignId,
UnsubscribeReason.UNSUBSCRIBED
);
reason: UnsubscribeReason.UNSUBSCRIBED,
});
}
export async function unsubscribeContact(
contactId: string,
campaignId: string,
reason: UnsubscribeReason
) {
export async function unsubscribeContact({
contactId,
campaignId,
reason,
}: {
contactId: string;
campaignId?: string;
reason: UnsubscribeReason;
}) {
// Update the contact's subscription status
try {
const contact = await db.contact.findUnique({
@@ -140,14 +144,16 @@ export async function unsubscribeContact(
data: { subscribed: false, unsubscribeReason: reason },
});
await db.campaign.update({
where: { id: campaignId },
data: {
unsubscribed: {
increment: 1,
if (campaignId) {
await db.campaign.update({
where: { id: campaignId },
data: {
unsubscribed: {
increment: 1,
},
},
},
});
});
}
}
return contact;

View File

@@ -103,7 +103,12 @@ export async function parseSesHook(data: SesEvent) {
mailStatus !== "CLICKED" ||
!(mailData as SesClick).link.startsWith(`${env.NEXTAUTH_URL}/unsubscribe`)
) {
await checkUnsubscribe(email.campaignId, email.contactId!, mailStatus);
await checkUnsubscribe({
contactId: email.contactId!,
campaignId: email.campaignId,
teamId: email.teamId,
event: mailStatus,
});
const mailEvent = await db.emailEvent.findFirst({
where: {
@@ -129,19 +134,60 @@ export async function parseSesHook(data: SesEvent) {
return true;
}
function checkUnsubscribe(
campaignId: string,
contactId: string,
event: EmailStatus
) {
async function checkUnsubscribe({
contactId,
campaignId,
teamId,
event,
}: {
contactId: string;
campaignId: string;
teamId: number;
event: EmailStatus;
}) {
if (event === EmailStatus.BOUNCED || event === EmailStatus.COMPLAINED) {
return unsubscribeContact(
contactId,
campaignId,
event === EmailStatus.BOUNCED
? UnsubscribeReason.BOUNCED
: UnsubscribeReason.COMPLAINED
);
const contact = await db.contact.findUnique({
where: {
id: contactId,
},
});
if (!contact) {
return;
}
const allContacts = await db.contact.findMany({
where: {
email: contact.email,
contactBook: {
teamId,
},
},
});
const allContactIds = allContacts
.map((c) => c.id)
.filter((c) => c !== contactId);
await Promise.all([
unsubscribeContact({
contactId,
campaignId,
reason:
event === EmailStatus.BOUNCED
? UnsubscribeReason.BOUNCED
: UnsubscribeReason.COMPLAINED,
}),
...allContactIds.map((c) =>
unsubscribeContact({
contactId: c,
reason:
event === EmailStatus.BOUNCED
? UnsubscribeReason.BOUNCED
: UnsubscribeReason.COMPLAINED,
})
),
]);
}
}