Documentation
¶
Overview ¶
Package lmtp implements the chassis's LMTP head: a personality that speaks LMTP (RFC 2033) to a colocated Postfix (or any LMTP client) and turns each delivery into a normal txcl envelope.
Phase 0 scope: protocol skeleton only. Raw RFC 5322 bytes ride the envelope as `_txc.lmtp.msg.raw` (b64); MIME parsing lands in Phase 1. The verdict is broadcast (same status for every recipient) using the plain `smtp.Session` interface; per-recipient verdicts via `smtp.LMTPSession` are Phase 3.
Default-deny: if the pipeline doesn't return an explicit `_txc.lmtp.res.code`, every recipient gets 550 5.1.1. Mail-convention "user unknown" is the safer default than silently accepting (250) or queue-forever-then-bounce (4xx).
LMTP is OFF by default. Both gates must be flipped:
- `lmtp` must appear in `--personalities`
- `--lmtp-listen-addrs` must be non-empty
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type LMTPController ¶
type LMTPController struct {
// contains filtered or unexported fields
}
LMTPController owns the LMTP listeners and their go-smtp Servers.
One Controller can host multiple listeners (e.g. a Unix socket for Postfix plus a TCP socket for cross-host LMTP); each listener gets its own `smtp.Server`. The Controller doesn't care which listener a delivery arrived on — that string flows into the envelope as `_txc.lmtp.listener` for ingress routing to inspect.
func NewController ¶
func NewController(ctx context.Context, pu *processor.Unit, resolver ingress.MailResolver) *LMTPController
NewController constructs (but does not start) an LMTP controller. Mirrors the constructor shape of the other personalities so server.go can treat them uniformly.
`resolver` is the chassis's ingress resolver, restricted to its MailResolver facet. The chassis-side wiring in server.go type-asserts the data-plane resolver against MailResolver and passes it through; pass nil for embedders / tests that don't need ingress routing — every RCPT TO then default-denies (550) for lack of any opted-in stack.
func (*LMTPController) Start ¶
func (l *LMTPController) Start()
Start binds the configured listeners and serves LMTP on each. The double-gate (personality string AND non-empty listen addrs) means existing deployments cannot acquire a new listener on upgrade without explicit opt-in.
func (*LMTPController) Stop ¶
func (l *LMTPController) Stop()
Stop drains in-flight LMTP transactions and closes the listeners. Each go-smtp Server is shut down with a 5s ceiling so a wedged session can't stall chassis shutdown.