diff --git a/backend/src/controllers/cachedEmail.controller.ts b/backend/src/controllers/cachedEmail.controller.ts index fb9e18df..025a9504 100644 --- a/backend/src/controllers/cachedEmail.controller.ts +++ b/backend/src/controllers/cachedEmail.controller.ts @@ -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({ diff --git a/backend/src/services/imapService.ts b/backend/src/services/imapService.ts index 3bb5afbe..d35a3fe1 100644 --- a/backend/src/services/imapService.ts +++ b/backend/src/services/imapService.ts @@ -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.`, ); }