only unsub contacts on permanent bounces (#156)

* only unsub on permanent counces

* add hard bounce to email usage

* add hard bounce for campaign

* fix
This commit is contained in:
KM Koushik
2025-04-26 09:05:54 +10:00
committed by GitHub
parent 759e438863
commit 6dc6b4d213
5 changed files with 57 additions and 16 deletions

View File

@@ -334,7 +334,8 @@ export async function sendCampaignEmail(
export async function updateCampaignAnalytics(
campaignId: string,
emailStatus: EmailStatus
emailStatus: EmailStatus,
hardBounce: boolean = false
) {
const campaign = await db.campaign.findUnique({
where: { id: campaignId },
@@ -361,6 +362,9 @@ export async function updateCampaignAnalytics(
break;
case EmailStatus.BOUNCED:
updateData.bounced = { increment: 1 };
if (hardBounce) {
updateData.hardBounced = { increment: 1 };
}
break;
case EmailStatus.COMPLAINED:
updateData.complained = { increment: 1 };

View File

@@ -1,5 +1,10 @@
import { EmailStatus, Prisma, UnsubscribeReason } from "@prisma/client";
import { SesClick, SesEvent, SesEventDataKey } from "~/types/aws-types";
import {
SesBounce,
SesClick,
SesEvent,
SesEventDataKey,
} from "~/types/aws-types";
import { db } from "../db";
import {
unsubscribeContact,
@@ -57,6 +62,12 @@ export async function parseSesHook(data: SesEvent) {
// Update daily email usage statistics
const today = new Date().toISOString().split("T")[0] as string; // Format: YYYY-MM-DD
const isHardBounced =
mailStatus === EmailStatus.BOUNCED &&
(mailData as SesBounce).bounceType === "Permanent";
console.log("mailStatus", mailStatus, "isHardBounced", isHardBounced);
if (
[
"DELIVERED",
@@ -89,11 +100,13 @@ export async function parseSesHook(data: SesEvent) {
bounced: updateField === "bounced" ? 1 : 0,
complained: updateField === "complained" ? 1 : 0,
sent: updateField === "sent" ? 1 : 0,
hardBounced: isHardBounced ? 1 : 0,
},
update: {
[updateField]: {
increment: 1,
},
...(isHardBounced ? { hardBounced: { increment: 1 } } : {}),
},
});
}
@@ -108,6 +121,7 @@ export async function parseSesHook(data: SesEvent) {
campaignId: email.campaignId,
teamId: email.teamId,
event: mailStatus,
mailData: data,
});
const mailEvent = await db.emailEvent.findFirst({
@@ -118,7 +132,11 @@ export async function parseSesHook(data: SesEvent) {
});
if (!mailEvent) {
await updateCampaignAnalytics(email.campaignId, mailStatus);
await updateCampaignAnalytics(
email.campaignId,
mailStatus,
isHardBounced
);
}
}
}
@@ -139,13 +157,23 @@ async function checkUnsubscribe({
campaignId,
teamId,
event,
mailData,
}: {
contactId: string;
campaignId: string;
teamId: number;
event: EmailStatus;
mailData: SesEvent;
}) {
if (event === EmailStatus.BOUNCED || event === EmailStatus.COMPLAINED) {
/**
* If the email is bounced and the bounce type is permanent, we need to unsubscribe the contact
* If the email is complained, we need to unsubscribe the contact
*/
if (
(event === EmailStatus.BOUNCED &&
mailData.bounce?.bounceType === "Permanent") ||
event === EmailStatus.COMPLAINED
) {
const contact = await db.contact.findUnique({
where: {
id: contactId,