feat(mail): ING-03 SMTP-Server & Mailer (RFC 5321)
Neues Paket mail/internal/smtp: SMTP-Server für eingehende Mails, von Grund auf implementiert, analog zu mail/internal/imap und mail/internal/pop3 — TCP-Listener mit einer Goroutine pro Verbindung, Session-Zustandsmaschine (Greeting/Ready/MailFromSet/RcptToSet), Kommandos HELO/EHLO, MAIL FROM, RCPT TO, DATA, RSET, NOOP, QUIT. Envelope wird schrittweise aufgebaut und validiert (503 bei übersprungenen Schritten, 553 bei ungültiger Absender-/Empfängeradresse), Nachrichtengröße wird während DATA laufend gegen eine konfigurierbare Höchstgröße geprüft (552 bei Überschreitung, Sink bekommt die Nachricht nicht). Dot-Stuffing beim Empfang korrekt rückgängig gemacht. Neues Paket mail/internal/mailer: Mailer-Komponente für ausgehende Nachrichten. headerWriter ist die einzige Stelle, an der Header geschrieben werden — jeder Feldwert wird hart gegen CR/LF/Steuerzeichen geprüft, bevor er in die Nachricht geschrieben wird. Behebt den bekannten archivmail-Fehler (Header-Injection durch Stringkonkatenation ohne CRLF-Prüfung, siehe known-issues-archivmail.md #1). Sender.Send überträgt per echtem net/smtp-Client (Standardbibliothek) — keine Zugangsdaten im Code, Zieladresse kommt vom Aufrufer. Alle drei Pflichtprüfungen mit echten Nachweisen durchgeführt: CRLF-/Steuerzeichen-Injection in Betreff und Anzeigenamen schlägt fehl (vier Testfälle), Ende-zu-Ende-Header-Integritätstest über echten SMTP-Dialog (Mailpit/MailHog nicht installierbar auf diesem Rechner — Ersatz durch den in dieser Kachel gebauten echten SMTP-Server, kein Mock, im Prüfprotokoll begründet), Lasttest mit 50 gleichzeitigen Verbindungen ohne Goroutine-/Verbindungsleck. go build/go vet/golangci-lint clean, gesamtes Mail-Modul (~26 Pakete) regressionsfrei getestet.
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
// Package smtp implementiert ING-03s SMTP-Server (RFC 5321) für
|
||||
// eingehende Mails: HELO/EHLO, MAIL FROM, RCPT TO, DATA, RSET, QUIT.
|
||||
// Bewusste Neuimplementierung nach NEXARCH-Techstack, gleiche Konvention
|
||||
// wie mail/internal/imap und mail/internal/pop3 — eigene Session je
|
||||
// Verbindung in eigener Goroutine, schmale Sink-Schnittstelle statt
|
||||
// geteilter Typen über Paketgrenzen hinweg.
|
||||
package smtp
|
||||
|
||||
import "context"
|
||||
|
||||
// Envelope ist der SMTP-Umschlag einer eingehenden Nachricht, wie er
|
||||
// vor der DATA-Annahme validiert wurde (Akzeptanzkriterium 1).
|
||||
type Envelope struct {
|
||||
From string
|
||||
To []string
|
||||
}
|
||||
|
||||
// MessageSink nimmt eine vollständig empfangene, dot-entstuffte
|
||||
// Nachricht entgegen — Speicherung/Weiterverarbeitung ist Sache
|
||||
// anderer Kacheln.
|
||||
type MessageSink interface {
|
||||
Accept(ctx context.Context, envelope Envelope, raw []byte) error
|
||||
}
|
||||
Reference in New Issue
Block a user