The Book of
Postfix

Errata

Nobody's perfect! If you found a bug in our book tell us so we can tell everybody. Use errata@postfix-book.com to get in contact with us.

Last Updated on June 28th, 2006 by Ralf Hildebrandt

Fedora Core 3 (credits: David Baker)

I did want to mention that in Fedora Core 3, the install of Postfix (rpm from CD ISO) seems to want to use the /etc/aliases file instead of the /etc/postfix/aliases as your book shows. I know this is probably a RH/Fedora thing, but I just wanted to mention it.

Page 19: last paragraph (credits: Jon Forrest)

Postfix will act as relay host for local clients,...

Page 21: second paragraph, first sentence (credits: Mark Andrews)

... would be set to root@$mydomain, ...

Page 27: at the bottom of the page (credits: Mike Cappella)

For example, if you ran Postfix on a machine with the IP addresses 192.0.34.166/30 and 127.0.0.1, ...

Page 32: at the top of the page (credits: Simon Barrett)

127.0.0.1/8 must be 127.0.0.0/8

Page 35: end of the first paragraph (credits: Rod Dorman)

..., so that you can you focus on individual goals.

Page 41: description of smtpd (credits: Mike Cappella)

After accepting a message, smtpd puts it into the incoming queue, where qmgr takes over.
must rather be the much simpler sentence:
smtpd hands the message down to cleanup.

Page 45: below second note (credits: Emanuele Vicentini)

Postfix queries entries in a predefined order specified in the access(5) manual pages for the tables (access(5), transport(5), virtual(5), aliases(5) and canonical(5)).

Page 46: in the paragraph immediately under "Determining the Number of Simultaneous Connections to a Database", line 5: (credits: Michael Durket)

the client is in our personal blacklist and should then by be denied

Page 46: last paragraph (credits: Emanuele Vicentini, Mark Andrews)

Remember thatAccording to the next section, one lookup results in between one (exact match found) and a number of queries that depends on the number of "." (dots) in the domain component (no match found) of the lookup key, so as an average we'll assume 3, so the number...

Page 47: How Postfix Queries Maps (credits: Emanuele Vicentini)

The lookup order described there only applies to access(5) type maps!

Page 75: examples at the top of the page (credits: Michael Durket)

"general restrictions" should be replaced with "generic restrictions" to be consistent with the subheading on page 71

Page 77: smtpd_soft_error_limit (credits: Rod Dorman)

If a client causes errors and the total number of errors in the current SMTP session is below or equal to the value of smtpd_soft_error_limit, each error causes a delay of smtpd_error_sleep_time.

Page 84 (credits: Emanuele Vicentini)

If Postfix feels responsible for the message destination, reject_unauth_destination returns DUNNOOK, and Postfix evaluates the next restriction.

Page 87: Envelope sender example (credits: Gary V)

An example of a complete envelope server sender is sender@example.com

Page 91: Note near the top (Credits: Victor Duchovni)

There's just one exception: You must accept mail for postmaster in non-FQDN form. The address postmaster is exempt from all recipient restrictions (including delayed client/helo/sender restrictions), not just reject_non_fqdn_recipient.

Page 93: First example (credits: Mike Morris)
    smtpd_recipient_restrictions =
       reject_non_fqdn_recipient
       reject_non_fqdn_sender
       reject_unknown_sender_domain
       reject_unknown_recipient_domain
       check_recipient_access hash:/etc/postfix/roleaccount_exceptions
       permit_mynetworks
       reject_unauth_destination
       permit
    
must have check_recipient_access hash:/etc/postfix/roleaccount_exceptions after reject_unauth_destination:
    smtpd_recipient_restrictions =
       reject_non_fqdn_recipient
       reject_non_fqdn_sender
       reject_unknown_sender_domain
       reject_unknown_recipient_domain
       check_recipient_access hash:/etc/postfix/roleaccount_exceptions
       permit_mynetworks
       reject_unauth_destination
       check_recipient_access hash:/etc/postfix/roleaccount_exceptions
       permit
    
Page 93: Second example (credits: Timo Veith)
reject_multi_recipient_bounce should really go into smtpd_data_restrictions:

    smtpd_recipient_restrictions =
       reject_non_fqdn_recipient
       reject_non_fqdn_sender
       reject_unknown_sender_domain
       reject_unknown_recipient_domain
       permit_mynetworks
       reject_unauth_destination
       check_recipient_access hash:/etc/postfix/roleaccount_exceptions
       reject_multi_recipient_bounce
       reject_non_fqdn_hostname
       reject_invalid_hostname
       permit
    
Page 95: square instead of angular bracket (credits: Michael Durket)

specified as [ipv4address] (enclosed in angular square brackets) or as an IPv6 address, [ipv6:ipv6address], also enclosed in angular square brackets.

Page 96: check_sender_mx_access example (credits: Duncan Hill)

