fix(notifications): a real send keeps its ten minutes, only the admin test is impatient (#2196)

The #2196 timeouts were applied to one shared transport, so the 30-second
inactivity bound landed on the password-reset and notification mails as well
as on the admin's test send. That bound starts counting after the greeting,
which means it bounds the transfer: a relay that scans the message can sit on
DATA for minutes, and a reset mail dropped for that reason fails where nobody
can see it. Nodemailer's ten minutes are back for a real send, the connect and
greeting cuts stay, and the test send keeps the 30 seconds it needs to answer
inside the client's 40-second budget. The source comment already described this
split; only the value disagreed.
This commit is contained in:
Maurice
2026-09-03 13:59:39 +02:00
parent 15f22058e9
commit 9228ef2bce
2 changed files with 36 additions and 10 deletions
+20 -3
View File
@@ -147,13 +147,30 @@ describe('MailerService TLS options', () => {
expect(sendMail).not.toHaveBeenCalled();
});
it('MAILER-007: every SMTP phase is bounded, so a dead relay fails instead of hanging', async () => {
it('MAILER-007: connecting and greeting are bounded hard, the transfer is not', async () => {
configureSmtp();
await newMailer().sendEmail('someone@example.com', 'Subject', 'Body');
// Nodemailer's own defaults (120s / 30s / 600s) all outlive the client's 8s
// API timeout, which is how #2196 produced a failure nobody could read.
// Nodemailer's connect and greeting defaults (120s / 30s) outlive the client's
// 8s API timeout, which is how #2196 produced a failure nobody could read. The
// inactivity timeout keeps its ten minutes on a real send: it bounds the
// transfer, a scanning relay can sit on DATA for minutes, and nobody is
// waiting on the result.
expect(lastTransportOptions()).toMatchObject({
connectionTimeout: 10_000,
greetingTimeout: 10_000,
socketTimeout: 600_000,
});
});
it('MAILER-007b: the admin test send bounds the transfer too, because somebody is waiting', async () => {
configureSmtp();
await newMailer().testSmtp('someone@example.com');
// The client gives this call 40s (CHANNEL_TEST_TIMEOUT), so a relay that
// accepts the connection and then goes quiet still has to produce a verdict.
expect(lastTransportOptions()).toMatchObject({
connectionTimeout: 10_000,
greetingTimeout: 10_000,