# Postfix

Related articles

- PostFix Howto With SASL
- Amavis
- Virtual user mail system
- Courier MTA
- Exim
- OpenSMTPD
- OpenDMARC
- OpenDKIM

From Postfix's site:

  Postfix attempts to be fast, easy to administer, and secure, while at the same time being sendmail compatible enough to not upset existing users. Thus, the outside has a sendmail-ish flavor, but the inside is completely different.

The goal of this article is to setup Postfix and explain what the basic configuration files do. There are instructions for setting up local system user-only delivery and a link to a guide for virtual user delivery.

## Installation

Install the postfix package.

## Configuration

### master.cf

`/etc/postfix/master.cf` is the master configuration file where you can specify what kinds of protocols you will serve. It is also the place where you can put your new pipes e.g. to check for Spam!

It is recommended to enable secure SMTP as described in #Secure SMTP.

See this page for more information about encrypting outgoing and incoming email.

### main.cf

This article or section needs language, wiki syntax or style improvements.

Reason: Needs some cleanup (Discuss in Talk:Postfix#)

`/etc/postfix/main.cf` is the main configuration file where everything is configured. The settings below are recommended for virtual local-only delivery.

- `myhostname` should be set if your mail server has multiple domains, and you do not want the primary domain to be the mail host. You should have both a DNS A record and an MX record point to this hostname.

      myhostname = mail.nospam.net

- `mydomain` is usually the value of `myhostname`, minus the first part. If your domain is wonky, then just set it manually.

      mydomain = nospam.net

- `myorigin` is where the email will be seen as being sent from. I usually set this to the value of `mydomain`. For simple servers, this works fine. This is for mail originating from a local account. Since we are not doing local delivery (except sending), then this is not really as important as it normally would be.

      myorigin = $mydomain

- `mydestination` is the lookup for local users.

      mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain

- `mynetworks` and `mynetworks_style` control relaying, and whom is allowed to. We do not want any relaying.

  For our sakes, we will simply set `mynetwork_style` to host, as we are trying to make a standalone Postfix host, that people will use webmail on. No relaying, no other MTA's. Just webmail.

      mynetworks_style = host

- `relaydomains` controls the destinations that Postfix will relay TO. The default value is empty. This should be fine for now.

      relay_domains =

- `home_mailbox` or `mail_spool_directory` control how mail is delivered/stored for the users.

  If set, `mail_spool_directory` specifies an absolute path where mail gets delivered. By default Postfix stores mails in `/var/spool/mail`.

      mail_spool_directory = /home/vmailer

  Alternatively, if set, `home_mailbox` specifies a mailbox relative to the user's home directory where mail gets delivered (eg: /home/vmailer).

  Courier-IMAP requires "Maildir" format, so you must set it like the following example with trailing slash:

      home_mailbox = Maildir/

Warning: If you plan on implementing SSL/TLS, please respond safely to POODLE and FREAK/Logjam by adding the following to your configuration:

    smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
    smtp_tls_mandatory_protocols=!SSLv2,!SSLv3
    smtpd_tls_protocols=!SSLv2,!SSLv3
    smtp_tls_protocols=!SSLv2,!SSLv3
    smtpd_tls_exclude_ciphers = aNULL, eNULL, EXPORT, DES, RC4, MD5, PSK, aECDH, EDH-DSS-DES-CBC3-SHA, EDH-RSA-DES-CDC3-SHA, KRB5-DE5, CBC3-SHA

Then, generate a dhparam file by following these instructions and then adding the following to your configuration:

    smtpd_tls_dh1024_param_file = ${config_directory}/dhparams.pem

#### Default message and mailbox size limits

Postfix imposes both message and mailbox size limits by default. The message_size_limit controls the maximum size in bytes of a message, including envelope information. (default 10240000) The mailbox_size_limit controls the maximum size of any local individual mailbox or maildir file. This limits the size of any file that is written to upon local delivery, including files written by external commands (i.e. procmail) that are executed by the local delivery agent. (default is 51200000, set to 0 for no limit) If bounced message notifications are generated, check the size of the local mailbox under `/var/spool/mail` and use postconf to check these size limits:

    # postconf mailbox_size_limit
    mailbox_size_limit = 51200000
    # postconf message_size_limit
    message_size_limit = 10240000

### Aliases

You can specify aliases (also known as forwarders) in `/etc/postfix/aliases`.

You need to map all mail addressed to root to another account since it is not a good idea to read mail as root.

Uncomment the following line, and change `you` to a real account.

    root: you

Once you have finished editing `/etc/postfix/aliases` you must run the postalias command:

    postalias /etc/postfix/aliases

For later changes you can use:

    newaliases

Tip: Alternatively you can create the file `~/.forward`, e.g. `/root/.forward` for root. Specify the user to whom root mail should be forwarded, e.g. user@localhost.

    /root/.forward

    user@localhost

### Local mail

To only deliver mail to local system users (that are in `/etc/passwd`) update `/etc/postfix/main.cf` to reflect the following configuration. Uncomment, change, or add the following lines:

    myhostname = localhost
    mydomain = localdomain
    mydestination = $myhostname, localhost.$mydomain, localhost
    inet_interfaces = $myhostname, localhost
    mynetworks_style = host
    default_transport = error: outside mail is not deliverable

All other settings may remain unchanged. After setting up the above configuration file, you may wish to set up some #Aliases and then #Start Postfix.

### Virtual mail

Virtual mail is mail that does not map to a user account (`/etc/passwd`).

See Virtual user mail system for a comprehensive guide how to set it up.

### DNS records

An MX record should point to the mail host. Usually this is done from configuration interface of your domain provider.

A mail exchanger record (MX record) is a type of resource record in the Domain Name System that specifies a mail server responsible for accepting email messages on behalf of a recipient's domain.

When an e-mail message is sent through the Internet, the sending mail transfer agent queries the Domain Name System for MX records of each recipient's domain name. This query returns a list of host names of mail exchange servers accepting incoming mail for that domain and their preferences. The sending agent then attempts to establish an SMTP connection to one of these servers, starting with the one with the smallest preference number, delivering the message to the first server with which a connection can be made.

Note: Some mail servers will not deliver mail to you if your MX record points to a CNAME. For best results, always point an MX record to an A record definition. For more information, see e.g. Wikipedia's List of DNS Record Types.

### Check configuration

Run the `postfix check` command. It should output anything that you might have done wrong in a config file.

To see all of your configs, type `postconf`. To see how you differ from the defaults, try `postconf -n`.

## Start Postfix

Note: You must run `newaliases` at least once for postfix to run, even if you did not set up any #Aliases.

Start/enable the `postfix.service`.

## Testing

This article or section needs language, wiki syntax or style improvements.

Reason: Needs some cleanup. There are probably more general ways to write this. (Discuss in Talk:Postfix#)

Now lets see if Postfix is going to deliver mail for our test user.

    nc servername 25
    helo testmail.org
    mail from:<test@testmail.org>
    rcpt to:<cactus@virtualdomain.tld>
    data
    This is a test email.
    .
    quit

### Error response

    451 4.3.0 <lisi@test.com>:Temporary lookup failure

Maybe you have entered the wrong user/password for MySQL or the MySQL socket is not in the right place.

This error will also occur if you neglect to run newaliases at least once before starting postfix. MySQL is not required for local only usage of postfix.

    550 5.1.1 <email@spam.me>: Recipient address rejected: User unknown in virtual mailbox table.

Double check content of mysql_virtual_mailboxes.cf and check the main.cf for mydestination

### See that you have received a email

Now type `$ find /home/vmailer`.

You should see something like the following:

    /home/vmailer/virtualdomain.tld/cactus@virtualdomain.tld
    /home/vmailer/virtualdomain.tld/cactus@virtualdomain.tld/tmp
    /home/vmailer/virtualdomain.tld/cactus@virtualdomain.tld/cur
    /home/vmailer/virtualdomain.tld/cactus@virtualdomain.tld/new
    /home/vmailer/virtualdomain.tld/cactus@virtualdomain.tld/new/1102974226.2704_0.bonk.testmail.org

The key is the last entry. This is an actual email, if you see that, it is working.

## Extra

### PostfixAdmin

To use PostfixAdmin, you need a working Apache/MySQL/PHP setup as described in Apache HTTP Server.

For IMAP functionality, you will need to install php-imap and uncomment imap.so in /etc/php/php.ini

Next, install postfixadmin.

This article or section needs language, wiki syntax or style improvements.

Reason: in-code comments (Discuss in Talk:Postfix#)

Edit the PostfixAdmin configuration file:

    /etc/webapps/postfixadmin/config.inc.php

    $CONF['configured'] = true;
    // correspond to dovecot maildir path /home/vmail/%d/%u
    $CONF['domain_path'] = 'YES';
    $CONF['domain_in_mailbox'] = 'NO';
    $CONF['database_type'] = 'mysql';
    $CONF['database_host'] = 'localhost';
    $CONF['database_user'] = 'postfix_user';
    $CONF['database_password'] = 'hunter2';
    $CONF['database_name'] = 'postfix_db';

    // globally change all instances of ''change-this-to-your.domain.tld''
    // to an appropriate value

If installing dovecot and you changed the password scheme in dovecot (to SHA512-CRYPT for example), reflect that with postfix

    /etc/webapps/postfixadmin/config.inc.php

    $CONF['encrypt'] = 'dovecot:SHA512-CRYPT';

As of dovecot 2, dovecotpw has been deprecated. You will also want to ensure that your config reflects the new binary name.

    /etc/webapps/postfixadmin/config.inc.php

    $CONF['dovecotpw'] = "/usr/sbin/doveadm pw";

Create the Apache configuration file:

    /etc/httpd/conf/extra/httpd-postfixadmin.conf

    Alias /postfixadmin "/usr/share/webapps/postfixAdmin"
    <Directory "/usr/share/webapps/postfixAdmin">
        DirectoryIndex index.html index.php
        AllowOverride All
        Options FollowSymlinks
        Require all granted
    </Directory>

To only allow localhost access to postfixadmin (for heightened security), add this to the previous <Directory> directive:

       Order Deny,Allow
       Deny from all
       Allow from 127.0.0.1

Now, include httpd-postfixadmin.conf to `/etc/httpd/conf/httpd.conf`:

    # PostfixAdmin configuration
    Include conf/extra/httpd-postfixadmin.conf

Note: If you go to yourdomain/postfixadmin/setup.php and it says do not find config.inc.php, add `/etc/webapps/postfixadmin` to the `open_basedir` line in `/etc/php/php.ini`.
Note: If you get a blank page check the syntax of the file with `php -l /etc/webapps/postfixadmin/config.inc.php`.

### Secure SMTP

For more information, see Postfix TLS Support.

#### STARTTLS over SMTP (port 587)

To enable STARTTLS over SMTP (port 587, the proper way of securing SMTP), add the following lines to `main.cf`

    /etc/postfix/main.cf

    smtpd_tls_security_level = may
    smtpd_tls_cert_file = /path/to/cert.pem
    smtpd_tls_key_file = /path/to/key.pem

Also in `master.cf` find and remove the comment from the following line to enable the service on that port:

    /etc/postfix/master.cf

    submission inet n       -       n       -       -       smtpd

If you need support for the deprecated SMTPS port 465, read the next section.

#### SMTPS (port 465)

The deprecated method of securing SMTP is using the wrapper mode which uses the system service smtps as a non-standard service and runs on port 465.

To enable it uncomment the following lines in

    /etc/postfix/master.cf

    smtps     inet  n       -       n       -       -       smtpd
      -o smtpd_tls_wrappermode=yes
      -o smtpd_sasl_auth_enable=yes

And verify that these lines are in `/etc/services`:

    smtps 465/tcp # Secure SMTP
    smtps 465/udp # Secure SMTP

If they are not there, go ahead and add them (replace the other listing for port 465). Otherwise Postfix will not start and you will get the following error:

    postfix/master[5309]: fatal: 0.0.0.0:smtps: Servname not supported for ai_socktype

### SpamAssassin

Install the spamassassin package.

Go over `/etc/mail/spamassassin/local.cf` and configure it to your needs.

#### Spam Assassin rule update

Update the SpamAssassin matching patterns and compile them:

    # sa-update
    # sa-compile

You will want to run this periodically, the best way to do so is by setting up a Systemd/Timers.

Create the following service, which will run these commands:

    /etc/systemd/system/spamassassin-update.service

    [Unit]
    Description=spamassassin housekeeping stuff

    [Service]
    User=spamd
    Group=spamd
    Type=oneshot
    ExecStart=-/usr/bin/vendor_perl/sa-update --allowplugins #You can remove the allowplugins options if you do not want direct plugin updates from SA.
    ExecStart=-/usr/bin/vendor_perl/sa-compile
    # You can automatically train SA's bayes filter by uncommenting this line and specifying the path to a mailbox where you store email that is spam (for ex this could be yours or your users manually reported spam)
    #ExecStart=-/usr/bin/vendor_perl/sa-learn --spam <path to your spam>

Then create the timer, which will execute the previous service daily:

    /etc/systemd/system/spamassassin-update.timer

    [Unit]
    Description=spamassassin house keeping

    [Timer]
    OnCalendar=daily
    Persistent=true

    [Install]
    WantedBy=timers.target

Finally, you'll need to modify your Spamassassin systemd service file so that it knows to restart itself to read the new rules. Copy the bundled service file to a custom service file:

    # cp /usr/lib/systemd/system/spamassassin.service /etc/systemd/system

And edit the newly created `/etc/systemd/system/spamassassin.service` to include:

    [Unit]
    PartOf=spamassassin-update.service

This will ensure that Spamassassin's spamd is restarted just before the timer runs. This means the rules will be available the next day if your timer runs daily. This is so that there is no long service interruption while `sa.service` runs as it takes a while to compile rules.

Now you can start and enable `spamassassin-update.service`.

#### SpamAssassin stand-alone generic setup

Note: If you want to combine SpamAssassin and Dovecot Mail Filtering, ignore the next two lines and continue further down instead.

Edit `/etc/postfix/master.cf` and add the content filter under smtp.

    smtp      inet  n       -       n       -       -       smtpd
      -o content_filter=spamassassin

Also add the following service entry for SpamAssassin

    spamassassin unix -     n       n       -       -       pipe
      flags=R user=spamd argv=/usr/bin/vendor_perl/spamc -e /usr/bin/sendmail -oi -f ${sender} ${recipient}

Now you can start `spamassassin.service`.

#### SpamAssassin combined with Dovecot LDA / Sieve (Mailfiltering)

Set up LDA and the Sieve-Plugin as described in Dovecot#Sieve. But ignore the last line `mailbox_command...` .

Instead add a pipe in `/etc/postfix/master.cf`:

     dovecot   unix  -       n       n       -       -       pipe
           flags=DRhu user=vmail:vmail argv=/usr/bin/vendor_perl/spamc -u spamd -e /usr/lib/dovecot/dovecot-lda -f ${sender} -d ${recipient}

And activate it in `/etc/postfix/main.cf`:

     virtual_transport = dovecot

#### SpamAssassin combined with Dovecot LMTP / Sieve

Set up the LMTP and Sieve as described in Dovecot#Sieve.

Edit `/etc/dovecot/conf.d/90-plugins.conf` and add:

     sieve_before = /etc/dovecot/sieve.before.d/
     sieve_extensions = +vnd.dovecot.filter
     sieve_plugins = sieve_extprograms
     sieve_filter_bin_dir = /etc/dovecot/sieve-filter
     sieve_filter_exec_timeout = 120s #this is often needed for the long running spamassassin scans, default is otherwise 10s

Create the directory and put spamassassin in as a binary that can be ran by dovecot:

     # mkdir /etc/dovecot/sieve-filter
     # ln -s /usr/bin/vendor_perl/spamc /etc/dovecot/sieve-filter/spamc

Create a new file, `/etc/dovecot/sieve.before.d/spamassassin.sieve` which contains:

     require [ "vnd.dovecot.filter" ];
     filter "spamc" [ "-d", "127.0.0.1", "--no-safe-fallback" ];

Compile the sieve rules `spamassassin.svbin`:

     # cd /etc/dovecot/sieve.before.d
     # sievec spamassassin.sieve

Finally, restart `dovecot.service`.

#### Call ClamAV from SpamAssassin

Install and setup clamd as described in ClamAV.

Follow one of the above instructions to call SpamAssassin from within your mail system.

Install the perl-cpanplus-dist-arch package. Then install the ClamAV perl library as follows:

     # /usr/bin/vendor_perl/cpanp -i File::Scan::ClamAV

Add the 2 files from http://wiki.apache.org/spamassassin/ClamAVPlugin into `/etc/mail/spamassassin/`. Edit `/etc/mail/spamassassin/clamav.pm` and update `$CLAM_SOCK` to point to your Clamd socket location (default is `/var/lib/clamav/clamd.sock`).

Finally, restart `spamassassin.service`.

### Using Razor

Make sure you have installed SpamAssassin first, then:

Install the razor package.

Register with Razor.

     # mkdir /etc/mail/spamassassin/razor
     # chown spamd:spamd /etc/mail/spamassassin/razor
     # sudo -u spamd -s
     $ razor-admin -home=/etc/mail/spamassassin/razor -register
     $ razor-admin -home=/etc/mail/spamassassin/razor -create
     $ razor-admin -home=/etc/mail/spamassassin/razor -discover

Tell SpamAssassin about Razor, add

     razor_config /etc/mail/spamassassin/razor/razor-agent.conf

to `/etc/mail/spamassassin/local.cf`.

Tell Razor about itself, add

     razorhome = /etc/mail/spamassassin/razor/

to `/etc/mail/spamassassin/razor/razor-agent.conf`

Finally, restart `spamassassin.service`.

### Hide the sender's IP and user agent in the Received header

This is a privacy concern mostly, if you use Thunderbird and send an email. The received header will contain your LAN and WAN IP and info about the email client you used. (Original source: AskUbuntu) What we want to do is remove the Received header from outgoing emails. This can be done by the following steps:

Add this line to main.cf

    smtp_header_checks = regexp:/etc/postfix/smtp_header_checks

Create /etc/postfix/smtp_header_checks with this content:

    /^Received: .*/     IGNORE
    /^User-Agent: .*/   IGNORE

Finally, restart postfix.service

### Postfix in a chroot jail

Postfix is not put in a chroot jail by default. The Postfix documentation [1] provides details about how to accomplish such a jail. The steps are outlined below and are based on the chroot-setup script provided in the postfix source code.

First, go into the `master.cf` file in the directory `/etc/postfix` and change all the chroot entries to 'yes' (y) except for the services `qmgr`, `proxymap`, `proxywrite`, `local`, and `virtual`

Second, create two functions that will help us later with copying files over into the chroot jail (see last step)

    CP="cp -p"

    cond_copy() {
      # find files as per pattern in $1
      # if any, copy to directory $2
      dir=`dirname "$1"`
      pat=`basename "$1"`
      lr=`find "$dir" -maxdepth 1 -name "$pat"`
      if test ! -d "$2" ; then exit 1 ; fi
      if test "x$lr" != "x" ; then $CP $1 "$2" ; fi
    }

Next, make the new directories for the jail:

    set -e
    umask 022

    POSTFIX_DIR=${POSTFIX_DIR-/var/spool/postfix}
    cd ${POSTFIX_DIR}

    mkdir -p etc lib usr/lib/zoneinfo
    test -d /lib64 && mkdir -p lib64

Find the localtime file

    lt=/etc/localtime
    if test ! -f $lt ; then lt=/usr/lib/zoneinfo/localtime ; fi
    if test ! -f $lt ; then lt=/usr/share/zoneinfo/localtime ; fi
    if test ! -f $lt ; then echo "cannot find localtime" ; exit 1 ; fi
    rm -f etc/localtime

Copy localtime and some other system files into the chroot's etc

    $CP -f $lt /etc/services /etc/resolv.conf /etc/nsswitch.conf etc
    $CP -f /etc/host.conf /etc/hosts /etc/passwd etc
    ln -s -f /etc/localtime usr/lib/zoneinfo

Copy required libraries into the chroot using the previously created function `cond_copy`

    cond_copy '/usr/lib/libnss_*.so*' lib
    cond_copy '/usr/lib/libresolv.so*' lib
    cond_copy '/usr/lib/libdb.so*' lib

And don't forget to reload postfix.

### Rule-based mail processing

With policy services one can easily finetune postfix' behaviour of mail delivery. postfwd and policydAUR provide services to do so. This allows you to e.g. implement time-aware grey- and blacklisting of senders and receivers as well as SPF policy checking.

Policy services are standalone services and connected to Postfix like this:

    /etc/postfix/main.cf

    smtpd_recipient_restrictions =
      ...
      check_policy_service unix:/run/policyd.sock
      check_policy_service inet:127.0.0.1:10040

Placing policy services at the end of the queue reduces load, as only legitimate mails are processed. Be sure to place it before the first permit statement to catch all incoming messages.

### DANE (DNSSEC)

#### Resource Record

Warning: This is not a trivial section. Be aware that you make sure you know what you are doing. You better read Common Mistakes before.

DANE supports several types of records, however not all of them are suitable in postfix.

Certificate usage 0 is unsupported, 1 is mapped to 3 and 2 is optional, thus it is recommendet to publish a "3" record. More on Resource Records.

#### Configuration

Opportunistic DANE is configured this way:

    /etc/postfix/main.cf

    smtpd_use_tls = yes
    smtp_dns_support_level = dnssec
    smtp_tls_security_level = dane

    /etc/postfix/master.cf

    dane       unix  -       -       n       -       -       smtp
      -o smtp_dns_support_level=dnssec
      -o smtp_tls_security_level=dane

To use per-domain policies, e.g. opportunistic DANE for example.org and mandatory DANE for example.com, use something like this:

    /etc/postfix/main.cf

    indexed = ${default_database_type}:${config_directory}/

    # Per-destination TLS policy
    #
    smtp_tls_policy_maps = ${indexed}tls_policy

    # default_transport = smtp, but some destinations are special:
    #
    transport_maps = ${indexed}transport

    transport

    example.com dane
    example.org dane

    tls_policy

    example.com dane-only

Note: For global mandatory DANE, change `smtp_tls_security_level` to `dane-only`. Be aware that this makes postfix tempfail on all delivieres that do not use DANE at all!

Full documentation is found here.

## See also

- Out of Office for Squirrelmail
- Postfix Ubuntu documentation
- Use Gmail as an SMTP relay

Category:

- Mail server

Hidden category:

- Pages or sections flagged with Template:Style