# Mail-Graveyard — bauen & benutzen ## 1. Bauen ```sh ./compile.sh ``` Holt htmx ins `frontend-js/dist`, macht `go mod tidy` und baut ein statisches Binary für Linux **und** Windows (`mail-graveyard` / `mail-graveyard.exe`). ## 2. Konfig ```sh cp config.json.example config.json ``` `config.json` (bleibt lokal, ist ge-`.gitignore`-t) setzt nur App-Sachen: Bind/Port, Admin-Login, DB-Pfad, mbox-Wurzel, optionale `mbox_compression` (`none` oder `zstd`) und das **Forward-SMTP** (nur fürs manuelle Weiterleiten aus dem Viewer). Die **Umzugs-Konten** legst du im Browser an, nicht hier. ## 3. Starten (Web) ```sh ./mail-graveyard --init-db # nur beim ersten Start: DB aus db_path anlegen ./mail-graveyard # danach normal, lauscht auf 127.0.0.1:8087 ``` Fehlt die DB-Datei spaeter, startet Mail-Graveyard bewusst nicht mehr still mit einer leeren Datenbank. Dann `db_path` pruefen oder nur fuer eine echte Neuinstallation erneut `--init-db` benutzen. Browser auf `http://127.0.0.1:8087`, mit Admin-Login aus `config.json`. Oberfläche im Outlook-2013-Look: Reiter **Postfächer** (Konten anlegen: Quelle alt → Ziel neu, Sicherheits-Modus `tls`/`starttls`/`none`, „Test" prüft beide Logins), Reiter **Umzug** (starten + Fortschritt), Reiter **Betrachten** (lokale mbox durchsehen, einzeln weiterleiten). ## 4. Starten (CLI — Cutover) Ohne Web, z. B. als Cronjob oder Dauerlauf im Umzugsfenster: ```sh ./mail-graveyard --run all # einmalig alle Konten (Delta) ./mail-graveyard --run dr-gold --watch # ein Konto, Delta-Schleife bis Stop ``` Die kanonische Inhaltsidentitaet verhindert dabei doppelte **Schreibvorgaenge** in Archiv und Ziel. Der aktuelle Volllauf laedt trotzdem jede Quellmail erneut, bevor er deren Body-Hash pruefen kann. Grosse Konten deshalb bis zum UID-Delta-Watcher nicht in kurzen Intervallen als Dauerlauf starten. ## 5. Wartung ```sh ./mail-graveyard --reindex all ./mail-graveyard --dedup-target konto-name # Dry-Run ./mail-graveyard --dedup-target konto-name --apply # loescht Dubletten im Ziel ./mail-graveyard --snapshot /sicherungen/stand-2026-07-16 ./mail-graveyard --verify-snapshot /sicherungen/stand-2026-07-16 ``` `--reindex` baut den Archiv-Index fuer vorhandene mbox/mbox.zst-Dateien neu auf. `--dedup-target` ist bewusst ein Dry-Run, bis `--apply` gesetzt wird; Mails ohne Message-ID werden nie geloescht. `--snapshot` erzeugt zuerst per SQLite `VACUUM INTO` einen konsistenten DB-Stand. Anschliessend kopiert es aus jeder append-only mbox exakt das durch `MAX(file_offset+frame_len)` **dieses DB-Standes** belegte Praefix. Das Ziel muss neu sein und enthaelt `data/mail-graveyard.db`, `backup/...` sowie ein Manifest mit Grenzen und SHA-256-Pruefsummen. Ein Fehler hinterlaesst ein klar benanntes `.partial-*`-Verzeichnis und wird nie als fertiger Stand umbenannt. Die Datenbank wird wegen der enthaltenen Klartext-Zugangsdaten mit `0600` geschrieben; die Verifikation weist unter Linux weiter gefasste Rechte zurueck. `--verify-snapshot` veraendert weder Produktion noch Snapshot: Es prueft Manifest, Dateigroessen, SHA-256, SQLite-Integritaet, Stufenreihenfolge und den Identitaetsdigest. Danach kopiert es nur die Snapshot-DB in ein temporaeres Restore-Verzeichnis und reindiziert dort alle mbox-Dateien. Der Identitaetsdigest muss vor und nach dem Reindex gleich bleiben. Der lokale Snapshot ist nur die konsistente **Vorstufe** eines Backups. Er enthaelt Kontozugangsdaten und muss anschliessend verschluesselt auf einen raeumlich getrennten Datentraeger uebertragen werden. ## 6. Sicherheit Tool hält fremde IMAP-Passwörter und kann Mails senden → Default bind `127.0.0.1`. Falls remote nötig: hinter Caddy + `/vadmin`-Mail-2FA. `config.json` und `*.db` nie committen. Die Live-SQLite-Datei sowie ihre WAL-/SHM-Sidecars werden bei jedem Start auf `0600` gesetzt. Das gilt auch fuer weitere `*.db`, `*.db-wal` und `*.db-shm` direkt im konfigurierten Datenverzeichnis sowie fuer die Datenbank eines neu erzeugten Snapshots. Kann ein Dateisystem Unix-Rechte nicht abbilden (z. B. bestimmte exFAT-/CIFS-Mounts), startet das Werkzeug bewusst nicht: Zugangsdaten bleiben fail-closed statt unbemerkt lesbar. ## 7. Reihenfolge bei einem echten Umzug 1. Ziel-Postfächer beim neuen Hoster anlegen (`archiv-…`, `temp-…`). 2. Konten im Browser eintragen, „Test" grün. 3. `--run` laufen lassen, im **Betrachten**-Reiter / mbox stichprobenartig prüfen. 4. Während der Umstellung `--watch` für das Delta laufen lassen. 5. Domain portieren; danach zeigt der neue Hoster auf die Zielpostfächer.