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>
165 lines
6.5 KiB
Markdown
165 lines
6.5 KiB
Markdown
# 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-host` in Postfix `main.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_
|