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"); throw new Error("Invalid unsubscribe link");
} }
return await unsubscribeContact( return await unsubscribeContact({
contactId, contactId,
campaignId, campaignId,
UnsubscribeReason.UNSUBSCRIBED reason: UnsubscribeReason.UNSUBSCRIBED,
); });
} }
export async function unsubscribeContact( export async function unsubscribeContact({
contactId: string, contactId,
campaignId: string, campaignId,
reason: UnsubscribeReason reason,
) { }: {
contactId: string;
campaignId?: string;
reason: UnsubscribeReason;
}) {
// Update the contact's subscription status // Update the contact's subscription status
try { try {
const contact = await db.contact.findUnique({ const contact = await db.contact.findUnique({
@@ -140,6 +144,7 @@ export async function unsubscribeContact(
data: { subscribed: false, unsubscribeReason: reason }, data: { subscribed: false, unsubscribeReason: reason },
}); });
if (campaignId) {
await db.campaign.update({ await db.campaign.update({
where: { id: campaignId }, where: { id: campaignId },
data: { data: {
@@ -149,6 +154,7 @@ export async function unsubscribeContact(
}, },
}); });
} }
}
return contact; return contact;
} catch (error) { } catch (error) {

View File

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