Using Postfix

Table of Contents

1. Overview

Postfix is a mailer daemon maintained by Wietse Venema. It is an open source
project, and was created as an alternative to Sendmail. It is a drop-in
replacement for Sendmail, and includes a ‘sendmail’ wrapper that acts as
a Sendmail program, and allows programs to function with it as if it was
sendmail itself. More information, including FAQs and downloads are
available at

2. Why Postfix?

Postfix was designed from the beginning up with speed in mind. Postfix is
running on systems that send over 1,000,000 unique messages a day. Postfix
is also designed differently from Sendmail. Instead of one single, monolithic
binary, Postfix is split up into several smaller programs, which run at
lowered privileges, each of which handles a specific task. There are no
setuid binaries in Postfix, and only one setgid binary. What this means is,
there are less chances for root exploit through postfix.

Postfix is also much easier to configure than Sendmail. it uses a plaintext
configuration file, (no m4 needed) and can be reloaded on the fly without
shutting down.

Postfix also supports alias, virtualhosts, and other databases in several
formats, such as plaintext (hash), berkeley DB, or even MySQL. This provides
more options when setting up mail services for systems with many users and
multiple domains.

3. Installing Postfix

The postfix install is very simple. Most distributions provide packages
for postfix, and if they don’t, simply download the tarball (latest
stable version as of this writing is 2.0.4) and unpack it. then simply run

# make

to compile it. After compilation, make sure you back up your old sendmail:

# mv /usr/sbin/sendmail /usr/sbin/sendmail.OFF
# mv /usr/bin/newaliases /usr/bin/newaliases.OFF
# mv /usr/bin/mailq /usr/bin/mailq.OFF
# chmod 755 /usr/sbin/sendmail.OFF /usr/bin/newaliases.OFF \


Next, make sure you add a postfix user for postfix to run as.
Either add the line


to your /etc/passwd, or run

# useradd -d /no/where -d /no/where -s /no/shell postfix

Next, add a postdrop group. Note that, no user should be a member of this
group, not even the postfix user. This is the group postfix will setgid to
when doing mail delivery.

# groupadd postdrop

Now run:

# make install

This will run an interactive install script, and prompt you where to install
things. The rest of this guide will assume you install stuff to the default
install place.

3.1. Running Postfix

To start the postfix daemon simply run:

# postfix start

Likewise, to stop it, simply:

# postfix stop

To regenerate the aliases and virtual maps databases:

# newaliases

To force reload of the config file:

# postfix reload

To have all queued mail to be flushed out of the queue and attempt delivering
it again:

# postfix flush

4. Configuration

Postfix keeps all its configuration in /etc/postfix (unless you specified
otherwise during install) The main Postfix config file is A default
config file will be provided for you with comments. You only need to edit a
few thing and you will be ready to run Postfix.

Files: Main config file for postfix config for the master postfix process, sets limits on its
child processes and functions. This is safe to leave
aliases this file contains the username aliases. useful for having
multiple email addresses point to the same user.
virtualhosts similar to aliases, except this allows you to specify
aliases per-domain instead of just for one domain. Useful
when running multiple domains.

4.1. configuration directive style

Directives in popstfix are in the style key = value.
String values don’t need to be quoted. You can use
the value of one directive in another, prefixed by a $.
for example:

mydestination = $myhostname, mail.$mydomain

Lists of comma-separated strings can be extended to multiple lines,
simply by ending a line with a comma.

Boolean values are yes/no.

4.2. Common configuration directives

