E-Mail-Ordner-Triage als offenen Punkt in TODO.md skizzieren
CI / build-and-test (push) Canceled after 0s

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-30 22:55:57 +02:00
co-authored by Claude Sonnet 5
parent 9dce6576e2
commit 28469bf547
+43 -20
View File
@@ -2334,27 +2334,50 @@ CSV-Exports der Auswertung (6.3.3) über die gemeinsame Export-Infrastruktur aus
Mail (eM Client gegen ein schlecht konfiguriertes Open-Xchange-"Fake-Exchange", echtes
Outlook/EWS funktioniert dort nicht zuverlässig — Open-Xchange spricht aber Standard-IMAP).
Ziel ist **keine** vollwertige Mail-Client-Funktion in LehrerApp (kein Compose/Reply, keine
Ordnerverwaltung, kein Postfach-weites Lesen), sondern eine schmale Brücke: Der Nutzer legt
in eM Client einen Ordner an (z.B. "→LehrerApp") und verschiebt dorthin manuell, was eine
Aktion in der Schule braucht. LehrerApp verbindet sich **nur read-only per IMAP** und
**nur mit diesem einen Ordner** (kein `DELETE`/`STORE`/`MOVE` auf dem Server), zeigt die
Mails dort an (Betreff/Absender/Datum/Textvorschau) und bietet pro Mail "→ Termin anlegen"
/ "→ Aufgabe anlegen" (öffnet die bestehenden Dialoge aus 6.1.2 bzw. Kapitel 4, vorbefüllt
mit Betreff als Titel). Als "bearbeitet" markierte Mails verschwinden nur lokal aus der
LehrerApp-Ansicht (Merkliste bereits gesehener IMAP-UIDs) — das tatsächliche Verschieben
zurück in Posteingang/Archiv bleibt bewusst manuelle Aufgabe des Nutzers in eM Client, damit
LehrerApp ganz ohne Schreibrechte auf dem Postfach auskommt.
allgemeine Ordnerverwaltung, kein Postfach-weites Lesen), sondern eine schmale Brücke: Der
Nutzer legt in eM Client einen Ordner an (z.B. "→LehrerApp") und verschiebt dorthin manuell,
was eine Aktion in der Schule braucht. LehrerApp verbindet sich per IMAP **ausschließlich
mit diesem einen Ordner plus einem festgelegten Archiv-Zielordner** — keine anderen Ordner
werden je adressiert, insbesondere nicht der Posteingang. Zeigt die Mails im Triage-Ordner
an (Betreff/Absender/Datum/Textvorschau) und bietet pro Mail "→ Termin anlegen" /
"→ Aufgabe anlegen" (öffnet die bestehenden Dialoge aus 6.1.2 bzw. Kapitel 4, vorbefüllt mit
Betreff als Titel). Nach dem Anlegen verschiebt LehrerApp die Mail automatisch in den
Archiv-Ordner (`UID MOVE`, RFC 6851; falls vom Open-Xchange-Server nicht unterstützt:
Fallback `COPY` + `\Deleted`-Flag + `EXPUNGE`, jeweils nur innerhalb des Triage-Ordners) —
genau der manuelle "Mail raussuchen und archivieren"-Schritt entfällt damit. Echtes Löschen
bleibt eine separate, bewusst zusätzliche Aktion (eigener Button, nicht automatisch beim
Archivieren mitgemacht).
- **Architektur-Vorbild:** wie `LehrerApp.WebUntis` ein eigenständiger, serverunabhängiger
Client — neues `LehrerApp.Mail`-Projekt (IMAP-Verbindung + Nachrichtenliste, z.B. via
`MailKit`, Eintrag in `Directory.Packages.props`), Desktop bindet es analog zu
`LehrerApp.WebUntis` direkt ein. Zugangsdaten (IMAP-Host/Port/Nutzer/Passwort, Ordnername)
dürfen wie WebUntis-Zugangsdaten **nicht** über `LehrerApp.Api` laufen — rein lokal, gleiches
Einstellungsfeld-Muster wie die WebUntis-URL (Kapitel 12).
- **Offen:** Passwort-Speicherung (OS-Credential-Store vs. verschlüsselt in den lokalen
Settings, wie es die übrigen gespeicherten Zugangsdaten der App bereits handhaben — dort
nachsehen statt neu entscheiden); Poll-Intervall; ob eine Mail-Vorschau nur Text oder auch
einfaches HTML rendern soll; Verhalten bei Anhängen (zunächst vermutlich ignorieren, nur
Text/Metadaten).
Client — neues `LehrerApp.Mail`-Projekt (IMAP-Verbindung + Nachrichtenliste + Move/Delete,
via `MailKit` — .NET hat kein natives IMAP in der BCL, `System.Net.Mail` deckt nur SMTP ab;
MailKit ist der De-facto-Standard, MIT-lizenziert, Eintrag in `Directory.Packages.props`),
Desktop bindet es analog zu `LehrerApp.WebUntis` direkt ein. Zugangsdaten
(IMAP-Host/Port/Nutzer/Passwort, Triage- und Archiv-Ordnername) dürfen wie
WebUntis-Zugangsdaten **nicht** über `LehrerApp.Api` laufen — rein lokal, gleiches
Einstellungsfeld-Muster wie die WebUntis-URL (Kapitel 12). Passwort wird lokal verschlüsselt
abgelegt (Nutzerentscheid: gleiches Bedrohungsmodell wie eM Client selbst — wer lokal an die
Zugangsdaten kommt, hätte auch direkten Zugriff auf das Mailprogramm), kein separater
OS-Credential-Store nötig. Der Postfach-Bereich (Navigationspunkt, Triage-Ansicht) bleibt in
der UI komplett verborgen, bis IMAP-Zugangsdaten hinterlegt sind — gleiches
Sichtbarkeits-/DI-Registrierungsmuster wie `SyncEngine`/`SnapshotService`, die laut
`AppBootstrapper.LoadServerUrl` nur bei konfigurierter Server-URL überhaupt registriert
werden.
- **Mehrgeräte-Fall:** Ein aus einer Mail erzeugter `WorkTask`/Termin synct wie jedes andere
Objekt ganz normal über den bestehenden Sync-Layer zu allen Geräten (kein Zusatzaufwand,
siehe die `OnChange`-Begründung im Nachtrag oben). Es fehlt nur der Rückkanal: das
tatsächliche Verschieben/Löschen der Mail kann nur das Gerät ausführen, das selbst IMAP-
Zugangsdaten zum *gleichen* Postfach hinterlegt hat. Dafür trägt der `WorkTask` ein neues,
nicht-geheimes Herkunftsfeld (z.B. `SourceMailAccount` = IMAP-Nutzername/Adresse,
`SourceMailFolder`, `SourceMailUid`) — synct automatisch mit. Jeder Client vergleicht dieses
Feld beim Anzeigen mit seiner eigenen lokalen IMAP-Konfiguration: nur bei Übereinstimmung
wird der "Postfach archivieren"-Button überhaupt angezeigt; ohne passende (oder ganz ohne)
lokale Zugangsdaten sieht der Task nur einen Hinweis "stammt aus Mail auf …", aber keine
ausführbare Aktion. Verhindert, dass ein Gerät ohne die richtigen Zugangsdaten versucht, auf
ein Postfach zuzugreifen, das es gar nicht kennt.
- **Offen:** Poll-Intervall; ob `UID MOVE` vom Open-Xchange-Server tatsächlich unterstützt wird
(vorher gegen den echten Server prüfen, sonst greift der Fallback); ob eine Mail-Vorschau nur
Text oder auch einfaches HTML rendern soll; Verhalten bei Anhängen (zunächst vermutlich
ignorieren, nur Text/Metadaten).
**Nachtrag — Pädagogische Klassen-Aufgaben (Nutzer-Feedback):** Wunsch nach einer zweiten,
"weniger arbeitszeitrelevant als pädagogisch" gedachten Art von Todo-Item (Beispiele: