Zweck
Das Mail-Modul ist eine Single-Page-App mit Folder-Tree (links), Mail-Liste (Mitte) und Detail-Pane (rechts) auf Desktop, sowie einem Single-Pane-Navigator auf Mobile. Es verbindet sich mit Microsoft 365 über Mail-Konten, bietet einen Compose-Modal mit Rich-Text-Editor und AI-Draft, sowie einen Live-Sync über useMailStream() (WebSocket/SSE).
Voraussetzungen
Berechtigungen (CASL)
| Action | Subject | Wirkung | Keycloak-Rolle |
|---|---|---|---|
view | FE_Mail, Mail | Mail-Modul aufrufbar | — |
view/update | MailFolder | Folder-Tree und Reorder | APP_SPEAMCORE_VIEW/UPDATE_MAIL_FOLDER |
view | MailRecipient, MailEmployeeState | Empfaenger und Lese-Status | APP_SPEAMCORE_VIEW_MAIL_RECIPIENT, MAIL_EMPLOYEE_STATE |
create | Mail | Mail versenden | APP_SPEAMCORE_CREATE_MAIL |
update | Mail | Draft speichern | APP_SPEAMCORE_UPDATE_MAIL |
delete | Mail | Soft-Delete (in Trash) | APP_SPEAMCORE_DELETE_MAIL |
viewAll | Mail | Admin-Override: sieht alle Postfaecher des Mandanten unabhaengig von MailboxEmployee-Zuweisung — gedacht fuer IT/Compliance/Audit. Ohne diese Permission greift der Standard-Scope (nur eigene + explizit zugewiesene Aliase). | APP_SPEAMCORE_VIEW_ALL_MAIL |
Routen
| Pfad | Variante |
|---|---|
/mail | Standard im Modal-Modus |
/mail/:mailId | Direktlink auf eine konkrete Mail |
/mail-popout | Eigenes Browserfenster ohne Modal-Wrapper |
/mail-popout/:mailId | wie oben mit Mail-Vorauswahl |
Schritt-für-Schritt-Anleitung
Mail lesen
- Mail (
/mail) öffnen. - Linke Sidebar zeigt den Folder-Tree (Inbox / Sent / Drafts / Trash + Custom-Folder).
- Folder anklicken → Mail-Liste in der Mitte.
- Mail anklicken → Detail-Pane rechts mit Volltext, Anhängen und Aktionen.
Mail schreiben
- Compose klicken —
MailComposeModalöffnet sich. - Empfaenger eingeben (Autocomplete via
MailRecipientInput, mit Contact-Resolution). - Subjekt und Body pflegen — Rich-Text-Editor mit HTML-Sanitization.
- Optional AI-Draft klicken (
MailComposeAiButton) — generiert Body via LLM, anschliessend bearbeitbar. - Anhänge per Drag-&-Drop (
MailAttachmentZone) ergaenzen — max. 25 MB pro Datei (Graph-API-Limit). - Senden —
POST /api/mails/send.
Auf Mail antworten / weiterleiten
Aus dem Detail-Pane: Reply, ReplyAll oder Forward — jeweils öffnet MailComposeModal mit vorbefuelltem Body.
Folder umsortieren
In der Sidebar per Drag-&-Drop. Wirkt über useFolderReorder() und PATCH /api/mail-folders/:id/reorder.

