Files
nexarch/mail/docs/ING-01-PRUEFPROTOKOLL.md
sysopsandClaude Sonnet 5 54c5f74778 ING-01: imap-server-grundgeruest
IMAP-Server-Grundgerüst: TCP-Listener, Command-Parser, Session-
Zustandsmaschine (Not Authenticated/Authenticated/Selected), Grundbefehle
CAPABILITY/LOGIN/SELECT/FETCH/LOGOUT.

- parser.go: Tag+Kommando+Argumente (Atome, zitierte Zeichenketten),
  keine IMAP-Literalsyntax (kleinste Lösung).
- response.go: sanitizeResponseText entfernt eingebettete CR/LF vor jeder
  Antwortzeile — bekannten archivmail-Fehler (Header-/Zeilen-Injection
  durch Stringkonkatenation ohne CRLF-Prüfung) strukturell vermieden.
- session.go/commands.go: strikte Zustandsprüfung je Kommando, verbotene
  Übergänge und fehlerhafte Zeilen liefern BAD/NO statt
  Verbindungsabbruch. maxCommandLineBytes begrenzt Pufferwachstum
  defensiv.
- server.go: TCP-Accept-Schleife, eine Goroutine je Verbindung.
- Authenticator/MailboxStore als schmale Schnittstellen — echte
  Benutzerverwaltungs-/Postfach-Anbindung ist Sache von IMP-01 u. a.

Prüfungen (alle real durchgeführt, siehe mail/docs/ING-01-PRUEFPROTOKOLL.md):
1. Manuelle Session mit Pythons imaplib gegen den echten laufenden
   Server: alle Grundbefehle real beantwortet, ungültiges SELECT liefert
   real NO ohne Verbindungsabbruch.
2. TestSession_StateTransitionsAndForbiddenTransitions: alle drei
   Zustandsübergänge und deren verbotene Übergänge real über TCP geprüft.
3. TestServer_50ParallelSessionsNoLeak: 50 reale parallele Sessions,
   0 Fehler.

Kein Umbau: alle bestehenden Pakete unverändert.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HhgFcLS8tYMhDJpP74C6AQ
2026-08-31 23:33:00 +02:00

4.2 KiB
Raw Permalink Blame History

ING-01 Prüfprotokoll: IMAP-Server-Grundgerüst

Keine Vorbedingungen im Mail-Board (sofort startbar).

Umsetzung

  • mail/internal/imap/state.goState (NotAuthenticated, Authenticated, Selected, RFC 3501 §3).
  • mail/internal/imap/parser.goparseCommandLine/tokenize: Tag + Kommando + Argumente (Atome und doppelt zitierte Zeichenketten), keine IMAP-Literalsyntax ({n}CRLF... — bewusst nicht Bestandteil der kleinsten Lösung, LOGIN/SELECT/FETCH kommen ohne Literale aus).
  • mail/internal/imap/response.gosanitizeResponseText: Bekannten Fehler vermieden (archivmail: Header-/Zeilen-Injection durch Stringkonkatenation ohne CRLF-Prüfung) — jede Antwortzeile entfernt eingebettete CR/LF, bevor sie geschrieben wird, keine direkte Interpolation von Nutzereingaben in eine Rohantwort.
  • mail/internal/imap/session.go/commands.go — Session- Zustandsmaschine mit CAPABILITY/LOGIN/SELECT/FETCH/LOGOUT, strikte Zustandsprüfung je Kommando (Akzeptanzkriterium 1), fehlerhafte Zeilen/unbekannte Kommandos/verbotene Zustandsübergänge liefern eine BAD/NO-Antwort statt eines Verbindungsabbruchs (Akzeptanzkriterium 3). maxCommandLineBytes begrenzt die Puffergröße defensiv (Vorbild Dovecot: defensive Fehlerbehandlung statt optimistischem Parsing).
  • mail/internal/imap/server.goServer.Serve: TCP-Accept-Schleife, eine Goroutine je Verbindung.
  • Authenticator/MailboxStore sind schmale Schnittstellen — echte Benutzerverwaltungs-/Postfach-Anbindung ist Sache von IMP-01 u. a. („Nicht Bestandteil dieser Kachel"), dieses Paket kennt weder Core-IAM noch mail/internal/storage.
  • Kein Umbau: alle bestehenden Pakete unverändert — ING-01 fügt ausschließlich das neue mail/internal/imap-Paket hinzu.

Prüfungen

# Prüfung Ergebnis
1 Manuelle Session mit Standard-IMAP-Client durchgespielt und protokolliert bestanden echte Session mit Pythons Standardbibliothek imaplib gegen den real laufenden Server auf 192.168.1.131 (Port 14300): CAPABILITY→OK, LOGIN→OK, SELECT INBOX→OK (2 Nachrichten), FETCH 1:2 (FLAGS)→OK mit realen Flags, SELECT eines nicht existierenden Postfachs→NO OHNE Verbindungsabbruch, danach CAPABILITY erneut→OK, LOGOUT→BYE. Vollständiges Protokoll siehe unten
2 Automatisierter Test deckt alle drei Zustandsübergänge und deren verbotene Übergänge ab bestanden TestSession_StateTransitionsAndForbiddenTransitions: SELECT/FETCH in NotAuthenticated→BAD, LOGIN→Authenticated, erneutes LOGIN/FETCH in Authenticated→BAD, SELECT→Selected, FETCH in Selected→OK — alle real über echte TCP-Verbindung gegen den echten Server geprüft
3 Lasttest mit 50 parallelen Sessions ohne Ressourcenleck bestanden TestServer_50ParallelSessionsNoLeak: 50 reale, gleichzeitige TCP-Verbindungen, je vollständiger LOGIN→SELECT→FETCH→LOGOUT-Durchlauf, 0 Fehler

Manuelles Sitzungsprotokoll (Pflichtprüfung 1, real erzeugt)

CAPABILITY -> OK [b'IMAP4rev1']
LOGIN -> OK [b'LOGIN completed']
SELECT INBOX -> OK [b'2']
FETCH 1:2 (FLAGS) -> OK [b'1 (FLAGS (\\Seen))', b'2 (FLAGS ())']
SELECT NICHT_VORHANDEN (erwartet NO) -> NO [b'SELECT failed: no such mailbox']
CAPABILITY nach Fehler (Verbindung noch offen) -> OK [b'IMAP4rev1']
LOGOUT -> BYE [b'IMAP4rev1 Server logging out']

Testserver und Testskript wurden nach der Prüfung wieder entfernt (Wegwerf-cmd/imap-manual-test, nicht Teil des Produktcodes).

Zusätzlich (AC2/AC3, ergänzend real geprüft): TestCommands_AllBaseCommandsAnswered (alle fünf Grundbefehle real beantwortet) und TestSession_MalformedLineDoesNotDisconnect (syntaktisch fehlerhafte Zeile → * BAD, Verbindung bleibt real funktionsfähig).

Build/Test-Ergebnis (192.168.1.131)

go build ./...  -> clean
go vet ./...    -> clean
golangci-lint run ./...  -> 0 issues
go test ./internal/imap/... -v -timeout 60s  -> 5/5 bestanden
TEST_TENANT_DSN=... TEST_MANTICORE_URL=... go test ./... -p 1
  -> alle 12 Pakete bestanden, keine Regression

Gesamtergebnis

Bestanden. Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen real erfüllt. Entsperrt IMP-01, ING-02, ING-05, ING-06, ING-07, ING-08, ING-10, QA-07.