/** * Übersetzt rohe Backend/IMAP-Fehlermeldungen in benutzerfreundliche Sätze. * * Backend liefert oft IMAP-Server-Antworten 1:1 durch (z.B. * `[AUTHENTICATIONFAILED] Invalid credentials (Failure)`). Die zeigen wir * dem User NICHT — stattdessen humane Übersetzung mit Hinweis was zu tun ist. */ export type MailErrorReason = | 'auth_failed' | 'app_password_required' | 'connection_failed' | 'host_unreachable' | 'tls_error' | 'rate_limited' | 'unknown'; export function classifyMailError(raw: string | null | undefined): MailErrorReason { if (!raw) return 'unknown'; const s = raw.toLowerCase(); if ( s.includes('authenticationfailed') || s.includes('invalid credentials') || s.includes('authentication failed') || s.includes('login failed') || s.includes('auth failed') || s.includes('bad password') || s.includes('wrong password') ) { return 'auth_failed'; } if ( s.includes('application-specific password') || s.includes('app password required') || s.includes('weblogin_required') || s.includes('two-factor') ) { return 'app_password_required'; } if ( s.includes('etimedout') || s.includes('econnrefused') || s.includes('connection timeout') || s.includes('socket timeout') || s.includes('connection reset') ) { return 'connection_failed'; } if ( s.includes('enotfound') || s.includes('host not found') || s.includes('getaddrinfo') || s.includes('dns') ) { return 'host_unreachable'; } if (s.includes('tls') || s.includes('ssl') || s.includes('certificate')) { return 'tls_error'; } if (s.includes('rate limit') || s.includes('too many') || s.includes('throttl')) { return 'rate_limited'; } return 'unknown'; } /** * Liefert den i18n-Schlüssel für die humane Variante eines Mail-Errors. * Caller ruft `t(humanizeMailError(rawError))` für den finalen Text. */ export function humanizeMailError(raw: string | null | undefined): string { const reason = classifyMailError(raw); return `mail.errors.${reason}`; }