UI-Elemente
Komponente: MailFolderSidebar
Folder-Tree mit Drag-&-Drop. Folder-Typen: inbox, sent, drafts, trash, custom.
Komponente: MailComposeModal
Rich-Text-Editor mit Recipient-Autocomplete, Anhang-Zone und AI-Draft-Button.
Button: „AI-Draft"
Generiert via LLM einen Mail-Body aus dem Kontext (Empfaenger, Betreff, vorhergehende Mails). Erfordert aktiven AI-Provider.
Hook: useMailStream
WebSocket-/SSE-Subscription für eingehende Mails. Invalidiert die Mail-Queries automatisch.
Felder und Eingaben (Compose-Modal)
| Feldname | Pflicht | Datentyp | Wirkung beim Ausfuellen | Voraussetzung |
|---|---|---|---|---|
to | ja | EmailAddress[] | Empfaenger der Mail. Validation via RFC 5322. | mind. ein gueltiger Empfaenger. |
cc | nein | EmailAddress[] | Kopie. | gültige Adressen. |
bcc | nein | EmailAddress[] | Blindkopie. | gültige Adressen. |
subject | nein | String (max. 255) | Betreff der Mail. | — |
body | ja | HTML/Text | Hauptinhalt. Wird HTML-sanitiert vor dem Versenden. | — |
attachmentDocumentIds | nein | UUID[] | Anhänge über das Document-Modell. | Datei kleiner als 25 MB. |
Modell-Felder (Mail)
| Feld | Datentyp | Wirkung |
|---|---|---|
mailboxId | UUID | Mail-Zuordnung zur Mailbox. |
microsoftMessageId | String | Graph-API-ID — Identifizierung in Microsoft 365. |
conversationId | String | Threading. |
internetMessageId | String | RFC-2822-ID. |
subject, body, bodyType | — | Inhalt. |
receivedAt, sentAt | DateTime | Zeitstempel. |
isDraft | Boolean | Drafts werden lokal in SpeamCore gehalten. |
recipients | nested[] | From/To/CC/BCC mit MailAddress-Aufloesung zu Kontakt. |
employeeStates | nested[] | Pro Mitarbeiter Lese-Status, Folder-Zuweisung und seit Welle 139 isHandled/handledAt. |
calendarEvent | nested | iCal-Verknuepfung (Phase 1). |
aiSummary (Welle 139) | TEXT | KI-Zusammenfassung in 2-3 Sätzen, max. 2000 Zeichen. |
aiSummaryDurationMs (Welle 139) | Integer | Verarbeitungs-Dauer für die UI-Anzeige („in 2,3 Sek erstellt"). |
aiCategory, aiNeedsReply, aiReplySuggestion, aiProcessedAt, linkedEntityType/-Id | gemischt | KI-Klassifizierung + Antwortvorschlag + Verknüpfung zu Auftrag/Beleg. |
KI-Banner-Card und Erledigt-Workflow (Welle 139)
Im Detail-Panel erscheint über dem Mail-Body eine KI-Banner-Card mit:
- Zusammenfassung (
aiSummary) in 2–3 Sätzen plus Dauer-Hinweis - Key-Facts als Pills:
aiCategory(lila),linkedEntityType(neutral),aiNeedsReplyals „Handlung notwendig" (orange) oder „Erledigt" (grün, wennisHandled = true) - Action-Chips:
- „Antwortvorschlag übernehmen" — übernimmt
aiReplySuggestionins Reply-Formular - „Als erledigt markieren" — togglet
isHandled(siehe unten)
- „Antwortvorschlag übernehmen" — übernimmt
- „Erneut analysieren" (im AI-Assist-Menü oder Sidebar-Header) startet
POST /api/mails/:id/reprocess-ai— der Query-Cache wird live gepatcht, kein Refresh nötig
Erledigt-Status (isHandled)
Pro Mail und Mitarbeiter speichert MailEmployeeState:
| Feld | Wirkung |
|---|---|
isHandled | Boolean — User markiert die Mail als bearbeitet. |
handledAt | Zeitstempel. |
Sichtbarkeit:
- Inbox, Smart-Folders, Custom-Folders: erledigte Mails werden über
?hideHandled=trueausgeblendet (Default in der Inbox-Sicht). - Trash, Sent, Drafts: erledigte Mails bleiben sichtbar.
- Der Counter
unreadCounts.needsActionzählt nuraiNeedsReply = true AND isHandled != true.
Mailbox-Override für KI-Zusammenfassung
MicrosoftConfig.aiAutoSummary (mandantenweit) und Mailbox.aiAutoSummaryOverride (pro Postfach) steuern, ob neue Mails automatisch eine aiSummary erhalten. Reprocess-Endpoint funktioniert unabhängig davon.
Liste — Datum-Sections + Quick-Range + Background-Preload (Welle 139)
Die Mail-Liste rendert seit Welle 139 Sticky-Section-Header zwischen den Zeilen:
| Section | Bedingung |
|---|---|
| HEUTE | gleicher Kalendertag |
| GESTERN | dayDiff = 1 |
| DIESE WOCHE | dayDiff ≤ aktueller ISO-Wochentag (ab Montag) |
| LETZTE WOCHE | dayDiff ≤ Wochentag + 7 |
| DIESEN MONAT | gleicher Monat und Jahr |
| ÄLTER | Fallback |
Sections werden in Search/Trash/Drafts unterdrückt. Basis-Datum: receivedAt → sentAt → updatedAt → createdAt.
Zusätzlich:
- Quick-Range-Dropdown im List-Header (schneller Wechsel zwischen typischen Zeiträumen).
- Background-Preload der letzten 30 Tage (max. 6 Pages) bei aktiver Inbox-Sicht — beim Scrollen entsteht kein Loading-Spinner mehr.
Popout-only Mail-Fenster (Welle 139)
Das eingebettete Mail-Modal in der App wurde entfernt. Klick auf das Mail-Icon im Header öffnet jetzt immer das Popout-Fenster (separates Browser-Fenster). Vorteil: Mehrfenster-Workflow, die Mail bleibt sichtbar, während im Haupt-Tab andere Module bedient werden.
MailboxAlias-Blacklist + Per-User-Permissions (Welle 139)
Auf Mail-Konten sind zwei neue Mechanismen aktiv:
MailboxAlias.isBlacklisted— permanent ausgeschlossen, unabhängig vonisActive. Aliase mit diesem Flag erscheinen in keiner Liste und keinem Counter.MailboxEmployee.aliasPermissions— Map<emailAddress>→'read' | 'write' | 'readwrite'. ImaliasMode = separatewerden nur Aliase angezeigt, auf die der Mitarbeiter die passende Permission hat.unreadCountsrespektiert die Permission-Map.
Wiederverwendbare Konzepte
- Mail-Konten — Microsoft-365-Anbindung.
- Polymorpher Parent-Pattern — Mails werden in
DocumentParent/MailRecipientpolymorph verknuepft. - Berechtigungen verstehen (CASL)
Signatur-Editor (Welle 149)
Pro Mandant gibt es einen zentralen Signatur-Editor unter Customization → Mail-Signature (Route /customization/mail-signature). Drei Layout-Varianten zur Auswahl:
| Variante | Aufbau |
|---|---|
compact | eine Zeile mit Name + Titel, darunter Kontakt-Daten kompakt |
classic | klassischer Block mit Logo links, Daten rechts |
stacked | Logo oben, Name + Titel darunter, Kontakt darunter |
Felder pro Toggle (Vorname / Nachname / Job-Titel / Telefon / Mobil / Email): jeder Wert kann ein-/ausgeblendet werden. Firmen-Daten (Adresse, USt-IdNr., Geschäftsführer) sind read-only aus /settings/company und können nicht im Editor überschrieben werden — die Konsistenz bleibt garantiert.
Personalisierung zur Renderzeit: Beim Versand jeder Mail lädt der Render-Service den Sender-Kontext und injiziert Name + Telefon + Mail des aktuellen Mitarbeiters. Eine Signatur — beliebig viele Sender.
Logo-Höhe: Slider 60–250 px für proportionales Logo. Bild aus dem Customization-Logo.
Disclaimer + Confidentiality: Frei editierbar im Legal-Bereich, wird unten an die Signatur angehängt.
Preview als anderer Mitarbeiter: Im Editor-Header gibt's einen Mitarbeiter-Picker (view:Employee-Check) — sehen Sie, wie die Signatur für Anna Müller aussieht, ohne sich als Anna einzuloggen.
Default-Auto-Load: Im Compose-Modal wird die Signatur automatisch angehängt, ohne dass der User einen Insert-Button drücken muss. Über das Settings-Toggle pro Mitarbeiter abschaltbar.
Output: Inline-HTML (keine CSS-Klassen) mit Outlook-Fallback-Strukturen.
Phishing-AI (Welle 149)
Zwei neue Mail-Felder klassifizieren eingehende Mails auf Phishing-Risiko:
| Feld | Typ | Werte |
|---|---|---|
aiScamScore | ENUM | none / low / medium / high |
aiScamReasons | TEXT | KI-Begründung in 1–3 Sätzen |
Erkennung: Im selben KI-Call wie aiSummary / aiCategory — der Prompt prüft auf Domain-Spoofing, Login-Forderungen, Vorschussbetrug, Dringlichkeits-Drohungen.
Anzeige im Detail-Panel:
aiScamScore = "high"→ rote Warnbox über dem Mail-Body mit Empfehlung „IT kontaktieren, nicht klicken"aiScamScore = "medium"→ orange Warnung mit Hinweis „Bitte zweimal lesen"aiScamReasonswird unterhalb angezeigt — der User versteht, warum der Score so hoch ist
Config: MicrosoftConfig.aiScamDetectionEnabled mandantenweit, Mailbox.aiScamDetectionOverride pro Postfach. Standardmäßig aktiv.
Bidirektionaler MS↔SC State-Sync (Welle 149)
SpeamCore und Outlook (Microsoft 365) bleiben jetzt in beide Richtungen synchron — wenn ein User im Outlook Web eine Mail liest, wird sie sofort in SpeamCore als gelesen markiert (und umgekehrt). Details im Konzept: Mail Microsoft Graph-Sync.
Was synchronisiert wird:
isRead(gelesen / ungelesen)flag(markiert)parentFolderId(in welchem Ordner)isTrashed(in den Papierkorb verschoben)- Folder-Tree-Updates (neue Ordner, Umbenennungen)
Technik: Microsoft Graph-Webhook-Subscriptions pro Mailbox, automatische Verlängerung über microsoft-subscription-renewal.worker.ts (Cron alle 12 h).
Auto-Erledigt (Welle 149)
Wenn Sie eine Mail mit der Action „Antworten" (oder „Allen antworten") beantworten, markiert SpeamCore automatisch alle bisherigen Mails im selben Thread (gleiche conversationId) als isHandled = true — sofern sie aiNeedsReply = true haben und noch nicht erledigt sind. Pro Mitarbeiter im MailEmployeeState-Team.
Nicht für Forwards — die starten eine neue conversationId.
So bleibt die Smart-Folder-Sicht „Braucht Antwort" sauber, ohne dass Sie nachträglich Häkchen setzen.
Smart-Folder-Bulk-Aktionen (Welle 149)
Drei neue Endpoints für Massen-Aktionen auf einen kompletten Smart-Folder:
| Endpoint | Wirkung |
|---|---|
POST /api/mail-employee-state/mark-folder-read | Alle Mails im gewählten Folder als gelesen |
POST /api/mail-employee-state/mark-folder-handled | Alle Mails als erledigt |
POST /api/mail-employee-state/mark-folder-unread | Alle als ungelesen (z. B. Übergabe an Kollegen) |
Smart-Folder-Targets: inbox, sentitems, drafts, trash, needsAction, newsletters, attachments, calendar.
Realkosten-Anzeige (Welle 149)
Im Mailbox-Detail unter „KI-Kosten" zeigt die AiCostEstimateCard die echten KI-Kosten der letzten 30 Tage, sobald genug Daten vorhanden sind:
| Feld | Quelle |
|---|---|
aiActualCostEur30d | Summe AiUsageLog.costEur über 30 Tage (4 Dez.) |
aiActualMailCount30d | Anzahl Mails mit KI-Analyse |
aiActualDays | Anzahl unterschiedlicher Tage mit Aktivität |
aiActualCostPerMail | Mittelwert pro Mail (6 Dez.) |
aiActualAvgPerDay | Mittelwert pro Tag (4 Dez.) |
Realwerte ab: ≥ 10 Mails ODER ≥ 5 Tage Datengrundlage. Sonst zeigt die Karte eine hartkodierte Schätzung mit dem Hinweis „Basierend auf Standard-Annahmen — echte Werte ab Tag 5".
Alias-Switcher in der Sidebar (Welle 149)
Pro Mailbox können Aliase eingerichtet sein (z. B. info@, vertrieb@, support@). In der MailFolderSidebar sind sie als eingerückte Klick-Switcher unter der Mailbox sichtbar:
- Pro Alias eigener Unread-Counter
- Klick filtert die Liste auf den Alias (
?aliasFilterAddress=...) - BE-Filter via
recipientAliasEmail(JOIN-Query, ersetzt den alten URL-Killer mit 1000+ UUIDs)
Mehrere Aliase gleichzeitig? Aktuell nur einer als Filter. Für „alle anschauen": Filter zurücksetzen.
Gravatar + EmailAvatar (Welle 149)
Statt grauer Initial-Kacheln zeigen Mails jetzt das Gravatar-Bild des Absenders, sofern verfügbar:
- Neuer
Contact.profilePictureDocumentId+profilePictureSyncedAt - Sync über
contact-enrichment-worker(kein Live-Call beim Anzeigen — wir laden das Bild einmalig in unser Document-Modul) - SHA-256(email) als Gravatar-Key,
d=404(nur echte Avatare, keine Identicons) - FE-Fallback: deterministisch hash-gefärbte Initialen client-seitig (nicht persistiert)
- DSGVO-Hinweis: Beim Sync wird der E-Mail-Hash an Automattic übermittelt — User muss im Settings-Toggle
gravatarEnabledopt-in. Beim Opt-Out werden keine Gravatare gezogen.
Compliance-Whitelist (Welle 149)
Vehicle-Recipient-Whitelist pro Mailbox — wer darf Mails von welchen Absendern verarbeiten:
- Auf Mailbox-Ebene gepflegt
- NULL = Rolle-basiert (Default — Standard-Permissions greifen)
- Nicht-NULL = explizite Whitelist überschreibt Rollen-Permissions
Eingesetzt z. B. bei Personalrats-Postfach: nur HR-Leitung + Personalrat-Mitglieder dürfen Mails verarbeiten, normale HR-SB sind ausgeschlossen.
UX-Updates Compose (Welle 149)
Der Compose-Modal wurde komplett redesigned:
- Schmaler Header mit kompakten An / Cc / Bcc / Betreff-Zeilen (keine eigene Toolbar pro Feld)
- TipTap-BubbleMenu (Bold/Italic/Underline/Link/List) erscheint nur auf Text-Selektion
- Footer-Action-Bar: großer Senden-Button in Mandantenfarbe mit Tastatur-Hinweis
⌘↵, daneben Icons für Anhang, Bild, Signatur, KI-Pill, Discard - Resizable über Bottom-Right-Handle, Größe in
localStoragepersistiert - Reply-Visualisierung: Attribution „Am 26.05.2026 schrieb Max Müller …" + tenant-gefärbter Quote-Block
Bulk-Toolbar bei Multi-Select
Sobald mehrere Mails markiert sind (Click+Shift, Cmd/Ctrl+A, Multi-Klick), schwebt eine Bulk-Action-Bar unten:
- Markieren als gelesen / ungelesen / erledigt
- In Papierkorb verschieben
- Verschieben in Folder (Picker)
Tastatur-Shortcuts
| Taste | Wirkung |
|---|---|
/ | Search-Fokus in der Listen-Suchleiste |
? | Shortcut-Overlay (Cheatsheet-Modal) |
y | Aktuelle Mail toggle-handled |
u | Aktuelle Mail toggle-read |
Cmd/Ctrl+Enter | Compose senden |
Cmd/Ctrl+A | Alle Mails in Liste selektieren |
Esc | Compose schließen / Multi-Select aufheben |
Right-Click-Aktionen
Rechtsklick auf eine Mail in der Liste öffnet ein Context-Menü mit:
- Antworten / Allen antworten / Weiterleiten
- Toggle Erledigt / Gelesen / Markiert
- Copy Sender / Copy Subject
- In Folder verschieben
- Löschen
Smart-Folder-Sidebar Rechtsklick: „Alle als gelesen / ungelesen / erledigt" auf den ganzen Folder.
Orphan-Cleanup + Archive-Folder (Welle 149)
Hintergrund-Service mailOrphanCleanup.service:
- Prüft beim Sync: gibt Microsoft Graph für unsere Mail-ID einen 404 zurück → die Mail wurde auf MS-Seite endgültig gelöscht
$batch GETfür parallele Prüfung (effizient)- Force-Delete in SpeamCore — Mail verschwindet aus der Liste
- Trigger: Boot + nach jedem Sync
Archive-Folder: Neuer Folder-Typ MailFolder.type = 'archive' (Well-Known Outlook /archive). Über Smart-Folder-Aktionen oder Drag&Drop ablegen.
Verknüpfungen zu anderen Modulen
- Mail-Konten — Quelle der Mailbox, KI-Feature-Toggles + Compliance-Whitelist.
- Mail Microsoft Graph-Sync — Konzept-Hintergrund zum bidirektionalen Sync.
- Kontakte —
MailAddress-Auflösung, Gravatar-Sync. - Mitarbeiter —
MailEmployeeStatepro Mitarbeiter und Mail (isHandled,isRead,isStarred). - Dokumente — Anhänge über das
Document-Modell + Gravatar-Bild-Storage. - Briefe — Mail-Scan-to-Inbox überführt eingehende Mails mit PDF-Anhang in den Brief-Posteingang.
- KI-Chat-Architektur — Mail-Tools im MCP-Server für Auswertungen + Versand via KI.
Häufige Fehler und Lösungen
| Fehler | Lösung |
|---|---|
| Mail kommt nicht an | Empfaenger prüfen; ggf. Spam-Filter beim Empfaenger; lastSyncAt der Mailbox prüfen. |
| AI-Draft-Button fehlt | Kein AI-Provider aktiv. |
| Anhang wird abgelehnt | Datei größer als 25 MB (Graph-API-Limit). |
| Folder-Reorder bleibt nicht erhalten | Multiple-User-Edits — Lost-Update. Erneut versuchen. |
| Drafts gehen verloren | Drafts liegen nur in SpeamCore — bei MailboxEmployee-Loeschung gehen sie mit. |
API/Schnittstellen
| Methode | Endpoint | Zweck | CASL |
|---|---|---|---|
GET | /api/mails | Liste | view Mail |
GET | /api/mails/:id | Detail | view Mail |
POST | /api/mails/send | Neue Mail senden | create Mail |
POST | /api/mails/:id/send | Draft versenden | update Mail |
POST | /api/mails/:id/reply | Antworten | create Mail |
POST | /api/mails/:id/forward | Weiterleiten | create Mail |
PATCH | /api/mails/:id | Draft-Update | update Mail |
DELETE | /api/mails/:id | Soft-Delete (Trash) | delete Mail |
GET | /api/mail-folders | Folder-Tree | view MailFolder |
PATCH | /api/mail-folders/:id/reorder | Folder-Reorder | update MailFolder |
GET | /api/mail-employee-state/:employeeId | Per-Employee-State | — |
Versionshinweise
- 2026-04-29: Initiale Veröffentlichung mit FE-Tiefen-Standard.
- 2026-05-21 (Welle 139): Massive Erweiterung des Mail-Moduls. KI-Banner-Card mit Summary + Key-Facts-Pills + Action-Chips, persistente
aiSummarymit Dauer-Hinweis, „Erneut analysieren" viaPOST /:id/reprocess-aimit Live-Cache-Patch.isHandled/handledAtaufMailEmployeeState,?hideHandled=true-Param inlistMails,needsAction-Counter imunread-counts. Datum-Sections (HEUTE / GESTERN / ÄLTER), Quick-Range-Dropdown, Background-Preload der letzten 30 Tage (max. 6 Pages). Eingebettetes Mail-Modal entfernt — Header-Icon öffnet immer das Popout-Fenster.MailboxAlias.isBlacklistedals permanente Sperre,MailboxEmployee.aliasPermissionsals Per-User-Permission-Map. Quelle: ca. 20 FE-Commits + 9 BE-Commits zwischen 17.–21.05. - 2026-05-26 (Welle 149): Riesige Welle der Mail-Modul-Modernisierung. Signatur-Editor mit drei Layout-Varianten und Render-Zeit-Personalisierung. Phishing-AI mit
aiScamScore/aiScamReasonsund Warnboxen. Bidirektionaler MS↔SC State-Sync via Graph-Webhooks (siehe Konzept). Auto-Erledigt beim Antworten im Thread. Smart-Folder-Bulk-Aktionen (mark-folder-read/handled/unread). Realkosten-Anzeige ab 10 Mails / 5 Tage. Alias-Switcher in der Sidebar. Gravatar + EmailAvatar mit DSGVO-Opt-In. Compliance-Whitelist für Vehicle-Recipient. Compose-Redesign mit TipTap-BubbleMenu, Bulk-Toolbar, Tastatur-Shortcuts (/,?,y,u,⌘↵), Right-Click-Aktionen. Orphan-Cleanup + Archive-Folder. Quelle: FE765c2b90,d524b351,6581d2b4+ BE903df669,8a48cadb,8d8968d8,ee260713,f9e22872+ Workermicrosoft-subscription-renewal.worker.ts.