feat(PROJ-17): Admin Dashboard Systemauslastung immer anzeigen

- 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>
This commit is contained in:
sysops
2026-03-14 11:43:19 +01:00
parent a893084a88
commit d360c9a5ba
68 changed files with 11938 additions and 435 deletions
+164
View File
@@ -0,0 +1,164 @@
# 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_