soft_bounce When set to on, soft_bounce will not bounce any emails,
rather keep them in queue. this feature is great for
debugging, when you aren’t sure if your config is
correct. Make sure you turn this off when you are
done debugging, else your queue will fill up.
queue_directory the directory where postfix keeps its spools, usually
mail_owner The user to run lowered privilege postfix processes, usually
myhostname The hostname of the mail server, given out in the motd. if
not specified, gethostname() is used to find your hostname.
mydomain your local internet domain (ie if your myhostname is , mydomain should be
myorigin the domain that is appended to mail that originates locally.
inet_interfaces set to all to listen on all interfaces, set to an IP or
hostname of an interface or interfaces to bind to otherwise,
comma separated.
mydestination domains to accept mail for, comma separated.
alias_maps this is a file or list of files that map username aliases.
types of files include dbm, hash (plain text), or even mysl.
for example:
alias_maps = hash:/etc/postfix/aliases,dbm:/etc/aliases.db
mail_spool_directory here the mail spool is kept. usually /var/spool/mail
mailbox_command if specified, you can choose another delivery agent, ie
procmail. to set procmail as your delivery agent, use:
mailbox_command = /some/where/procmail
smtpd_banner if specified, you can tell postfix to send an alternate
banner when you connect. ie:
smtpd_banner = $myhostname ESMTP $mail_name

5. Spam, or how I learned to stop worrying and love the RBL

There are several ways to block spam. You can pipe your mail through a spam
filter, something like procmail or bogofilter, or use an RBL. an RBL is a
list of domains to deny mail from, usually maintained by a third party. These
parties usually list known open relays and spammers. Some charge you, but a
good bit of them are free. Postfix has a smtpd_client_restrictions directive
where you can specify options for blocking. for example:

smtpd_client_restrictions = reject_maps_rbl, reject_unknown_client

The reject_unknown_client rejects mail if the postfix server cannot determine
the client’s hostname. This will not block many spam mails, but it’ll block

The reject_maps_rbl tells postfix to use an RBL list when deciding whether
or not to block a domain. you then use the maps_rbl_domains to specify what
RBL lists to use. ie:

maps_rbl_domains =

an RBL list is simply a DNS server that you can query with the domain name in
question. if the domain name matches, then that domain is in the RBL list,
and postfix will deny mail from that domain. More info on RBL’s can be found
by looking at the links at the bottom of this document.

Another thing you can do is specify a smtp_sender_restrictions directive. this
directive allows you to set what sender addresses are blocked. this is
another way of blocking common spam. You can specify any number of the
following restrictions, as well as a map or maps.

The restrictions are: (taken from the postfix sample configurations)

  • permit_mynetworks: permit if the client address matches $mynetworks.
  • reject_unknown_client: reject the request if the client hostname is
  • reject_maps_rbl: reject if the client is listed under $maps_rbl_domains.
  • reject_invalid_hostname: reject HELO hostname with bad syntax.
  • reject_unknown_hostname: reject HELO hostname without DNS A or MX record.
  • reject_unknown_sender_domain: reject sender domain without A or MX record.
  • check_sender_access maptype:mapname
  • maptype:mapname: look up sender address, parent domain, or localpart@.
    Reject if result is REJECT or "[45]xx text"

    Permit if result is OK or all numerical.

for example:

smtpd_sender_restrictions = reject_unknown_sender_domain,

6. Fun with lookup tables (maps)

Postfix supports a lot more than simply hash maps. You can do maps using dbm,
regular expressions (either PCRE or standard type), even mysql, or even ldap.

For example, you might want to use regular expressions in your access map.
you could tell smtpd_sender_restrictions to use
pcre:/etc/postfix/access-regexp as its map.

Then you create an access-regexp file like this:

### file start: /etc/postfix/access-regexp
# Protect your outgoing majordomo exploders
/^(?!owner-)(.*)-outgoing@/550 Use ${1}@${2} instead

/^friend@(?!my\.domain)/550 Stick this in your pipe $0

550 Asia is a big spam house, mail from .$1 is not allowed.
####file end

Sure, you could implement the pattern matching through procmail or some other
mail delivery agent, but the mail will still be accepted by the mail daemon
(which will prompt the spammer to keep sending mail at your box, since the
spammer thinks he got through. Implementing pattern matching at the smtpd
level means

7. Resources