Skip to content

Commit e82d2b5

Browse files
committed
fix: skip unchanged first-run domain status emails
1 parent 5d5d50e commit e82d2b5

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

apps/web/src/server/service/domain-service.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,14 +212,20 @@ function shouldContinueVerifying(
212212
}
213213

214214
function shouldSendDomainStatusNotification({
215+
previousStatus,
215216
currentStatus,
216217
hasEverVerified,
217218
lastNotifiedStatus,
218219
}: {
220+
previousStatus: DomainStatus;
219221
currentStatus: DomainStatus;
220222
hasEverVerified: boolean;
221223
lastNotifiedStatus: DomainStatus | null;
222224
}) {
225+
if (lastNotifiedStatus === null && currentStatus === previousStatus) {
226+
return false;
227+
}
228+
223229
if (hasEverVerified) {
224230
return currentStatus !== lastNotifiedStatus;
225231
}
@@ -524,6 +530,7 @@ export async function refreshDomainVerification(
524530

525531
if (
526532
shouldSendDomainStatusNotification({
533+
previousStatus,
527534
currentStatus: updatedDomain.status,
528535
hasEverVerified:
529536
verificationState.hasEverVerified ||

apps/web/src/server/service/domain-service.unit.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,39 @@ describe("domain-service", () => {
243243
expect(mockSendMail).not.toHaveBeenCalled();
244244
});
245245

246+
it("does not send status email on first refresh when status is unchanged", async () => {
247+
const domain = createDomain({
248+
status: DomainStatus.SUCCESS,
249+
dkimStatus: DomainStatus.SUCCESS,
250+
spfDetails: DomainStatus.SUCCESS,
251+
isVerifying: false,
252+
});
253+
mockRedis.mget.mockResolvedValue([null, null, null]);
254+
mockGetDomainIdentity.mockResolvedValue({
255+
DkimAttributes: { Status: DomainStatus.SUCCESS },
256+
MailFromAttributes: { MailFromDomainStatus: DomainStatus.SUCCESS },
257+
VerificationInfo: {
258+
ErrorType: null,
259+
LastCheckedTimestamp: new Date("2026-03-09T12:00:00.000Z"),
260+
},
261+
VerificationStatus: DomainStatus.SUCCESS,
262+
});
263+
mockDb.domain.update.mockResolvedValue(
264+
createDomain({
265+
status: DomainStatus.SUCCESS,
266+
dkimStatus: DomainStatus.SUCCESS,
267+
spfDetails: DomainStatus.SUCCESS,
268+
dmarcAdded: true,
269+
isVerifying: false,
270+
}),
271+
);
272+
273+
await refreshDomainVerification(domain);
274+
275+
expect(mockSendMail).not.toHaveBeenCalled();
276+
expect(wasLastNotifiedStatusStored()).toBe(false);
277+
});
278+
246279
it("reserves the notification so concurrent refreshes do not double-send", async () => {
247280
const domain = createDomain();
248281
mockRedis.mget.mockResolvedValue([null, null, null]);

0 commit comments

Comments
 (0)