mailmap

package
v0.2.12 Latest Latest
Warning

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

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

Documentation

Overview

Package mailmap implements the chassis's "mail-domain accept map" head: a tiny TCP server that speaks the Postfix tcp_table(5) protocol so the edge Postfix can ask the chassis, per recipient domain, "is this an accepted mail domain?" before relaying it to the LMTP head.

This is what lets the single public edge Postfix accept mail for ANY verified tenant domain (a stacks subdomain or a custom domain) WITHOUT a static domain list and without becoming an open relay: the chassis (which owns tenant_hostnames) is the single source of truth, and the answer auto-updates as tenants add/verify domains. Postfix wires it as

relay_domains = tcp:<this head>:<port>

Protocol (Postfix tcp_table(5)): the client sends `get <key>\n` (the key %-encoded); we reply:

  • `200 OK\n` → key found → domain is accepted
  • `500 <text>\n` → not found → reject_unauth_destination rejects it
  • `400 <text>\n` → temp error → Postfix treats the table as unavailable and DEFERs (4xx) — never an open relay, never lost mail

If the head is down, Postfix can't connect → table unavailable → defer. We NEVER reply 200 on error/unknown (the open-relay guard): every accept is backed by a real verified tenant_hostnames row.

OFF by default. Both gates must be flipped:

  • `mailmap` must appear in `--personalities`
  • `--mailmap-listen-addrs` must be non-empty

The responder is unauthenticated; bind it only where the co-located Postfix can reach it (the compose network) — never a public interface.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type MailMapController

type MailMapController struct {
	// contains filtered or unexported fields
}

MailMapController owns the tcp_table listeners and serves the relay_domains acceptance lookup.

func NewController

func NewController(ctx context.Context, pu *processor.Unit, resolver ingress.MailResolver) *MailMapController

NewController constructs (but does not start) a mailmap controller. Mirrors the other personalities' constructor shape so server.go can treat them uniformly. `resolver` is the same MailResolver the LMTP head uses, so an accept decision can never drift from a route decision.

func (*MailMapController) Start

func (c *MailMapController) Start()

Start binds the configured listeners and serves the tcp_table protocol on each. The double-gate (personality string AND non-empty listen addrs) keeps the head off by default.

func (*MailMapController) Stop

func (c *MailMapController) Stop()

Stop closes the listeners and any in-flight connections, then waits for the accept loops and handlers to drain.

Jump to

Keyboard shortcuts

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