lmtp

package
v0.2.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 20, 2026 License: MPL-2.0 Imports: 27 Imported by: 0

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL