Vollständiger POP3-Server von Grund auf implementiert, analog zum bestehenden IMAP-Server (ING-01): TCP-Listener mit einer Goroutine pro Verbindung, CRLF/Byte-Stuffing-sichere Response-Writer, Zustandsmaschine (Authorization/Transaction/Update), Kommandos USER, PASS, STAT, LIST, RETR, DELE, QUIT. Zentrale Designentscheidungen: - USER antwortet immer +OK (RFC-konform), Prüfung erst bei PASS - Fehlgeschlagene Anmeldung liefert für unbekannten Benutzer und falsches Passwort denselben generischen Text (keine Informationspreisgabe, Akzeptanzkriterium 3) - DELE markiert Nachrichten nur sitzungslokal; store.Delete wird strukturell ausschließlich in QUIT (Transaction -> Update) aufgerufen, wodurch ein Verbindungsabbruch ohne QUIT nichts endgültig löscht (Pflichtprüfung 3) Alle drei Pflichtprüfungen mit echten Nachweisen durchgeführt: Zustandsübergangs-Tests gegen realen TCP-Server, manuelle Session mit Python-Standardbibliothek poplib (echtes Transkript im Prüfprotokoll), automatisierter Test für DELE-ohne-QUIT. Zusätzlich: 20 parallele reale Sessions (Akzeptanzkriterium 1), vollständiger RETR+DELE+QUIT-Zyklus (Akzeptanzkriterium 2). go build/go vet/golangci-lint clean, gesamtes Mail-Modul (~24 Pakete) regressionsfrei getestet. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HhgFcLS8tYMhDJpP74C6AQ
91 lines
3.5 KiB
Markdown
91 lines
3.5 KiB
Markdown
# ING-02 — POP3-Server: Prüfprotokoll
|
|
|
|
Datum: 2026-09-01
|
|
Host: 192.168.1.131 (Build/Test/Lint), rsync + ssh
|
|
Paket: `mail/internal/pop3`
|
|
|
|
## Umsetzung
|
|
|
|
Vollständiger POP3-Server (RFC 1939) von Grund auf implementiert:
|
|
TCP-Listener, CRLF/Byte-Stuffing-sichere Response-Writer, Session-Zustandsmaschine
|
|
(Authorization / Transaction / Update), Kommandos USER, PASS, STAT, LIST, RETR,
|
|
DELE, QUIT. Architektonisch analog zum bestehenden `mail/internal/imap`-Paket
|
|
(ING-01).
|
|
|
|
## Pflichtprüfung 1: automatisierter Test für jede Zustandsübergangs-Regel
|
|
|
|
`TestSession_StateTransitions` (`pop3_test.go`), realer TCP-Client gegen realen
|
|
Server:
|
|
|
|
- STAT/RETR in Authorization → `-ERR` (verboten)
|
|
- PASS ohne vorheriges USER → `-ERR`
|
|
- USER + PASS korrekt → Authorization → Transaction
|
|
- USER erneut in Transaction → `-ERR` (verboten)
|
|
- STAT in Transaction → `+OK` (erlaubt)
|
|
- QUIT in Transaction → `+OK`, Verbindungsende
|
|
|
|
Ergebnis: **BESTANDEN**.
|
|
|
|
## Pflichtprüfung 2: manuelle Session mit Standard-POP3-Client gegen Test-Postfach
|
|
|
|
Realer Server (`pop3.NewServer`) auf `127.0.0.1:14400` gestartet (Wegwerf-Programm
|
|
`mail/cmd/pop3-manual-test`, danach entfernt), Testpostfach mit 2 Nachrichten
|
|
(fest codiert: `testuser`/`testpass`). Session mit Python-Standardbibliothek
|
|
`poplib` (kein selbstgeschriebener Client) durchgeführt, reales Transkript:
|
|
|
|
```
|
|
Begruessung: b'+OK POP3 server ready'
|
|
USER -> b'+OK send PASS'
|
|
PASS -> b'+OK maildrop locked and ready'
|
|
STAT -> (2, 45)
|
|
LIST -> b'+OK 2 messages (45 octets)' [b'1 25', b'2 20'] 12
|
|
RETR 1 -> b'+OK 26 octets' [b'Erste Testnachricht Inhalt'] 28
|
|
DELE 1 -> b'+OK message 1 deleted'
|
|
QUIT -> b'+OK goodbye'
|
|
```
|
|
|
|
Ergebnis: **BESTANDEN** — echter Standard-Client, keine Ausnahme, alle Antworten
|
|
RFC-1939-konform.
|
|
|
|
## Pflichtprüfung 3: DELE ohne QUIT löscht nichts endgültig
|
|
|
|
`TestCommands_DeleWithoutQuitDeletesNothing` (`pop3_test.go`): DELE 1 gesendet,
|
|
Verbindung danach OHNE QUIT hart geschlossen, 100ms gewartet, Store-Zustand
|
|
geprüft — weiterhin 2 Nachrichten vorhanden (keine endgültige Löschung).
|
|
|
|
Strukturell garantiert durch Code-Design: `store.Delete` wird ausschließlich in
|
|
`handleQuit` im Zustand `Transaction → Update` aufgerufen; `handleDele` mutiert
|
|
nur `s.deleted` (sitzungslokal).
|
|
|
|
Ergebnis: **BESTANDEN**.
|
|
|
|
## Akzeptanzkriterien
|
|
|
|
1. **Jede Verbindung eigene Goroutine**: `Server.Serve` startet pro Accept eine
|
|
neue Goroutine (`server.go`). Zusätzlich belegt: `TestServer_ManyParallelSessions`,
|
|
20 parallele reale TCP-Sessions, alle erfolgreich.
|
|
2. **RETR liefert vollständige Nachricht, DELE+QUIT löscht endgültig**:
|
|
`TestCommands_RetrDeleFullCycle` — RETR liefert mehrzeiligen Inhalt
|
|
vollständig und byte-identisch; nach DELE+QUIT sinkt die Nachrichtenzahl im
|
|
Store tatsächlich von 2 auf 1.
|
|
3. **Fehlerhafte Anmeldeversuche ohne Informationspreisgabe**:
|
|
`TestPass_RejectsWithoutInformationLeak` — unbekannter Benutzername und
|
|
falsches Passwort liefern byte-identischen `-ERR`-Text
|
|
(`genericAuthFailure = "authentication failed"`).
|
|
|
|
## Build/Vet/Lint/Test — Gesamtmodul
|
|
|
|
```
|
|
go build ./... → OK
|
|
go vet ./... → OK
|
|
golangci-lint run ./... → 0 issues
|
|
go test ./... -p 1 (TEST_TENANT_DSN, TEST_MANTICORE_URL gesetzt) → alle Pakete ok, inkl. neuem internal/pop3 (0.109s, 5/5 Tests)
|
|
```
|
|
|
|
Keine Regression in den bestehenden ~23 Paketen.
|
|
|
|
## Ergebnis
|
|
|
|
ING-02 erfüllt alle Pflichtprüfungen und Akzeptanzkriterien mit echten,
|
|
ausgeführten Nachweisen. Freigeschaltet: ING-06, ING-07, ING-08, ING-10, QA-07.
|