Email-Anhang: echte IMAP-Fehlermeldung durchreichen
Bug: Anhang-Download schlug mit "Fehler beim Herunterladen des
Anhangs: Command failed" fehl – ohne jeden Kontext, warum.
Ursache: imapflow wirft bei jedem IMAP-NO/BAD-Response nur
`new Error('Command failed')` und legt den echten Server-Grund
in `.responseText` / `.responseStatus` ab. Unser Code las nur
`.message` und verlor damit alle Information.
Fix:
- fetchAttachmentInner extrahiert responseText/responseStatus
aus dem imapflow-Error und packt sie in die geworfene Meldung.
- downloadAttachment-Catch macht das gleiche, damit auch andere
IMAP-Fehler (mailboxOpen, connect) mit sinnvollem Text
durchkommen.
- Zusätzlicher Friendly-Mapping-Fall für "no longer exist" /
"no such message" → klare Meldung, dass die E-Mail-Liste
neu synchronisiert werden sollte.
Damit sieht der User im UI jetzt z.B. "NO Some of the requested
messages no longer exist" statt "Command failed" und weiß, dass
ein Resync hilft.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -797,7 +797,14 @@ export async function downloadAttachment(req: AuthRequest, res: Response): Promi
|
||||
res.send(attachment.content);
|
||||
} catch (error) {
|
||||
console.error('downloadAttachment error:', error);
|
||||
const rawMsg = error instanceof Error ? error.message : 'Unbekannter Fehler';
|
||||
// imapflow versteckt die eigentliche Server-Antwort in
|
||||
// `.responseText`/`.responseStatus` und setzt `.message` immer nur auf
|
||||
// `'Command failed'`. Wenn wir nur die `.message` ausgeben, sieht der
|
||||
// Endnutzer im UI nichts Verwertbares.
|
||||
const anyErr = error as { message?: string; responseText?: string; responseStatus?: string };
|
||||
const rawMsg = anyErr?.responseText
|
||||
? `${anyErr.responseStatus ? anyErr.responseStatus + ' ' : ''}${anyErr.responseText}`
|
||||
: error instanceof Error ? error.message : 'Unbekannter Fehler';
|
||||
const lower = rawMsg.toLowerCase();
|
||||
|
||||
let friendly = rawMsg;
|
||||
@@ -810,6 +817,8 @@ export async function downloadAttachment(req: AuthRequest, res: Response): Promi
|
||||
friendly = 'Zeitüberschreitung beim Verbinden zum IMAP-Server. Bitte später erneut versuchen.';
|
||||
} else if (lower.includes('authentication') || lower.includes('auth')) {
|
||||
friendly = 'IMAP-Authentifizierung fehlgeschlagen. Bitte Zugangsdaten prüfen.';
|
||||
} else if (lower.includes('no longer exist') || lower.includes('no such message') || lower.includes('unknown')) {
|
||||
friendly = 'Nachricht existiert im IMAP-Postfach nicht mehr (wahrscheinlich verschoben oder gelöscht). Bitte E-Mail-Liste neu synchronisieren.';
|
||||
}
|
||||
|
||||
res.status(500).json({
|
||||
|
||||
@@ -530,9 +530,16 @@ async function fetchAttachmentInner(
|
||||
}
|
||||
}
|
||||
} catch (fetchErr) {
|
||||
console.error(`[fetchAttachment] fetch(UID ${uid}) failed:`, fetchErr);
|
||||
// imapflow wirft bei IMAP-NO/BAD immer nur `new Error('Command failed')`,
|
||||
// die eigentliche Server-Antwort steht in `.responseText`. Ohne die
|
||||
// Anreicherung sähe der User oben im UI nur "Command failed" ohne
|
||||
// Kontext (Ursache 2026-07-11).
|
||||
const anyErr = fetchErr as { message?: string; responseText?: string; responseStatus?: string; response?: unknown };
|
||||
const detail = anyErr?.responseText || anyErr?.message || 'unbekannter Fehler';
|
||||
const statusTag = anyErr?.responseStatus ? `${anyErr.responseStatus} ` : '';
|
||||
console.error(`[fetchAttachment] fetch(UID ${uid}) failed [${statusTag}${detail}]:`, fetchErr);
|
||||
throw new Error(
|
||||
`Nachricht mit UID ${uid} konnte nicht geladen werden (${fetchErr instanceof Error ? fetchErr.message : 'unbekannter Fehler'}). Möglicherweise wurde sie im IMAP-Postfach verschoben oder gelöscht.`,
|
||||
`Nachricht mit UID ${uid} konnte nicht geladen werden: ${statusTag}${detail}. Möglicherweise wurde sie im IMAP-Postfach verschoben oder gelöscht.`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user