Differences between revisions 12 and 13
Revision 12 as of 2023-05-26 19:36:02
Size: 12516
Comment:
Revision 13 as of 2023-05-26 20:34:46
Size: 13139
Comment:
Deletions are marked like this. Additions are marked like this.
Line 153: Line 153:
Mail is received, routed, and queued by `master(8)`.

Set `myhostname` and `mydomain` to the fully-qualified names.
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'.
Line 160: Line 158:
}}} 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`.
Line 171: Line 180:
mydestination = www1.$mydomain localhost localhost.localdomain

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


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


Configuration

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.


Local Delivery

master(8) interprets these addresses as local: $myhostname, localhost.$mydomain, and localhost. To override this, set mydestination.

Alternatively, see Address Rewriting below and plan to re-route $myhostname.

If mail is destined for the local host, it is queued for local(8) to handle. (Any of bounce(8), defer(8) or trace(8) may then be called.)

The local part of the email address is extracted and casefolded to lowercase.

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

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 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.

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.

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.


Address Rewriting

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.


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)