Toast-Benachrichtigungen bei IMAP-Sync- und SMTP-Send-Fehlern

Bisher blieb ein fehlgeschlagener IMAP-Sync oder E-Mail-Versand still – der User
sah nur im Browser-Devtools, dass etwas schief lief. Jetzt erscheint eine rote
Toast-Benachrichtigung (8 Sekunden) mit der konkreten Fehlermeldung des Servers,
z.B. 'Sync fehlgeschlagen: IMAP-Authentifizierung fehlgeschlagen: NO [AUTHENTICATIONFAILED]'.

EmailClientTab (Synchronisieren-Button):
- toast.success bei erfolgreichem Sync
- toast.error bei Fehler + bei Backend-Response mit success=false

ComposeEmailModal (Senden):
- toast.success bei erfolgreichem Versand
- toast.error bei SMTP-Fehler mit Server-Response (zusätzlich zum Inline-Fehler)

Außerdem im imapService.testImapConnection:
- Roh-Error wird jetzt geloggt (code, response, responseStatus, authenticationFailed)
- ImapFlow-spezifische Felder werden in die Fehlermeldung übernommen, sodass
  z.B. '2 NO [AUTHENTICATIONFAILED] Authentication failed.' direkt sichtbar wird

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 15:16:04 +02:00
parent 620bc1bcd9
commit cfcdf088df
3 changed files with 56 additions and 4 deletions
@@ -1,5 +1,6 @@
import { useState, useRef, useEffect } from 'react';
import { Send, Paperclip, X, FileText } from 'lucide-react';
import toast from 'react-hot-toast';
import Modal from '../ui/Modal';
import Button from '../ui/Button';
import { stressfreiEmailApi, CachedEmail, MailboxAccount, EmailAttachment } from '../../services/api';
@@ -150,12 +151,24 @@ export default function ComposeEmailModal({
attachments: attachments.length > 0 ? attachments : undefined,
contractId,
}),
onSuccess: () => {
onSuccess: (result) => {
// Backend kann success=false zurückgeben auch bei HTTP 200
if (result && (result as any).success === false) {
const msg = (result as any).error || 'E-Mail-Versand fehlgeschlagen';
setError(msg);
toast.error(`SMTP-Fehler: ${msg}`, { duration: 8000 });
return;
}
toast.success('E-Mail versendet');
onSuccess?.();
handleClose();
},
onError: (err) => {
setError(err instanceof Error ? err.message : 'Fehler beim Senden');
onError: (err: any) => {
const msg =
err?.response?.data?.error ||
(err instanceof Error ? err.message : 'Fehler beim Senden');
setError(msg);
toast.error(`SMTP-Fehler: ${msg}`, { duration: 8000 });
},
});
@@ -1,6 +1,7 @@
import { useState, useEffect } from 'react';
import { RefreshCw, Plus, Mail, Inbox, Send, Trash2 } from 'lucide-react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import toast from 'react-hot-toast';
import { cachedEmailApi, stressfreiEmailApi, CachedEmail } from '../../services/api';
import { useAuth } from '../../context/AuthContext';
import Button from '../ui/Button';
@@ -95,7 +96,14 @@ export default function EmailClientTab({ customerId }: EmailClientTabProps) {
// Synchronisation
const syncMutation = useMutation({
mutationFn: (accountId: number) => stressfreiEmailApi.syncEmails(accountId),
onSuccess: () => {
onSuccess: (result) => {
// Backend liefert success=false bei IMAP-Fehler, aber ohne HTTP-Error
if (result && (result as any).success === false) {
const err = (result as any).error || 'IMAP-Synchronisation fehlgeschlagen';
toast.error(`Sync fehlgeschlagen: ${err}`, { duration: 8000 });
return;
}
toast.success('E-Mails synchronisiert');
// E-Mail-Listen neu laden
queryClient.invalidateQueries({ queryKey: ['emails'] });
// Ordner-Anzahlen aktualisieren
@@ -103,6 +111,10 @@ export default function EmailClientTab({ customerId }: EmailClientTabProps) {
// Mailbox-Accounts aktualisieren
queryClient.invalidateQueries({ queryKey: ['mailbox-accounts', customerId] });
},
onError: (error: any) => {
const msg = error?.response?.data?.error || error?.message || 'Unbekannter Fehler';
toast.error(`Sync fehlgeschlagen: ${msg}`, { duration: 8000 });
},
});
const handleSync = () => {