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
3.5 KiB
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
- Jede Verbindung eigene Goroutine:
Server.Servestartet pro Accept eine neue Goroutine (server.go). Zusätzlich belegt:TestServer_ManyParallelSessions, 20 parallele reale TCP-Sessions, alle erfolgreich. - 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. - 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.