Differences between revisions 14 and 24 (spanning 10 versions)
Revision 14 as of 2023-05-26 20:36:21
Size: 12783
Comment:
Revision 24 as of 2025-02-18 00:06:30
Size: 5489
Comment: ?
Deletions are marked like this. Additions are marked like this.
Line 52: Line 52:
== Design ==

Postfix consists of daemons and queues.

The queues are:

 * '''maildrop''' for local mail posted by `sendmail(1)`
 * '''hold''' for mail that required administrater intervention
 * '''incoming''' for mail recieved
 * '''active''' for delivery
 * '''deferred''' for mail that temporarily failed to deliver

Local mail sent by `sendmail(1)` is passed to `postdrop(1)`, which enqueues mail into maildrop. `pickup(8)` then passes mail from maildrop to `cleanup(8)`.

Received mail, whether by `smtpd(8)` or `qmqpd(8)`, is passed directly to `cleanup(8)`.

`cleanup(8)` passes back and forth with `trivial-rewrite(8)` and enqueues mail into incoming.

`qmgr(8)` moves mail from incoming into active and deferred, and schedules delivery by any of `smtp(8)`, `lmtp(8)`, `local(8)`, `virtual(8)`, or `pipe(8)`.

`master(8)` manages all daemons according to the configuration file `master.cf` (`see master(5)`). It looks like:

{{{
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (no) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd
#smtp inet n - n - 1 postscreen
#smtpd pass - - n - - smtpd
#dnsblog unix - - n - 0 dnsblog
#tlsproxy unix - - n - 0 tlsproxy
submission inet n - n - - smtpd
# -o syslog_name=postfix/submission
# -o smtpd_tls_security_level=encrypt
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_tls_auth_only=yes
# -o smtpd_reject_unlisted_recipient=no
# -o smtpd_client_restrictions=$mua_client_restrictions
# -o smtpd_helo_restrictions=$mua_helo_restrictions
# -o smtpd_sender_restrictions=$mua_sender_restrictions
# -o smtpd_recipient_restrictions=
  -o smtpd_relay_restrictions=permit
# -o milter_macro_daemon_name=ORIGINATING
smtps inet n - n - - smtpd
# -o syslog_name=postfix/smtps
# -o smtpd_tls_wrappermode=yes
# -o smtpd_sasl_auth_enable=yes
# -o smtpd_reject_unlisted_recipient=no
# -o smtpd_client_restrictions=$mua_client_restrictions
# -o smtpd_helo_restrictions=$mua_helo_restrictions
# -o smtpd_sender_restrictions=$mua_sender_restrictions
# -o smtpd_recipient_restrictions=
# -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
# -o milter_macro_daemon_name=ORIGINATING
#628 inet n - n - - qmqpd
pickup unix n - n 60 1 pickup
cleanup unix n - n - 0 cleanup
qmgr unix n - n 300 1 qmgr
#qmgr unix n - n 300 1 oqmgr
tlsmgr unix - - n 1000? 1 tlsmgr
rewrite unix - - n - - trivial-rewrite
bounce unix - - n - 0 bounce
defer unix - - n - 0 bounce
trace unix - - n - 0 bounce
verify unix - - n - 1 verify
flush unix n - n 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - n - - smtp
relay unix - - n - - smtp
        -o syslog_name=postfix/$service_name
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq unix n - n - - showq
error unix - - n - - error
retry unix - - n - - error
discard unix - - n - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - n - - lmtp
anvil unix - - n - 1 anvil
scache unix - - n - 1 scache
postlog unix-dgram n - n - 1 postlogd
}}}

Some important details to note:
 * `lmtp` implies port 24
 * `smtp` implies port 25
 * `smtps` implies port 465
 * `submission` implies port 587
== Usage ==

For unencrypted and unauthenticated connections, try a connection string like `smtp+insecure+none://example.com:25`.

When running a server that listens on port 465, with
Line 148: Line 63:

Before trying to configure Postfix, ensure that you understand the [[Postfix/Design|design]] of Postfix.

See also [[Postfix/Encryption|encryption]] and [[Postfix/Authentication|authentication]].
Line 171: Line 90:
----



=== Local Delivery ===

For local addresses, the local part is extracted and casefolded to lowercase. This will be used to attempt delivery.

