fix(mail): forceFullSweep on domain-add + 30s idle tick
Domain/display-name adds now force a full re-scan so newly-added gambling senders are caught immediately instead of waiting for the incremental UID window. IMAP-idle NOOP tick lowered 2min -> 30s to close the Junk-folder gap faster (Outlook drops straight into Junk, which IDLE does not watch). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
d31e45e2a8
commit
b757486579
@ -59,9 +59,12 @@ const DB_REFRESH_INTERVAL_MS = 5 * 60 * 1000; // 5 min — neue Connections en
|
||||
// Trade-off: alle 10min full reconnect-cycle. Vertretbar.
|
||||
const IDLE_RENEW_INTERVAL_MS = 10 * 60 * 1000; // 10 min
|
||||
|
||||
// NOOP-heartbeat alle 2min während IDLE: detect silent-drops (GMX-pattern).
|
||||
// Wenn NOOP fehlschlägt → close → loop iteriert → reconnect.
|
||||
const IDLE_NOOP_INTERVAL_MS = 2 * 60 * 1000; // 2 min
|
||||
// NOOP-heartbeat alle 30s während IDLE: detect silent-drops (GMX-pattern) +
|
||||
// Junk-Folder-Sweep-Frequenz. Vertretbar seit Phase-2-Inkremental-Scan:
|
||||
// leere SEARCH-Response (keine neuen UIDs) → skip ohne IMAP-Fetch, günstig.
|
||||
// Server-Headroom (CPX42) deckt die höhere Trigger-Rate ab.
|
||||
// Kein Konflikt mit IDLE_RENEW_INTERVAL_MS (10min) — beide laufen unabhängig.
|
||||
const IDLE_NOOP_INTERVAL_MS = 30 * 1000; // 30 s
|
||||
|
||||
// Token-Refresh-Schwelle: wenn Access-Token in weniger als 5min abläuft, vor
|
||||
// dem IMAP-Connect refreshen. Verhindert Mid-Session-Expiry.
|
||||
|
||||
@ -249,7 +249,11 @@ export default defineEventHandler(async (event) => {
|
||||
$fetch("/api/mail/scan-internal", {
|
||||
method: "POST",
|
||||
headers: { "x-admin-secret": adminSecret },
|
||||
body: { userId: user.id },
|
||||
// forceFullSweep: Alt-Mails der gerade hinzugefügten Domain werden sofort
|
||||
// erfasst — unabhängig davon ob lastFullSweepAt < 24h. Ohne dieses Flag
|
||||
// würde der inkrementelle Pfad greifen (UIDs > lastUid) und bereits vor-
|
||||
// handene Mails dieser Domain übersehen.
|
||||
body: { userId: user.id, forceFullSweep: true },
|
||||
}).catch((err: unknown) => {
|
||||
// Fire-and-forget: Fehler loggen, aber POST-Response nicht blockieren.
|
||||
// Der Scan ist best-effort — nächster Cron holt nach.
|
||||
|
||||
@ -32,7 +32,7 @@ export default defineEventHandler(async (event) => {
|
||||
throw createError({ statusCode: 401, message: "Unauthorized" });
|
||||
}
|
||||
|
||||
const body = (await readBody(event)) as { userId?: string };
|
||||
const body = (await readBody(event)) as { userId?: string; forceFullSweep?: boolean };
|
||||
const userId = body?.userId;
|
||||
if (!userId)
|
||||
throw createError({ statusCode: 400, message: "userId missing" });
|
||||
@ -102,7 +102,12 @@ export default defineEventHandler(async (event) => {
|
||||
// zustellen dass Blocklist-Updates auch ältere Mails erfassen.
|
||||
// Wichtig: wir behandeln lastUid temporär als 0 — NICHT persistieren.
|
||||
// Nach dem Sweep wird der echte maxUid gespeichert + lastFullSweepAt=NOW().
|
||||
//
|
||||
// forceFullSweep: explizit erzwungener Full-Sweep (z.B. nach Custom-Domain-Add).
|
||||
// Damit werden Alt-Mails der neuen Domain sofort erfasst, unabhängig davon
|
||||
// ob der letzte Full-Sweep < 24h her ist.
|
||||
const needsFullSweep =
|
||||
body.forceFullSweep === true ||
|
||||
!connection.lastFullSweepAt ||
|
||||
Date.now() - new Date(connection.lastFullSweepAt).getTime() > 24 * 3_600_000;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user