255.0.0.0/4 224.0.0.0/4 550 Mail server in class D multicast network

Page 97: Bounces to multiple recipient (credits: Timo Veith)

It can appear just about anywhere in the restriction list, but the following is an example where it appears after the permit_mynetworks option.in the smtpd_data_restrictions.

Page 99: Rejecting Blacklisted Clients example (credits: Duncan Hill)

Line 2 of the example listing should be indented.

Page 107: smtpd_recipient_restrictions list should not include reject_multi_recipient_bounce (Credits: Andrew Diederich)

smtpd_recipient_restrictions list should not include reject_multi_recipient_bounce. That goes in the smtpd_data_restrictions, like in the errata for page 98.

Page 107: (Credits: Andrew Diederich)

check_sender_mx_access /etc/postfix/verisign_mx_accesscidr:/etc/postfix/bogus_mx

The mx_access example is on page 96.

The smtpd_recipient_restrictions check_sender_access line in the example should be indented.

Page 113: Applying Checks to Separate Message Sections (credits: Ralf Hildebrandt)
The Caution Warning should start with this:

Using too many body_checks patterns can be very CPU-intensive, slowing down your...

reference to Figure 6-3 (credits: Ralf Hildebrandt)
The reference to Figure 6-3 was incomplete, or at least hard to follow. This makes it easier:

(see Figure 6-3 on page 61).

Page 123: (credits: Ralf Hildebrandt)

This action overrides content_filter settings in your main.cf file and requires you to configure different cleanup servers as well one before the filter, and one after the filter.make sure that the same *_checks are not being used at reinjection after the filter.

Page 124: (credits: Michael Durket)

The first line in the log example must read:
Apr 9 23:34:12 mail postfix/cleanup[12543]: 2B97315C00D: filter: header To: nofilter@example.comorg from client.example.com[10.0.0.1]; from=<sender@example.com> to=<nofilter@example.comorg> proto=ESMTP helo=<client.example.com>: nofilter:dummy

Page 134: (credits: Mike Cappella)

second line:
1. The smtpd configured with content_filter hands a message to cleanup, which then hands it to the queue manager.

Page 136: (credits: Tony Munday)

Notice that the transport type is inet this time, for an Internet transport (the preceding example was a Unix domain socket transport type).

Page 143: (credits: Bill Chmura)
  # groupadd filter
  # useradd -d /var/spool/altermime -G filter altermime
  
must be:
  # groupadd filter
  # useradd -d /var/spool/altermime -G filter filter
  
Page 144: (credits: Bill Chmura)

The script:

    $ALTERMIME --input=in.$$ \
               --disclaimer=/etc/postfix/disclaimer.txt \
               --disclaimer-html=/etc/postfix/disclaimer.txt \
               --xheader="X-Copyrighted-Material: Please visit http:// \
               www.example.com/message_disclaimer.html" || \
               { echo Message content rejected; exit $UNAVAILABLE; }
    
must have different pathnames for the disclaimer files:
    $ALTERMIME --input=in.$$ \
               --disclaimer=/etc/postfix/filter/disclaimer.txt \
               --disclaimer-html=/etc/postfix/filter/disclaimer.txt \
               --xheader="X-Copyrighted-Material: Please visit http:// \
               www.example.com/message_disclaimer.html" || \
               { echo Message content rejected; exit $UNAVAILABLE; }
    
That is /etc/postfix/filter/disclaimer.txt instead of just /etc/postfix/disclaimer.txt

Also, the reinjection command must use the -i argument to sendmail (Credits: Paul Badcock), otherwise any single dot on a line will terminate the sendmail command :
    # Call sendmail to reinject the message into Postfix
    $SENDMAIL -i "$@" <in.$$
    
Page 147: (credits: Ralf Hildebrandt)

The session example on top of page 147 lacks a blank line between the lines Subject: Testing disclaimer and
This is a test. There should be text at the bottom of this message

This results in a bodyless message.

Page 164: (credits: Ralf Hildebrandt)

The original smtpd listens to the amavisd-new replay reply,...

Page 170: (credits: Ralf Hildebrandt)

Set the host that mail will be relayed to (relayhost) (transport_maps)

Page 172: (credits: Andreas Hasenack)

If you want to explicitly deny relay access to a certain recipient, use an error code and message such as 554 Delivery not permitted instead of OK leave out the entry from the map.

Page 194: (credits: Michael Durket)

Because of the preceding entry, Postfix will accept mail for these addresses and deliver them to postmaster@example.com:

  • postmaster@$myorigin[$proxy_interfaces]
  • postmaster@[$inet_interfaces]
  • postmaster@$mydestination

Page 196: (credits: Patrick Koetter)

To create a mailbox user named vbox vuser with a user ID of 1000, run this command:

Page 205: (credits: Daniel Stellwagen)

