fix(email): recover stuck queue — reinit transporter on config save + manual flush ignores retry cap

Two gaps left emails stuck 'pending' after (re)configuring SMTP:

1. Saving the email config never re-initialised the transporter. The queue
   processor only re-inits when its cached transporter is null, so a changed
   SMTP account had no effect until a backend restart. Now call
   initializeTransporter(true) after save (it self-catches; invalid config
   just leaves it null, surfaced via the Test-email button).

2. The manual 'send now' flush (ignoreSchedule) still enforced retry_count<3,
   so emails that failed 3× while SMTP was broken could never be retried from
   the UI. Move the retry-cap (and schedule gate) to automatic runs only;
   a manual flush forces a retry of every pending email.
This commit is contained in:
Luca
2026-06-03 19:40:36 +02:00
parent a2b5ae17f3
commit 68c967f9bb
2 changed files with 18 additions and 3 deletions
+8 -3
View File
@@ -774,13 +774,18 @@ async function processEmailQueue({ ignoreSchedule = false, limit = 10 } = {}) {
// queue split-payment emails relative to the event date.
const now = new Date();
const query = db('email_queue')
.where('status', 'pending')
.where('retry_count', '<', 3);
.where('status', 'pending');
if (!ignoreSchedule) {
query.andWhere(function() {
// Automatic runs: respect the retry cap (don't hammer a failing
// address) AND the schedule (business-hours floor / future send).
query.where('retry_count', '<', 3).andWhere(function() {
this.whereNull('scheduled_at').orWhere('scheduled_at', '<=', now);
});
}
// A manual "send now" (ignoreSchedule) deliberately bypasses BOTH the
// schedule and the retry cap: the admin is forcing a retry, typically
// right after fixing SMTP. Without this, emails that failed 3× during
// an SMTP outage are stuck "pending" forever with no way to resend.
pendingEmails = await query
.orderBy('scheduled_at', 'asc')
.orderBy('created_at', 'asc')