d360c9a5ba
- Systemauslastungs-Sektion wird immer gerendert (nicht nur bei Erfolg) - Fehlermeldung wenn /api/admin/system/stats nicht erreichbar ist - Feature-Status auf In Review gesetzt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
6.5 KiB
6.5 KiB
PROJ-4: E-Mail-Import: SMTP-Eingang (primär via BCC)
Status: In Progress
Created: 2026-03-12 Last Updated: 2026-03-12
Hinweis
Dies ist der primäre Eingangsweg. archivmail enthält einen eingebetteten SMTP-Daemon, der ausschließlich E-Mails empfängt – kein Versand, keine Weiterleitung, kein MTA. Postfix (oder ein anderer Mailserver) wird per BCC-Mapping oder Always-BCC-Regel so konfiguriert, dass er eine Kopie jeder E-Mail an archivmails SMTP-Daemon zustellt.
Absender → Postfix (MTA) → Empfänger
│
└── BCC/always_bcc → archivmail SMTP-Daemon (nur Empfang)
│
▼
Storage Coordinator
IMAP und EML/MBOX-Upload sind sekundäre/ergänzende Methoden (z.B. für Altbestände).
Dependencies
- Requires: PROJ-5 (Speicherung & Indexierung) – eingehende E-Mails werden gespeichert
- Kein Login nötig für den Empfang – SMTP-Eingang läuft unabhängig vom HTTP-Server
User Stories
- Als Mailserver möchte ich E-Mails per BCC an archivmail zustellen, damit diese automatisch archiviert werden.
- Als Admin möchte ich den eingebetteten SMTP-Server konfigurieren (Port, TLS, erlaubte Absender-IPs).
- Als Admin möchte ich festlegen, welche Absender-IPs/Domains akzeptiert werden, damit nur der eigene Mailserver zustellen darf.
- Als System möchte ich eingehende E-Mails sofort nach Empfang indexieren, damit sie innerhalb von Sekunden durchsuchbar sind.
- Als Admin möchte ich den Status des SMTP-Empfängers sehen (läuft, Port, letzte empfangene E-Mail).
Acceptance Criteria
- Eingebetteter SMTP-Server lauscht auf konfigurierbarem Port (Standard: 25 oder 2525)
- TLS/STARTTLS-Unterstützung für verschlüsselte Übertragung
- IP-Allowlist: nur eingetragene Mailserver-IPs dürfen zustellen (Standard: nur localhost/127.0.0.1)
- Optionale Domain-Allowlist als zusätzliche Prüfebene
- E-Mails werden sofort nach Empfang gespeichert und indexiert
- SMTP-Quittierung (250 OK) erst nach erfolgreicher Speicherung
- Admin-UI zeigt: Port, TLS-Status, Anzahl empfangener E-Mails, letzte Aktivität
- Fehlerhafte/abgelehnte E-Mails werden geloggt
Edge Cases
- E-Mail ohne Absender (Envelope-From leer) → annehmen aber markieren
- Sehr große E-Mail (> 50 MB) → konfigurierbare Maximalgröße, Ablehnung mit 552-Fehlercode
- SMTP-Server-Port bereits belegt → klare Fehlermeldung beim Start
- Parallele Verbindungen (viele E-Mails gleichzeitig) → Connection-Pooling
- Duplicate Message-ID → überspringen wie bei anderen Import-Methoden
Technical Requirements
- RFC 5321 (SMTP) konformer reiner Empfänger – kein SMTP-Versand, keine Queue, kein Relay
- Kein SMTP AUTH – Zugang ausschließlich über IP-Allowlist (nur Postfix-IP eingetragen)
- Maximale Nachrichtengröße konfigurierbar (Standard: 50 MB)
- Startet als eigenständiger Goroutine/Service neben dem HTTP-Server
- Postfix-Konfiguration (außerhalb von archivmail, Dokumentation in README):
always_bcc = archiv@archivmail-hostin Postfixmain.cf, oder- Sender/Recipient BCC-Maps für granulare Kontrolle
Tech Design (Solution Architect)
Systemübersicht
Absender → Postfix (MTA) → Empfänger (normale Zustellung)
│
└── always_bcc / BCC-Map
│
▼ SMTP (Port 2525)
archivmail SMTP-Daemon
(nur Empfang, kein Versand)
│
▼
Storage Coordinator (PROJ-5)
(speichern + indexieren)
Komponentenstruktur
archivmail (Go-Binary)
│
├── HTTP-Server (Web-GUI + API)
│
└── SMTP-Daemon ← startet parallel zum HTTP-Server
├── TCP Acceptor ← lauscht auf Port 2525 (konfigurierbar)
├── IP Allowlist Guard ← prüft Absender-IP vor SMTP-Dialog
├── Session Handler (pro Verbindung, eigene Goroutine)
│ ├── TLS/STARTTLS Handler ← optional, Zertifikat aus config.yml
│ └── Size Limiter ← bricht DATA-Phase bei Überschreitung ab
└── Handoff → Storage Coordinator ← übergibt E-Mail nach vollständigem Empfang
SMTP-Dialogfluss
Postfix
│ TCP-Verbindung auf Port 2525
▼
IP Allowlist Guard
├─ IP unbekannt → Verbindung trennen (kein SMTP-Dialog)
└─ IP erlaubt → weiter
│
▼
220 archivmail SMTP ready
│
EHLO mail.firma.de
250 OK (kein AUTH angeboten – reiner Empfänger)
│
MAIL FROM: <absender@firma.de>
250 OK
│
RCPT TO: <archiv@archivmail>
250 OK
│
DATA
354 Start input
… E-Mail-Inhalt … (max. 50 MB)
.
│
├─ Zu groß → 552 Message size exceeds limit
├─ Duplikat (Message-ID) → 250 OK (still, kein Fehler – Postfix soll nicht retrying)
└─ Neu → Storage Coordinator → verschlüsselt speichern + indexieren
│
▼
250 OK ← erst nach erfolgreicher Speicherung
│
QUIT
Technische Entscheidungen
| Entscheidung | Begründung |
|---|---|
| Reiner Empfänger, kein MTA | archivmail ist kein Mailserver – keine ausgehende Queue, kein Relay-Risiko, kein Open-Relay |
| Kein SMTP AUTH | Vertrauen basiert auf IP, nicht auf Passwort – Postfix und archivmail laufen im gleichen Netz |
| 250 OK bei Duplikat | Postfix würde bei Fehler die Mail in die Retry-Queue stellen – sinnlos, da Duplikat bereits archiviert |
| 250 OK erst nach Speicherung | Solange Postfix keine Bestätigung hat, behält er die Mail und versucht erneut – kein Datenverlust |
| Port 2525 | Port 25 erfordert root-Rechte; 2525 läuft als unprivilegierter archivmail-Systembenutzer |
| Eine Goroutine pro Session | Viele parallele Verbindungen ohne Blocking; jede Session ist isoliert |
Postfix-Konfiguration (Dokumentation, außerhalb von archivmail)
# /etc/postfix/main.cf – einfachste Variante (alle Mails)
always_bcc = archiv@archivmail-host
# Oder granular per Sender-BCC-Map:
# sender_bcc_maps = hash:/etc/postfix/sender_bcc
# empfänger@firma.de archiv@archivmail-host
Go-Abhängigkeiten
| Paket | Zweck |
|---|---|
github.com/emersion/go-smtp |
Eingebetteter SMTP-Daemon (RFC 5321, nur Empfang) |
crypto/tls |
TLS/STARTTLS (Go Stdlib) |
net |
IP-Prüfung (Go Stdlib) |
QA Test Results
To be added by /qa
Deployment
To be added by /deploy