After creating the 'mail' database and before creating the 'virtual_mailbox_domains' table on Page 206, you need to select the 'mail' database with something like

    mysql> use mail;
    

Page 224: (credits: Mark Andrews)

one-time padone-time password

Page 227: (credits: Archaic)

The table contains one line labeled NestcapeNetscape Messenger 4.51+.

Page 239: (credits: Mark Andrews)

The mail database has to be created before you can create tables within it:

    mysql> CREATE TABLE `users` {
    

must become:

    mysql> CREATE DATABASE mail;
    mysql> CONNECT mail;
    mysql> CREATE TABLE `users` (
    
Page 248: (credits: Mark Andrews)
The text following the "ldd postconf -h daemon_directory/smtpd" example output:

The output of libsasl.so.2, which is the current major Cyrus SASL version, indicates that SASL support has been compiled into Postfix, and you are ready to configure SMTP authentication.

should read

The output of the ldd command includes libsasl.so.2, which is the current major Cyrus SASL version. This indicates that SASL support has been compiled into Postfix, and you are ready to configure SMTP authentication.

Page 249: (credits: Mike Harris)

2nd Example on page (Instructions on how to include SASL libs into Postfix) should read:
CCARGS="-DUSE_SASL_AUTH -I/usr/include/sasl" AUXLIBS="-L/usr/lib -lsasl2" It was missing the closing quotation marks on the CCARGS.

Page 250: (credits: Mark Andrews)
Caution note:

... to configure and link the Postfix library with the Cyrus SASL library ...

Page 253: (credits: Mark Andrews)
first sentence of "Configuring the SASL Realm":

You may need to set a realm within in main.cf ...

Page 257: (credits: Eric Geib)

The word DATA should be in bold in the example on page 257.

Page 265: step 2 of "The lmtp client" (credits: Mark Andrews)

of course, you could also share the credentials file with the smtp client

Page 265: step 3 of "The lmtp client" (credits: Mark Andrews)

lmtp_sasl_password_maps = hash:/etc/postfix/lmtp_passwd

Page 274: (credits: Lubomir Ptacek)

line 3 from the bottom of the page: It should read Mac instead of Max.

Page 332: (credits: Enrico Vogel)

Remove the "D" flag for the maildrop transport:

  maildrop unix -         n       n       -       -       pipe
    flags=Rhu user=vmail argv=/usr/local/bin/maildrop -d ${recipient} -w 75
  
This also implies that you can ignore the explanation for the "D" flag as well (credits: Lubomir Ptacek)
Page 338: (credits: Enrico Vogel)

The loop detection cannot work, since Postfix's pipe always appends a Delivered-To: header, which maildrop will see and say that the mail is looping! (see errata for p.332)

The maildroprc Script needs to be altered as well:

  if ( /^Delivered-To: $LOGNAME@mail.example.com/:h )
  {
    echo "This message is looping, it already has my Delivered-To: Header!"
    EXITCODE = 1
    exit
  }
  # Add Delivered-To: header
  xfilter "reformail -A'Delivered-To: $LOGNAME@mail.example.com'"
  
Page 371: (credits: Ralf Hildebrandt)

The chroot() system call alters how a process - after entering the chroot jail - perceives the filesystem to a process.

Page 372: (credits: Rod Dorman)

To change it, change the chroot option from n or - to y n to - or y.

Page 374: (credits: Ralf Hildebrandt)

Other files, such as socket devices sockets or devices...

Page 374: (credits: Michael A. Patton)

# strace -o outputfile program

Page 375: (credits: Ken Gallo)

original: chmod 750 /var/spool/postfix/var/run/saslauthd
corrected: chmod 770 /var/spool/postfix/var/run/saslauthd
Reason: The saslauthd program refuses to start if it cannot write to its socket (at least on Debian)

Page 376: (credits: Ken Gallo)

original: /usr/sbin/saslauthd -m /var/spool/postfix/var/run/saslauthd/mux -a shadow
corrected: /usr/sbin/saslauthd -m /var/spool/postfix/var/run/saslauthd -a shadow
Reason: The mux object is not created until saslauthd is running, but saslauthd refuses to run unless the full socket path exists and is writeable (at least on Debian)

Page 382: (credits: Dietmar Braun)

Bottom of the page: To carry out the test, use the following setting in your master.cfmain.cf...

Page 390: (credits: Ralf Hildebrandt)

In any case, these bounces will clutter your queue or go to the mailbox specified by double_bounce_recipient 2bounce_recipient (which may be your postmaster account).

Page 396: 2nd paragraph (credits: Ralf Hildebrandt)

cleanup then writes the message into a queuefile and this is bounced bounded by the disk I/O latency.

Page 435: (credits: Michael A. Patton)

In CIDR notation, an IP address is represented as A.B.C.D/n, where A.B.C.D is the prefix and n is called the IP prefix length or network prefix. The IP prefix length identifies the number of significant bits used to identify a network.