How to relay all mail to external account

Relay all mail to an external account which can come in handy in your lab environment.

I will forward all mail to using server, mail user and mail_token authentication token.

Update package index.

$ sudo apt install debconf

Ensure that debconf package is installed.

$ sudo apt install debconf

Store default postfix options.

$ cat << EOF | sudo debconf-set-selections
postfix postfix/mailname        string  bullseye
postfix postfix/main_mailer_type        select  No configuration

Install postfix mail server, libsasl2-modules sasl support, and mailutils utilities.

$ apt install postfix mailutils libsasl2-modules

Define default domain for mail utilities.

$ cat <<EOF | sudo tee /etc/mailutils.conf
address {

Alternatively, you can define an email address.

$ mail --config-help
# Configuration file structure for mail utility.
# For use in global configuration file (/etc/mailutils.conf), enclose it in
# `program mail { ... };
# For more information, use `info mail'.
tls-file-checks {
  # Configure safety checks for SSL key file.  Argument is a list or sequence
  # of check names optionally prefixed with '+' to enable or '-' to disable the
  # corresponding check.  Valid check names are:
  #   none          disable all checks
  #   all           enable all checks
  #   gwrfil        forbid group writable files
  #   awrfil        forbid world writable files
  #   grdfil        forbid group readable files
  #   ardfil        forbid world writable files
  #   linkwrdir     forbid symbolic links in group or world writable
  # directories
  #   gwrdir        forbid files in group writable directories
  #   awrdir        forbid files in world writable directories
  key-file <arg: list>;
  # Configure safety checks for SSL certificate.  See above for a description
  # of <arg>.
  cert-file <arg: list>;
  # Configure safety checks for SSL certificate authority file.  See above for
  # a description of <arg>.
  ca-file <arg: list>;

address {
  # Set the current user email address (default is loginname@defaultdomain).
  email-addr <email: address>;
  # Set e-mail domain for unqualified user names (default is this host)
  email-domain <domain: string>;

mailbox {
  # Use specified URL as a mailspool directory.
  mail-spool <url: string>;
  # Create mailbox URL using <pattern>.
  mailbox-pattern <pattern: string>;
  # Default mailbox type.
  mailbox-type <protocol: string>;
  # Default user mail folder
  folder <dir: string>;
  # Accuracy level of mailbox format autodetection. Argument is either a
  # decimal number or any of the following constants:
  #   auto    - set accuracy level from the environment variable
  #             MU_AUTODETECT_ACCURACY (default)
  #   fast    - do only a rough estimation of the mailbox format: fastest,
  #             but possibly inaccurate
  #   minimal - good balance between speed and accuracy
  autodetect-accuracy <n: number>;

locking {
  # Default locker flags (E=external, R=retry, T=time, P=pid).
  flags <arg: string>;
  # Set timeout for acquiring the lock.
  retry-timeout <arg: interval>;
  # Set the maximum number of times to retry acquiring the lock.
  retry-count <arg: integer>;
  # Expire locks older than this amount of time.
  expire-timeout <arg: interval>;
  # Use external locker program.
  external-locker <prog: string>;

# Include contents of the given file.  If a directory is given, include
# contents of the file <file>/<program>, where <program> is the name of the
# program.  This latter form is allowed only in the site-wide configuration
# file.
include <file-or-directory: string>;

Check configuration syntax.

$ mail --config-lint
mail: opening configuration file /etc/mailutils.conf
mail: parsing file `/etc/mailutils.conf'
mail: finished parsing file `/etc/mailutils.conf'
mail: opening configuration file /home/milosz/.mail
mail: configuration file /home/milosz/.mail doesn't exist

Store relay password.

$ cat <<EOF | sudo tee /etc/postfix/sasl_passwd

Create a lookup table.

$ sudo postmap /etc/postfix/sasl_passwd

Secure relay password.

$ sudo chmod 600 /etc/postfix/sasl_passwd
$ sudo chmod 600 /etc/postfix/sasl_passwd.db

Create rules to alter destination address.

$ cat <<EOF | sudo tee /etc/postfix/header_checks
/^To:.*@/ DISCARD

Create a lookup table.

$ sudo postmap /etc/postfix/header_checks

Create postfix configuration.

$ cat <<EOF | sudo tee /etc/postfix/
myorigin = \$myhostname
mynetworks =
mydestination =
inet_interfaces = loopback-only

compatibility_level = 2

header_checks = regexp:/etc/postfix/header_checks

relayhost = []:587

smtp_use_tls = yes
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt

Display smtpd service configuration.

$ sudo postconf -M smtp
smtp       inet  n       -       y       -       -       smtpd
smtp       unix  -       -       y       -       -       smtp

Ensure that smtpd service will be not listening.

$ sudo postconf -M# smtp/inet

These changes will be reflected in configuration file.

$ cat /etc/postfix/
# Postfix master process configuration file.  For details on the format
# of the file, see the master(5) manual page (command: "man 5 master" or
# on-line:
# Do not forget to execute "postfix reload" after editing this file.
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)          
# ==========================================================================
#smtp      inet  n       -       y       -       -       smtpd
#smtp      inet  n       -       y       -       1       postscreen
#smtpd     pass  -       -       y       -       -       smtpd
#dnsblog   unix  -       -       y       -       0       dnsblog
#tlsproxy  unix  -       -       y       -       0       tlsproxy

Restart postfix service.

$ sudo systemctl restart postfix

Send mail to another local user – it will be delivered to

$ whoami | mail --subject "$(hostname -f): who am i" root
Jun 15 09:27:24 bullseye postfix/pickup[24069]: A8C56C011B: uid=1000 from=<>
Jun 15 09:27:24 bullseye postfix/cleanup[24634]: A8C56C011B: redirect: header To: <> from local; from=<>:
Jun 15 09:27:24 bullseye postfix/cleanup[24634]: A8C56C011B: message-id=<20210615092724.A8C56C011B@bullseye.localdomain>
Jun 15 09:27:24 bullseye postfix/qmgr[22577]: A8C56C011B: from=<>, size=369, nrcpt=1 (queue active)
Jun 15 09:27:25 bullseye postfix/smtp[24636]: A8C56C011B: to=<>, orig_to=<>,[]:587, delay=1.2, delays=0.02/0/0.84/0.36, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as BCC92240009)
Jun 15 09:27:25 bullseye postfix/qmgr[22577]: A8C56C011B: removed

Send mail to another address in domain – it will be delivered to

$ whoami | mail --subject "$(hostname -f): who am i"
Jun 15 09:28:52 bullseye postfix/pickup[24069]: E3D8EC011B: uid=1000 from=<>
Jun 15 09:28:52 bullseye postfix/cleanup[24634]: E3D8EC011B: redirect: header To: <> from local; from=<>:
Jun 15 09:28:52 bullseye postfix/cleanup[24634]: E3D8EC011B: message-id=<20210615092852.E3D8EC011B@bullseye.localdomain>
Jun 15 09:28:52 bullseye postfix/qmgr[22577]: E3D8EC011B: from=<>, size=371, nrcpt=1 (queue active)
Jun 15 09:28:54 bullseye postfix/smtp[24636]: E3D8EC011B: to=<>, orig_to=<>,[]:587, delay=1.4, delays=0.01/0/1/0.38, dsn=2.0.0, status=sent (250 2.0.0 Ok: queued as 3173060016)
Jun 15 09:28:54 bullseye postfix/qmgr[22577]: E3D8EC011B: removed

Send mail to another address in a different domain – it will be discarded.

$ whoami | mail --subject "who am i"
Jun 15 09:28:23 bullseye postfix/pickup[24069]: 580DEC011B: uid=1000 from=<>
Jun 15 09:28:23 bullseye postfix/cleanup[24634]: 580DEC011B: discard: header To: <> from local; from=<>

This solution is not bulletproof, but it does the job.