Skip to content

Postfix

Postfix uses Userli to decide

  • which domains and mailboxes exist,
  • where aliases go (including postmaster@ and abuse@),
  • which sender addresses a user may use,
  • how many emails a user may send (SMTP quota),
  • whether an SMTP client may authenticate (SASL).

The connection is made by the userli-postfix-adapter, a small Go service running next to Postfix. It implements the Postfix socketmap protocol, a policy server for rate limiting and a Dovecot-compatible SASL server.

flowchart LR
    P[Postfix] -->|socketmap :10001| A[userli-postfix-adapter]
    P -->|policy :10003| A
    P -->|SASL :10006| A
    A -->|HTTPS /api/postfix| U[Userli]
    A --- R[(Redis)]

On the Userli host

Create an API token with the scope postfix:

bin/console app:api-token:create --name "Postfix" --scopes postfix

On the Postfix host

Run the adapter

Install the adapter from its releases or run its container image. It needs Redis for caching and rate limiting. Main settings:

Variable Description
USERLI_BASE_URL URL of Userli, e.g. https://users.example.org
USERLI_TOKEN API token with the postfix scope
REDIS_URL Redis connection, e.g. redis://localhost:6379/0
SASL_LISTEN_ADDR Enables SMTP authentication, e.g. :10006 or /var/spool/postfix/private/auth
POSTFIX_RECIPIENT_DELIMITER Your recipient_delimiter, e.g. +

See the adapter README for all options and its metrics.

Lookups

/etc/postfix/main.cf
virtual_mailbox_domains = socketmap:inet:localhost:10001:domain
virtual_mailbox_maps    = socketmap:inet:localhost:10001:mailbox
virtual_alias_maps      = socketmap:inet:localhost:10001:alias
smtpd_sender_login_maps = socketmap:inet:localhost:10001:senders

Deliver mail to Dovecot via LMTP, for example virtual_transport = lmtp:unix:private/dovecot-lmtp.

To stop users from sending with addresses that don't belong to them, add reject_sender_login_mismatch to smtpd_sender_restrictions on the submission port.

SMTP authentication

/etc/postfix/main.cf
smtpd_sasl_type = dovecot
smtpd_sasl_path = inet:localhost:10006
smtpd_sasl_auth_enable = yes

Authentication fails for deleted accounts, accounts with the role Spam and accounts that have to change their password. You can also use Dovecot's SASL server instead.

Rate limiting

/etc/postfix/main.cf
smtpd_end_of_data_restrictions = check_policy_service inet:localhost:10003

The limits come from Userli: per user or alias, or the global default (see Admin Guide → Settings).

Test

postmap -q "example.org" socketmap:inet:localhost:10001:domain
postmap -q "user@example.org" socketmap:inet:localhost:10001:mailbox
postmap -q "alias@example.org" socketmap:inet:localhost:10001:alias
postmap -q "user@example.org" socketmap:inet:localhost:10001:senders

Lookups are cached in Userli and in the adapter for a few minutes. Changes may take a short time to reach Postfix.