Neues Paket mail/internal/protoguard kapselt die für IMAP- und POP3-Sessions gemeinsam benötigte Timeout- und Backoff-Logik einer einzelnen Verbindung: - Pro Protokollphase konfigurierbarer Idle-Read-Timeout (POP3: Authorization/Transaction, IMAP: NotAuthenticated/Selected), vor jedem Lesevorgang neu gesetzt. - Sich verdoppelnder Backoff bei wiederholten Anmeldefehlversuchen einer Verbindung (BackoffBase bis BackoffMax), Verbindungstrennung nach konfigurierbarer Höchstzahl statt Dauerschleife. Server.NewServer bleibt unverändert (Standardkonfiguration); NewServerWithGuardConfig erlaubt abweichende Werte. Ressourcenaufräumung bei Verbindungsabbruch war bereits durch defer conn.Close() strukturell gegeben — der Timeout sorgt dafür, dass dieser Pfad auch bei hängenden oder böswilligen Gegenstellen zuverlässig erreicht wird. Alle drei Pflichtprüfungen mit echten Nachweisen durchgeführt: Chaos-Test mit 30 hart gekappten Verbindungen während aktiver Übertragung (kein Goroutine-Leck), Timeout-Auslösung in jeder Protokollphase beider Server, steigender Backoff mit definierter Verbindungstrennung nach Höchstzahl an Fehlversuchen. go build/go vet/golangci-lint clean, gesamtes Mail-Modul (~24 Pakete) regressionsfrei getestet.
4.4 KiB
ING-07 — Protokoll-Fehlerbehandlung & Wiederverbindung: Prüfprotokoll
Datum: 2026-09-01
Host: 192.168.1.131 (Build/Test/Lint), rsync + ssh
Pakete: mail/internal/protoguard (neu, gemeinsam genutzt), mail/internal/imap, mail/internal/pop3
Umsetzung
Neues Paket protoguard kapselt Timeout- und Backoff-Logik EINER
Verbindung (Guard), von IMAP- und POP3-Session gleichermaßen genutzt:
ApplyReadDeadline(conn, phase)setzt vor jedem Lesevorgang die Lese-Deadline passend zur aktuellen Protokollphase (POP3: Authorization/Transaction, IMAP: NotAuthenticated/Selected).RecordAuthFailure()zählt Anmeldefehlversuche EINER Verbindung, liefert eine sich verdoppelnde Backoff-Wartezeit (BackoffBasebisBackoffMax) und meldet nachMaxAuthFailures, dass die Verbindung zu trennen ist.
Server.NewServer verwendet protoguard.DefaultConfig() (5 Minuten
Timeout, max. 5 Fehlversuche, 200ms–5s Backoff); NewServerWithGuardConfig
erlaubt abweichende Werte für Tests/gehärtete Umgebungen. Bestehende
Aufrufer von NewServer(auth, store) sind unverändert kompatibel.
Ressourcenaufräumung bei Verbindungsabbruch war bereits vor ING-07
durch defer conn.Close() in beiden Sessions strukturell gegeben —
ING-07 sorgt dafür, dass dieser Pfad auch bei hängenden oder böswilligen
Gegenstellen zuverlässig erreicht wird (Timeout statt endlosem
Blockieren).
Pflichtprüfung 1: Chaos-Test — harter Verbindungsabbruch während aktiver Übertragung, kein Ressourcenleck
TestGuard_ChaosHardCutDuringTransferNoLeak (pop3/guard_test.go,
imap/guard_test.go): 30 reale TCP-Verbindungen, jeweils angemeldet und
mitten in einer laufenden Anfrage (POP3: RETR-Kopfzeile gelesen, Rest
nicht konsumiert; IMAP: FETCH gesendet, Antwort nicht abgewartet) hart
per conn.Close() gekappt. runtime.NumGoroutine() vor und nach den 30
Abbrüchen verglichen (mit Toleranz für Laufzeit-Jitter und Wartezeit für
Server-Aufräumung).
Ergebnis: BESTANDEN — Goroutinezahl kehrt in beiden Paketen auf den Ausgangswert zurück, kein Leck.
Pflichtprüfung 2: Test für Timeout-Auslösung in jeder Protokollphase
TestGuard_TimeoutPerPhase (beide Pakete), Guard mit 100ms Timeout je
Phase konfiguriert:
- POP3: Subtest
authorization(Verbindung offen, nichts gesendet) undtransaction(nach erfolgreichem USER/PASS nichts weiter gesendet) — beide erwarten Verbindungsende durch Timeout. - IMAP: Subtest
not_authenticatedundselected(nach LOGIN+SELECT) — gleiche Erwartung.
Ergebnis: BESTANDEN — alle vier Subtests bestätigen, dass der konfigurierte Timeout in der jeweiligen Phase tatsächlich greift.
Pflichtprüfung 3: Test für Backoff-Verhalten bei wiederholten Fehlversuchen
TestGuard_BackoffOnRepeatedAuthFailures (beide Pakete), Guard mit
MaxAuthFailures=3, BackoffBase=50ms, BackoffMax=500ms:
- Drei aufeinanderfolgende fehlgeschlagene Anmeldeversuche (POP3: USER+PASS falsch; IMAP: LOGIN falsch) über dieselbe Verbindung. Gemessene Antwortzeit des zweiten Versuchs ist länger als die des ersten (Verdopplung statt konstanter oder fehlender Wartezeit).
- Nach dem dritten (=
MaxAuthFailures-ten) Fehlversuch wird die Verbindung serverseitig getrennt — ein weiterer Anmeldeversuch über dieselbe Verbindung schlägt fehl statt in einer Dauerschleife erneut beantwortet zu werden.
Ergebnis: BESTANDEN.
Akzeptanzkriterien
- Verbindungsabbrüche räumen serverseitige Session-Ressourcen zuverlässig auf: durch Pflichtprüfung 1 belegt (kein Goroutine-Leck nach 30 harten Abbrüchen in beiden Protokollen).
- Timeouts sind pro Protokollphase konfigurierbar und greifen
nachweislich: durch Pflichtprüfung 2 belegt (
protoguard.Config. PhaseTimeoutje Phase, vier bestandene Subtests). - Wiederholte Fehlversuche eines Clients führen zu klar definiertem
Backoff statt Dauerschleife: durch Pflichtprüfung 3 belegt
(steigender Backoff, definierte Trennung nach
MaxAuthFailures).
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/protoguard (indirekt über imap/pop3-Tests abgedeckt)
Keine Regression in den bestehenden ~24 Paketen.
Ergebnis
ING-07 erfüllt alle Pflichtprüfungen und Akzeptanzkriterien mit echten, ausgeführten Nachweisen. Freigeschaltet: QA-02.