Initial Email-Forwarder scaffold
This commit is contained in:
commit
91e52aecd0
22 changed files with 1007 additions and 0 deletions
115
Codex-Briefing.md
Normal file
115
Codex-Briefing.md
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
# Codex-Briefing — Email-Forwarder
|
||||
|
||||
Du baust ein Go-Single-Binary im Hausstil (wie WatchDove): `main.go` als
|
||||
Orchestrator, nummerierte `backend/NN-*.go`, Server-gerendertes HTML + HTMX,
|
||||
`config.json`, SQLite via `modernc.org/sqlite` (kein cgo). Das Gerüst steht;
|
||||
fülle die `// TODO Codex`-Stellen. **Lies zuerst `Projektbeschreibung.md` – die
|
||||
5 harten Regeln sind bindend.**
|
||||
|
||||
## Bibliotheken (lean, keine Lawine)
|
||||
|
||||
- IMAP: `github.com/emersion/go-imap/v2` (+ `imapclient`)
|
||||
- Parsen (Message-ID, Header, Text/HTML für Viewer): `github.com/emersion/go-message`
|
||||
- SQLite: `modernc.org/sqlite`
|
||||
- POP3-Fallback: `github.com/knadh/go-pop3`
|
||||
- SMTP-Weiterleiten: `net/smtp` (stdlib) — keine Extra-Dependency
|
||||
|
||||
`go mod tidy` + `go mod vendor` (Offline-Bunker, wie im Template).
|
||||
|
||||
## Modul-Landkarte
|
||||
|
||||
| Datei | Inhalt |
|
||||
|---|---|
|
||||
| `main.go` | Flags (`--run`, `--watch`), LoadConfig→ConnectDB→InitAuth, Web oder CLI |
|
||||
| `backend/00-router.go` | Routen + `renderShell` (Outlook-2013-Dreispalter) — **da steht schon das Layout** |
|
||||
| `backend/01-config.go` | `config.json` (App + Forward-SMTP). Konten NICHT hier, sondern DB |
|
||||
| `backend/02-database.go` | Schema + Account-CRUD + `copied`-Cache (Idempotenz) |
|
||||
| `backend/03-auth.go` | Login + `AuthMiddleware` |
|
||||
| `backend/04-imap-source.go` | Quelle: Ordnerbaum + Fetch `BODY[] FLAGS INTERNALDATE` |
|
||||
| `backend/05-imap-target.go` | Ziel: `EnsureFolder` + `Append` (Flags + INTERNALDATE) |
|
||||
| `backend/06-mbox.go` | mbox schreiben (Umzug) **und** lesen (Viewer) |
|
||||
| `backend/07-migrate.go` | Motor: pro Konto/Ordner/Mail, Dedup, Doppel-Write, Fortschritt |
|
||||
| `backend/08-viewer.go` | mbox im Browser: Liste, Lesen, Weiterleiten |
|
||||
| `backend/09-smtp.go` | SMTP nur fürs Weiterleiten |
|
||||
| `backend/10-pop3.go` | POP3-Fallback-Quelle (nur INBOX, nie DELE) |
|
||||
|
||||
## DB-Schema (SQLite)
|
||||
|
||||
```
|
||||
accounts(id, name,
|
||||
src_host, src_port, src_security, src_insecure, src_user, src_pass, src_proto,
|
||||
dst_host, dst_port, dst_security, dst_insecure, dst_user, dst_pass,
|
||||
mbox_dir, active)
|
||||
folder_map(id, account_id, src_folder, dst_folder) -- optional, Vorrang vor Rollen-Automatik
|
||||
copied(account_id, folder, message_id UNIQUE) -- Delta-Cache
|
||||
jobs(id, account_id, started, finished, total, done, errors, state)
|
||||
```
|
||||
|
||||
`src_security`/`dst_security` = `"tls"` | `"starttls"` | `"none"`.
|
||||
`src_insecure`/`dst_insecure` = ungültige Zerts akzeptieren.
|
||||
|
||||
## Der Umzugs-Kern (07-migrate.go), Schritt für Schritt
|
||||
|
||||
1. Quelle öffnen: `src_proto=imap` → `OpenIMAPSource`, sonst `OpenPOP3Source`.
|
||||
2. `Folders()` → rekursiver Ordnerbaum.
|
||||
3. Pro Ordner: Zielordner via `MapSourceToTarget` (11-folders.go) bestimmen —
|
||||
Rollen-Zuordnung gegen die vorhandenen Ziel-Ordner (keine Dubletten),
|
||||
Trenner umhängen, `folder_map` als Override. Dann `EnsureFolder`.
|
||||
4. `Fetch(folder)` streamend. Pro Mail: `AlreadyCopied(id,folder,msgID)`?
|
||||
→ ja: überspringen. Nein: **beide** schreiben — `TargetMailbox.Append`
|
||||
(IMAP, mit Flags+INTERNALDATE) **und** `MboxWriter.Append` (lokal), dann
|
||||
`MarkCopied`. Fehler pro Mail zählen, nicht den ganzen Lauf abbrechen.
|
||||
5. `jobs` fortschreiben (Browser pollt `/migrate/status` alle 3 s).
|
||||
6. `--watch`: Schleife mit Pause; dank `copied` kopiert jeder Durchlauf nur Neues.
|
||||
|
||||
## UI — Outlook 2013 (Vorlage)
|
||||
|
||||
Look sitzt schon in `frontend-js/dist/style.css` + `renderShell`:
|
||||
**Ribbon** (Outlook-Blau `#0072c6`) mit Reitern *Umzug · Postfächer · Betrachten
|
||||
· Einstellungen*, darunter **Dreispalter**: links Ordnerbaum (Konto → Ordner),
|
||||
Mitte Nachrichtenliste (ungelesen = fett blau), rechts Lesebereich; unten
|
||||
Statusleiste. Flach, Segoe UI, blaue Auswahlzeile `#cde6f7`. Panes per HTMX
|
||||
nachladen (`#tree` / `#list` / `#read`). Klassen stehen im CSS: `.tree-node`,
|
||||
`.msg-row(.unread/.active)`, `.read-*`, `.grid/.input/.btn`.
|
||||
|
||||
Reiter **Postfächer** = Konten-CRUD (Formular wie WatchDove `targetForm`, Quelle-
|
||||
und Ziel-Block, „Test"-Button prüft beide Logins). Reiter **Umzug** = Konten
|
||||
starten + Fortschritt. Reiter **Betrachten** = mbox-Viewer, im Lesebereich ein
|
||||
„Weiterleiten"-Button (öffnet Formular → `09-smtp.go`).
|
||||
|
||||
`frontend-js/dist/htmx.min.js` per Bun holen (wie Template) und mit einchecken.
|
||||
|
||||
## Sonderfälle — die drei Umzugs-Fallen (zwingend)
|
||||
|
||||
1. **Unverschlüsselte Alt-Provider.** Verbinden nach `src_security`:
|
||||
`tls`=DialTLS (993), `starttls`=DialStartTLS (143), `none`=Dial (reiner
|
||||
Klartext). `src_insecure` → `tls.Config{InsecureSkipVerify:true}` für
|
||||
kaputte/selbstsignierte Zerts. Muss ohne TLS funktionieren — alte Hoster
|
||||
können oft nichts anderes. (04/05-imap-*.go, POP3 analog 110/995.)
|
||||
2. **Sonderzeichen in Ordnernamen.** IMAP-Ordner sind auf der Leitung
|
||||
modified-UTF-7 (`Gelöschte`→`Gel&APY-schte`). go-imap dekodiert/kodiert das —
|
||||
intern IMMER mit dem Klartext-Namen arbeiten, **nie doppelt kodieren**.
|
||||
Hierarchie-Trenner (`.` vs `/`) je Server aus LIST lesen und beim Umhängen
|
||||
übersetzen (`11-folders.go`).
|
||||
3. **Standardordner nicht doppeln.** `11-folders.go` bildet jeden Ordner auf
|
||||
eine Rolle ab (SPECIAL-USE `\Sent \Drafts \Junk \Trash \Archive`, sonst
|
||||
mehrsprachige Namensliste). `MapSourceToTarget` sortiert Gesendet/Entwürfe/
|
||||
Spam/Papierkorb/Archiv/Posteingang in den **vorhandenen** Rollen-Ordner des
|
||||
Ziels statt „Gesendete Objekte" **neben** „Gesendete Elemente" zu legen.
|
||||
Manuelles `folder_map` schlägt die Automatik.
|
||||
|
||||
## Sicherheit
|
||||
|
||||
Tool hält fremde IMAP-Passwörter und kann Mails senden. Default `bind=127.0.0.1`
|
||||
+ Login. Falls je remote (hinter Caddy): `/vadmin`-Mail-2FA-Muster aus dem
|
||||
Web-Deploy-Kit vorschalten. `config.json`/DB nie committen (`.gitignore` steht).
|
||||
|
||||
## Fertig-Kriterien (Durchstich zuerst)
|
||||
|
||||
1. **Durchstich:** ein Konto, nur `INBOX`, Quelle→Ziel-`APPEND` + mbox,
|
||||
Message-ID-Dedup, zweimal laufbar ohne Dubletten.
|
||||
2. Alle Ordner rekursiv + `EnsureFolder` im Ziel.
|
||||
3. Konten-CRUD + Test-Button im Browser.
|
||||
4. Viewer (Liste/Lesen) + Weiterleiten.
|
||||
5. `--watch`-Delta-Schleife.
|
||||
6. Optional: POP3-Fallback.
|
||||
Loading…
Add table
Add a link
Reference in a new issue