Changes
Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com>
This commit is contained in:
co-authored by
renee-png
parent
b5803fc9b4
commit
079d179b5b
@@ -8,6 +8,10 @@ import { simpleParser } from "mailparser";
|
||||
import { matchAndUpdateEmails } from "@/lib/email-matching.server";
|
||||
|
||||
const MAX_MESSAGES_PER_RUN = 50;
|
||||
// Cloudflare Workers drop long-lived TLS sockets when streaming very large
|
||||
// IMAP FETCH responses. Skip oversize messages (>5 MB) so a single huge
|
||||
// email doesn't kill the whole poll. They can be retrieved manually later.
|
||||
const MAX_MESSAGE_SIZE_BYTES = 5 * 1024 * 1024;
|
||||
|
||||
export const Route = createFileRoute("/hooks/poll-imap")({
|
||||
server: {
|
||||
@@ -51,13 +55,48 @@ export const Route = createFileRoute("/hooks/poll-imap")({
|
||||
const sinceUid = (settings.last_uid ?? 0) + 1;
|
||||
const range = `${sinceUid}:*`;
|
||||
|
||||
for await (const msg of client.fetch(
|
||||
// First pass: fetch lightweight envelopes only to learn the
|
||||
// size of each message. Then fetch full source one-by-one,
|
||||
// skipping anything over the size cap.
|
||||
const candidates: Array<{ uid: number; size: number }> = [];
|
||||
for await (const meta of client.fetch(
|
||||
range,
|
||||
{ uid: true, source: true, envelope: true, size: true },
|
||||
{ uid: true, size: true },
|
||||
{ uid: true },
|
||||
)) {
|
||||
if (meta.uid <= (settings.last_uid ?? 0)) continue;
|
||||
candidates.push({ uid: meta.uid, size: meta.size ?? 0 });
|
||||
if (candidates.length >= MAX_MESSAGES_PER_RUN * 4) break;
|
||||
}
|
||||
|
||||
for (const cand of candidates) {
|
||||
if (imported >= MAX_MESSAGES_PER_RUN) break;
|
||||
if (msg.uid <= (settings.last_uid ?? 0)) continue;
|
||||
|
||||
// Always advance highestUid so we don't re-attempt skipped messages.
|
||||
if (cand.uid > highestUid) highestUid = cand.uid;
|
||||
|
||||
if (cand.size > MAX_MESSAGE_SIZE_BYTES) {
|
||||
console.warn(
|
||||
`Skipping IMAP uid ${cand.uid} (${cand.size} bytes > ${MAX_MESSAGE_SIZE_BYTES})`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
let msg: { uid: number; source: Buffer; size?: number } | null = null;
|
||||
try {
|
||||
for await (const m of client.fetch(
|
||||
String(cand.uid),
|
||||
{ uid: true, source: true, size: true },
|
||||
{ uid: true },
|
||||
)) {
|
||||
msg = m as any;
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Per-message fetch failed uid", cand.uid, e);
|
||||
continue;
|
||||
}
|
||||
if (!msg) continue;
|
||||
|
||||
let parsed;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user