Mail is delivered to a user-specific folder under `mail_spool_directory`, i.e. `/var/spool/mail/root`. (Alternatively, mail can be delivered into users' home directories via `home_mailbox`.) The following manipulations are made to locally-delivered mail:

 * prepend a `From SENDER DATETIME` envelope header
 * prepend an `X-Original-To:` header
 * prepend an `Delivered-To:` header
 * prepend a `Return-Path:` header
 * prepend a `>` character to lines beginning with `From `
 * append an empty line

Also, the mailbox is locked while delivery is in progress; if an error occurs, the mailbox is truncated to its original length. Delivery is executed with the permissions of the recipient.



==== Custom Delivery ====

A custom delivery command can be provided with `mailbox_command_maps` or `mailbox_command`.

In most cases, the command is executed with the recipient's permissions. If the recipient is `root`, a custom delivery command is executed with `default_privs`.



==== Qmail ====

For `qmail`-style mailboxes, the value of `mail_spool_directory` or `home_mailbox` must end in a forward slash (`/`).

{{{
home_mailbox = Maildir/
}}}

The following manipulations are made to locally-delivered `qmail`-style mail:
 * prepend a `Delivered-To:` header
 * prepend an `X-Original-To:` header
 * prepend a `Return-Path:` header

----



=== Forwarding ===

When attempting delivery, `forward_path` is scanned for a `forward(5)` file (i.e. `~/.forward`). These looks like:

{{{
[email protected] # anything after # is ignored
"|/path/to/examplemda"
}}}

Forwarded mail is sent as a new message with the `Delivered-To:` header, to prevent loops.

Note that the second line is only allowable if `allow_mail_to_commands` is set to:

{{{
allow_mail_to_commands = alias,forward,include
}}}

The default `alias,forward` disallows custom commands.

----



=== Routing ===


=== Routing Mail ===
Line 260: Line 112:
The first part of each line is a pattern. The second part is an instruction beginning with `local`, `lmtp`, `smtp`, or `relay`. The `local` instruction expands to the `local_transport` setting, which itself defaults to `local:$myhostname`. Bracketing an address prevents a MX record lookup; the A record alone is looked up and used naively. The first part of each line is a pattern. The second part is an instruction:

 * a `local` instruction attempts [[Postfix/LocalDelivery|local delivery]] to the specified address
   * a bare `local` instruction expands to the `local_transport` setting, which itself defaults to `local:$myhostname`
 * a `lmtp` instruction forwards mail to an [[Email/LMTP|LMTP]] server
 * a `smtp` instruction forwards mail to an [[Email/SMTP|SMTP]] server
 * a `relay` instruction causes mail to [[Postfix/Relaying|relayed]]

Bracketing an address prevents a [[Protocols/DNS#Records|MX record]] lookup; the [[Protocols/DNS#Records|A record]] alone is looked up and used naively. If even A record lookup should be skipped (i.e. for a name defined in the [[Linux/Hosts|hosts file]]), additionally specify `smtp_dns_support_level = disabled`.
Line 272: Line 132:
==== Relaying ====

The `relay` instruction in a `transport(5)` file causes mail to be relayed to another SMTP server.

Use of a relay server often requires authentication and encryttion. Try:

{{{
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = lmdb:/etc/postfix/sasl/sasl_passwd
smtp_tls_security_level = encrypt
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
}}}

`/etc/postfix/sasl/sasl_passwd` should look like:

{{{
[smtp.gmail.com]:587 [email protected]:wwwwxxxxyyyyzzzz
}}}

Run `postmap /etc/postfix/sasl/sasl_passwd` and a hashed file will be produced. If your `postmap(1)` does not use LMDB, replace the `lmdb:` with whatever algorithm ''was'' used.

----


Line 300: Line 134:
To rewrite addresses as they are received, try:

{{{
smtp_generic_maps = lmdb:/etc/postfix/generic
}}}

A `generic(5)` file (i.e. `/etc/postfix/generic`) looks like:

{{{
root@localdomain [email protected]
root [email protected]
@localdomain [email protected]
}}}

The first part of each line is a pattern. The second part is the address that overwrites a matching address.

Note the second line only rewrites addresses using a domain in `$myorigin`, `$mydestination`, `$inet_interfaces`, or `$proxy_interfaces`. The matching also happens in that hierarchical order: by full address, then by local part, then by domain part.

Run `postmap /etc/postfix/generic` and a hashed file will be produced. If your `postmap(1)` does not use LMDB, replace the `lmdb:` with whatever algorithm ''was'' used.

----
See [[Postfix/Rewriting|here]].

Postfix

postfix(1) is an SMTP mail transfer agent.


Installation

Most Linux and BSD distributions offer a postfix package.

For systemd-capable systems, start and enable postfix.service.

For BSD distributions, try:

postfix start

Containers

postfix(1) is designed to be launched from userspace, rather than being a binary that can be invoked in the foreground. However, a new start-fg subcommand was added in version 3.3.

Consider the following Dockerfile as a template.

FROM alpine:latest
RUN apk add --no-cache postfix
EXPOSE 25
CMD ["postfix", "start-fg"]

To publish this service on an interface like 10.0.0.1, try:

sudo docker build --tag postfix .
sudo docker run --detach --name my-postfix \
  --restart=always \
  --publish 10.0.0.1:25:25 \
  postfix


Usage

For unencrypted and unauthenticated connections, try a connection string like smtp+insecure+none://example.com:25.

When running a server that listens on port 465, with


Configuration

Before trying to configure Postfix, ensure that you understand the design of Postfix.

See also encryption and authentication.

Receiving Mail

Set myhostname and mydomain to the fully-qualified names. Set mydomains to the set of all 'trusted' networks. Set mydestination to the set of all domains that should be considered 'local'.

myhostname = www1.example.com
mydomain = example.com
mynetworks = 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
mydestination = $myhostname $mydomain www.$mydomain localhost localhost.localdomain

By default mail is only accepted...

  • from clients in trusted networks ($mynetworks)

  • from clients that authenticated with SASL
  • for remote addresses matching $relay_domains

  • for local addresses found in $mydestination (defaulting to $myhostname, localhost.$mydomain, and localhost)

To adjust restrictions, try configuring smtpd_relay_restrictions or (the older and less-preferred method) smtpd_recipient_restrictions.

Routing Mail

To route mail based on the recipient domain, try:

transport_maps = lmdb:/etc/postfix/transport

A transport(5) file (i.e. /etc/postfix/transport) looks like:

admin@localhost      relay:[smtp.gmail.com]:587
service1.example.com lmtp:unix:/path/to/service.sock
example.com          lmtp:0.0.0.0:24
.example.com         lmtp:0.0.0.0:24
localhost            local
.localdomain         local
*                    relay:[smtp.gmail.com]:587

The first part of each line is a pattern. The second part is an instruction:

  • a local instruction attempts local delivery to the specified address

    • a bare local instruction expands to the local_transport setting, which itself defaults to local:$myhostname

  • a lmtp instruction forwards mail to an LMTP server

  • a smtp instruction forwards mail to an SMTP server

  • a relay instruction causes mail to relayed

Bracketing an address prevents a MX record lookup; the A record alone is looked up and used naively. If even A record lookup should be skipped (i.e. for a name defined in the hosts file), additionally specify smtp_dns_support_level = disabled.

Domains prefixed with a dot (.) are a pattern for all subdomains. The example above captures localhost and *.localdomain for local delivery.

The asterisk (*) domain is a fallback route, used only if nothing else matches.

The matching happens in the hierarchical order shown above: by full address, then by full domain part, then by subdomain part, and finally the fallback.

Run postmap /etc/postfix/transport and a hashed file will be produced. If your postmap(1) does not use LMDB, replace the lmdb: with whatever algorithm was used.

Address Rewriting

See here.

Posting Mail

master(8) expects mail posted locally to use $myhostname as the sender's domain. To override this, set myorigin.

myorigin = $mydomain


Administration

Testing the service

Install mailx and send an empty email.

To test mail relay to external hosts, try:

mail -s 'Test Email' '[email protected]' </dev/null

Alternatively, try using telnet.

Reviewing the queue

Two useful administrative utilities exist for reviewing the mail queue: postqueue(1) and postcat(1).

To view the mail queue, try:

postqueue -p

This will display the queued messages, the senders and recipients, and a mail ID.

To force all queued mail to be sent now, run:

postqueue -f

To instead force a singular message to be send now, run:

postqueue -i MAILID

To instead inspect a message in the queue, try:

postcat -vq MAILID


See also

postfix(1)

Postfix project documentation


CategoryRicottone

Postfix (last edited 2025-02-18 00:11:40 by DominicRicottone)