- Webhook route and Gitea integration - IMAP service and Nextcloud/Porkbun setup docs - Settings UI improvements and API updates - SSH/Webhook fix prompt for emailsorter.webklar.com - Bootstrap, config and AI sorter updates
10 KiB
10 KiB
Implementierungsplan: IMAP / Porkbun / Nextcloud
Plan, um EmailSorter um einen IMAP-Provider (z. B. Porkbun) zu erweitern. Dann funktioniert die Sortierung auch für Postfächer, die in Nextcloud Mail genutzt werden.
Übersicht
| Phase | Inhalt | Aufwand (grobe Schätzung) |
|---|---|---|
| 1 | IMAP-Bibliothek + Service-Grundgerüst | 1–2 h |
| 2 | Datenbank + Connect-Route für IMAP | 1 h |
| 3 | Sortier-Logik für IMAP (Ordner statt Labels) | 2–3 h |
| 4 | Frontend: IMAP-Verbindung anlegen | 1–2 h |
| 5 | Testen, Feinschliff, Doku | 1 h |
Phase 1: IMAP-Bibliothek und Service
Ziel: Backend kann sich per IMAP (z. B. Porkbun) verbinden, INBOX auflisten und E-Mails lesen.
1.1 Abhängigkeit hinzufügen
- Datei:
server/package.json - Aktion: Dependency
imapflowhinzufügen (moderner IMAP-Client für Node, SSL-Support). - Befehl:
npm install imapflowim Ordnerserver/.
1.2 Neuer Service
- Datei (neu):
server/services/imap.mjs - Inhalt (Kern-Interface):
- Konstruktor:
ImapService({ host, port, secure, user, password })– z. B. für Porkbun:host: 'imap.porkbun.com', port: 993, secure: true. - connect() – Verbindung aufbauen (login).
- listEmails(maxResults, fromSeq?) – Nachrichten aus INBOX (z. B. per FETCH ENVELOPE), Rückgabe:
{ messages: [{ id, uid, ... }], nextSeq }. - getEmail(messageId) bzw. batchGetEmails(ids) – eine bzw. mehrere Mails laden, Rückgabe-Format wie Gmail/Outlook:
{ id, headers: { from, subject }, snippet }. - close() – Verbindung sauber trennen (LOGOUT).
- Konstruktor:
- Hinweis: IMAP nutzt oft UID oder Sequence Number als „id“; einheitlich als
idnach außen geben (String), damit die Sortier-Route wie bei Gmail/Outlook arbeitet.
1.3 Akzeptanz Phase 1
- Ein kleines Test-Script (z. B.
server/scripts/test-imap.mjs) oder ein temporärer Route-Handler liest Umgebungsvariablen (IMAP_HOST, IMAP_PORT, IMAP_USER, IMAP_PASSWORD), bautImapServiceauf, ruftlistEmails(10)undgetEmail(...)auf und loggt das Ergebnis. Keine Credentials im Repo – nur.env/ Umgebungsvariablen.
Phase 2: Datenbank und Connect-Route
Ziel: Ein neuer Account-Typ „imap“ kann angelegt werden; Zugangsdaten werden gespeichert.
2.1 Datenbank (Appwrite)
- Datei:
server/bootstrap-v2.mjs(oder separates Migrations-Script). - Aktion: In der Collection
email_accountsoptionale Attribute anlegen:imapHost(String, optional)imapPort(Integer, optional)imapSecure(Boolean, optional)
- Alternative (einfacher für nur Porkbun): Keine neuen Felder; Host/Port im Code fest (imap.porkbun.com, 993). Dann nur
email+ Passwort nötig; Passwort in bestehendem FeldaccessTokenspeichern (semantisch „geheimer Token für IMAP“). Für spätere andere IMAP-Server die optionalen Felder nachziehen.
2.2 Connect-Route erweitern
- Datei:
server/routes/email.mjs - Route:
POST /api/email/connect(bzw. die Route, die Accounts anlegt). - Aktionen:
- Im Validierungs-Schema
providerum'imap'erweitern: z. B.rules.isIn('provider', ['gmail', 'outlook', 'demo', 'imap']). - Body für IMAP: mindestens
userId,provider: 'imap',email,password(oderaccessTokenals Passwort). Optional:imapHost,imapPort,imapSecure. - Wenn
provider === 'imap':- Host/Port/Secure aus Body oder Default (Porkbun: imap.porkbun.com, 993, true).
- Passwort nicht loggen; in DB in
accessToken(oder neuem Feld) speichern. - Optional: einmalig
ImapServiceinstanziieren,connect()+listEmails(1)aufrufen; bei Erfolg Account anlegen, sonst Fehler zurückgeben („Ungültige Anmeldedaten“).
- Account-Dokument anlegen mit
provider: 'imap',email,accessToken(= Passwort), ggf.imapHost,imapPort,imapSecure.
- Im Validierungs-Schema
2.3 Middleware/Validierung
- Datei:
server/middleware/validate.mjs(falls dort Regeln liegen) oder direkt in der Route. - Aktion: Für IMAP ggf. zusätzliche Felder erlauben:
imapHost,imapPort,imapSecure,password(oder wie du das Feld nennst).
2.4 Akzeptanz Phase 2
- Per API-Client (Postman/curl) oder Frontend: POST mit
provider: 'imap',email,password(und optional Host/Port) an/connectsenden. Erwartung: 201, Account in Appwrite mitprovider: 'imap'. Bei falschem Passwort: 4xx mit verständlicher Meldung.
Phase 3: Sortier-Logik für IMAP
Ziel: POST /api/email/sort funktioniert für Accounts mit provider === 'imap': E-Mails werden per KI kategorisiert und in IMAP-Ordner verschoben.
3.1 Ordner-Mapping
- Konzept: Kategorien (z. B.
vip,promotions,newsletters,archive) auf Ordner-Namen mappen. Z. B.:archive/archive_read→ OrdnerArchiveoderEmailSorter/Archivepromotions→PromotionsoderEmailSorter/Promotions- usw.
- Datei: Entweder in
server/services/imap.mjs(FunktiongetFolderNameForCategory(category)) oder inserver/services/ai-sorter.mjs/ Config. Einheitliche Liste (z. B. ObjektcategoryToFolder) verwenden.
3.2 IMAP-Service erweitern
- Datei:
server/services/imap.mjs - Neue Methoden:
- ensureFolder(folderName) – Ordner anlegen (CREATE), falls nicht vorhanden; Fehler „existiert bereits“ ignorieren.
- moveToFolder(messageId, folderName) – Nachricht aus INBOX in den Ordner verschieben (MOVE oder COPY + DELETE aus INBOX).
- Optional: markAsRead(messageId) – falls „archive_read“ = verschieben + als gelesen markieren.
3.3 Sortier-Route erweitern
- Datei:
server/routes/email.mjs - Stelle: Dort, wo
account.provider === 'gmail'und=== 'outlook'abgefragt werden (und Demo). - Aktion: Neuen Block
else if (account.provider === 'imap')hinzufügen:ImapServiceaus Account-Daten instanziieren (host, port, secure, user = email, password = accessToken).connect().- In einer Schleife (analog Gmail/Outlook):
listEmails(batchSize, nextSeq)→ Liste von Nachrichten.batchGetEmails(ids)→ From, Subject, Snippet.- Für jede E-Mail: KI-Kategorie ermitteln (bestehender
AISorterService), dannensureFolder(categoryToFolder[category])undmoveToFolder(id, folderName). - Bei „archive_read“ ggf. zusätzlich als gelesen markieren.
- Statistiken aktualisieren (wie bei Gmail/Outlook).
close()aufrufen.
- Fehlerbehandlung: Bei IMAP-Fehlern (z. B. „Invalid credentials“) sinnvolle Meldung zurückgeben und ggf. Account als „reconnect nötig“ markieren.
3.4 Akzeptanz Phase 3
- Ein IMAP-Account ist verbunden. Aufruf von
POST /api/email/sortmituserIdundaccountId. Erwartung: E-Mails aus INBOX werden kategorisiert und in die richtigen Ordner verschoben; Response enthält z. B.sortedCountund Kategorie-Statistiken. In Nextcloud Mail (oder anderem IMAP-Client) erscheinen die neuen Ordner und verschobenen Mails.
Phase 4: Frontend – IMAP verbinden
Ziel: Nutzer können im UI „Anderes Postfach (IMAP)“ wählen und E-Mail + Passwort eingeben.
4.1 Verbindungs-Flow
- Datei(en): Dort, wo heute Gmail/Outlook/Demo angeboten werden (z. B. Setup, Settings, „E-Mail verbinden“).
- Aktion:
- Neue Option „IMAP / anderes Postfach“ (oder „Porkbun / eigenes Postfach“).
- Beim Klick: Formular anzeigen mit:
- E-Mail (Pflicht)
- Passwort / App-Passwort (Pflicht, Typ Passwort)
- Optional (z. B. für Power-User): Host, Port, SSL (Checkbox); Defaults: imap.porkbun.com, 993, SSL an.
- Submit: POST an Backend (z. B.
/api/email/connect) mitprovider: 'imap',email,password, optionalimapHost,imapPort,imapSecure. - Bei Erfolg: Erfolgsmeldung, Account-Liste aktualisieren. Bei Fehler: Meldung anzeigen (z. B. „Anmeldung fehlgeschlagen – prüfe E-Mail und Passwort“).
4.2 API-Client (Frontend)
- Datei: z. B.
client/src/lib/api.ts - Aktion: Methode
connectImapAccount(userId, { email, password, imapHost?, imapPort?, imapSecure? })hinzufügen, diePOST /api/email/connectmit diesen Daten aufruft.
4.3 Akzeptanz Phase 4
- Im UI „IMAP verbinden“ auswählen, E-Mail + Passwort eingeben, absenden. Account erscheint in der Account-Liste. Danach „Sortieren“ auslösbar und funktioniert wie in Phase 3.
Phase 5: Testen und Doku
- Manuell: Mit einem echten Porkbun-Account (oder anderem IMAP) verbinden, Sortierung ausführen, in Nextcloud prüfen, ob Ordner und Mails stimmen.
- Sicherheit: Prüfen, dass Passwörter nirgends geloggt werden und nicht im Frontend gespeichert werden.
- Doku:
docs/setup/IMAP_NEXTCLOUD_PORKBUN.mdggf. um „Konfiguration Porkbun“ und „Troubleshooting“ ergänzen (z. B. App-Passwort, 2FA).
Kurz-Checkliste
- Phase 1:
imapflowinstalliert,server/services/imap.mjsmit connect, listEmails, getEmail, close; Test mit .env-Credentials. - Phase 2: Appwrite
email_accountsggf. um IMAP-Felder erweitert; Connect-Route akzeptiertimapund speichert Zugangsdaten; Test: Account per API anlegen. - Phase 3: Ordner-Mapping; ImapService: ensureFolder, moveToFolder; Sortier-Route: Block für
provider === 'imap'; Test: Sortierung für IMAP-Account. - Phase 4: Frontend-Option „IMAP“, Formular E-Mail/Passwort, API-Anbindung; Test: End-to-End Verbindung + Sortierung aus UI.
- Phase 5: Manueller Test mit Porkbun/Nextcloud; Sicherheits-Check; Doku aktualisiert.
Dateien-Übersicht
| Aktion | Datei |
|---|---|
| Neu | server/services/imap.mjs |
| Neu (optional) | server/scripts/test-imap.mjs |
| Ändern | server/package.json (imapflow) |
| Ändern | server/bootstrap-v2.mjs (optional: IMAP-Attribute) |
| Ändern | server/routes/email.mjs (provider imap, connect + sort) |
| Ändern | server/middleware/validate.mjs (falls nötig) |
| Ändern | Frontend: Connect-UI (Setup/Settings) + client/src/lib/api.ts |
| Ändern | docs/setup/IMAP_NEXTCLOUD_PORKBUN.md (Feinschliff) |
Wenn du mit Phase 1 startest, reicht zunächst: imapflow einbinden und imap.mjs mit connect + listEmails + getEmail implementieren und lokal mit Porkbun testen.