Files
archivmail/features/PROJ-4-import-smtp.md
T
sysops 7c29ee88bd docs: vollständige README, PROJ-2 Web-Upload, PROJ-19 Mailpiler-Migration
README.md:
- Vollständige Dokumentation aller implementierten Funktionen
- Konfigurationsreferenz, Installation, Systemd, REST-API-Übersicht
- In-Progress-Features klar gekennzeichnet

PROJ-2 (EML/MBOX Web-Upload):
- POST /api/admin/upload – Multipart-Upload mit Hintergrund-Job
- GET /api/admin/upload/{jobID}/progress – Polling
- Admin-Tab "Import" mit Drag-and-Drop, Fortschrittsbalken, Abschlussbericht

PROJ-19 (Mailpiler Migration):
- archivmail import-piler mit Methoden: pilerexport | direct | auto
- Direct: AES-256-CBC + zlib mit defensiven Fallbacks
- pilerexport: Wrapper um mailpilers Export-Tool

Status-Updates: PROJ-3, PROJ-4, PROJ-6, PROJ-7, PROJ-10, PROJ-11 → Deployed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 09:23:34 +01:00

165 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PROJ-4: E-Mail-Import: SMTP-Eingang (primär via BCC)
## Status: Deployed
**Created:** 2026-03-12
**Last Updated:** 2026-03-17
## 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_