Home > Support > HOWTO List > Postfix notes

Using SpamAssassin with Postfix

Spamassassin is a popular spam filter.

To install spamassassin on most distros try 'apt-get install spamassassin'.  Then you just need to hook it into your mail server.

Spam assassin is normally run via procmail (/etc/procmailrc) when you are operating a mail server like sendmail.  When you are running postfix you can integrate it via a master.cf filter.

Just add the following to /etc/postfix/master.cf:

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

spamassassin unix  -       n       n       -       -       pipe
   user=nobody argv=/usr/bin/spamc -f -e /usr/sbin/sendmail.postfix -oi -f ${sender} ${recipient}

If you're using Debian, you should use /usr/sbin/sendmail rather than sendmail.postfix.

This sets up an smtp 'filter'.  Then defines what that filter does.  In our case it sets up spamc (the spamassassin client) to check with spamd (the server) whether the incoming email is spam or not.

The -e /usr/sbin/sendmail.postfix does sendmail emulation for postfix.

If you were doing this with sendmail you would just put a spamc entry in /etc/procmailrc.

Missing virtual.db file

Getting an error like:

fatal: open database /etc/postfix/virtual.db: No such file or directory
warning: process /usr/libexec/postfix/smtpd pid 27552 exit status 1
warning: /usr/libexec/postfix/smtpd: bad command startup -- throttling

Then you need to create virtual.db file.

Run postmap virtual from /etc/postfix.

IIRC RHEL4's postfix startup script re-creates the virtual.db file so you should not hit this unless you are on some other distro (e.g. Debian?)

Enabling Postfix SMTP AUTH

To get postfix doing smtp auth on a redhat based distro like RHEL4 you'll need the following config settings:

smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination

On Debian Sarge this howto works a treat: http://www.tribulaciones.org/docs/postfix-sasl-tls-howto.html (I just needed to change the permissions on /etc/sasldb2 after getting this error: postfix/smtpd[3217]: warning: SASL authentication problem: unable to open Berkeley db /etc/sasldb2: Permission denied)

Virtual domains

You have more than 1 domain pointing at your Postfix server, and you want to have user@domain1.com seperate from user@domain2.com. The solution is virtual mailbox maps.

In mydestination list your servers hostname/mail server name (i.e. what just 'user' will get expanded to, usually user -> user@yourhostname.com) and localhost:

mydestination = $myhostname, localhost

Setup the file that will list the virtual users aliases, and the virtual domains:

virtual_mailbox_domains = example.com 2.example.com
virtual_mailbox_maps = hash:/etc/postfix/virtual
# if you get an error about the mail box base not being set use something like:
virtual_mailbox_base = /var/spool/mail/
# these control the ownership of the mailbox files.  See also http://www.akadia.com/services/postfix_separate_mailboxes.html
virtual_uid_maps = static:1001
virtual_gid_maps = static:8

Into /etc/postfix/virtual, put your virtual aliases, including catch-alls:

postmaster@example.com postmaster
postmaster@yourotherdomain.com jack
info@example.com       joe
info@yourotherdomain.com     jane

# catch-all
@example.com         jim

See also: http://www.postfix.org/VIRTUAL_README.html especially http://www.postfix.org/VIRTUAL_README.html#canonical.

Forwarding email

Say your server controls email sent to original.example.com.  But you want that email to be forwarded to a different email server (i.e. not stored on the original.example.com mail server)

e.g. (e.g. so that email sent to becky@original.example.com which is a domain hosted by your postfix server, is forwarded to becky@forwarded.example.com which is likely an email address hosted elsewhere)

Add these settings to /etc/postfix/main.cf:

virtual_alias_domains = original.example.com, otherdomainetc.example.com
virtual_alias_maps = hash:/etc/postfix/virtual_alias_domains

Create a file that lists the original email address and the address to which postfix should forward the mail.  e.g. /etc/postfix/virtual_alias_domains:

becky@original.example.com becky@forwarded.example.com

Run postmap /etc/postfix/virtual_alias_domains to 'compile' that file into an index.

Restart postfix with /etc/init.d/postfix restart

The difference between virtual_alias_domains and virtual_mailbox_domains is that the former is forwarded somewhere and the latter is stored on your server.

Mixing forwarded domains and virtual domains

Want to send forward sue@original.example.com to someaccount@forwarded.example.com (on a different email server) and store joan@original.example.com locally?

Then set original.example.com as a virtual_alias_domains.  In /etc/postfix/virtual_alias_domains have:

joan@original.example.com joan_original
sue@original.example.com someaccount@forwarded.example.com

Emails sent to joan@original.example.com will be sent to joan_original@yourserverhostname.com.  If yourserverhostname.com is setup in virtual_mailbox_domains you would be able to redirect it there with an entry in /etc/postfix/virtual like:

joan_original@yourserverhostname.com joan

(Which would normally end up in /var/spool/mail/joan).

Encrypting your SMTP traffic with TLS

With TLS you can establish a 'regular' non-encypted SMTP connection, then 'negotiate' a secured TLS connection.  This is good, for example, when sending passwords during SMTP authentication (if you are sending plain text logins).  It will also encrypt your email message while it is on the way to your SMTP server.  And since the one port (usually port 25) is used for both encrypted and non-encrypted connections the setup can be a bit simpler.

Note that if your email server needs to forward it to another machine, then there are no guarantees that the message will be encrypted during that part of its journey.  Or indeed when it is picked up at the end by the recipient (via pop3 or imap).

To enable TLS with postfix ensure your /etc/postfix/main.cf contains:

# means that clients can use plain unencrypted SMTP connections if they wish
smtpd_tls_auth_only = no
# means that when the SMTP server forwards the message on, it will not use TSL
smtp_use_tls = no
smtpd_use_tls = yes
smtp_tls_note_starttls_offer = yes
smtpd_tls_key_file = /etc/postfix/ssl/smtp.key
smtpd_tls_cert_file = /etc/postfix/ssl/smtp.cert
smtpd_tls_CAfile = /etc/postfix/ssl/smtp.pem

smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
tls_random_source = dev:/dev/urandom
smtpd_tls_session_cache_timeout = 3600s

You can check this by running postconf | grep tls


mkdir -p /etc/postfix/ssl 
bash makecert.sh

This will generate a self-signed certificate.

You can see that TLS is working.  Your /var/log/maillog will show something like:

Aug 29 10:01:55 example postfix/smtpd[1870]: TLS connection established from example.com[]: TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)

If you have a 'real' certifcate then you can use that as well.  In that case the /etc/postfix/main.cf will looks something like:

# Means that clients can use plain unencrypted SMTP connections if they wish

smtpd_tls_auth_only = no
smtp_use_tls = yes
smtpd_use_tls = yes
smtp_tls_note_starttls_offer = yes
smtpd_tls_session_cache_timeout = 3600s
smtp_tls_cert_file = /etc/httpd/conf/ssl.key/example.com.pem
smtpd_tls_cert_file = $smtp_tls_cert_file

To create the pem file run something like this (which just puts the certificate and private key into a single file):

{ cat /etc/httpd/conf/ssl.key/$domain.key; cat /etc/httpd/conf/ssl.crt/$domain.crt ; } > /etc/httpd/conf/ssl.key/$domain.pem

Debian Postfix + SMTP authentication setup

This assumes that you're running Debian Sarge, and that your Postfix is chrooted (the default). It will setup saslauthd to authenticate using PAM.

Grab the required packages and create directories

apt-get install sasl2-bin libsasl2-modules
mkdir -p /var/spool/postfix/var/run/saslauthd
chown -R postfix:root /var/spool/postfix/var
mkdir /etc/postfix/sasl

In /etc/default/saslauthd, uncomment the START=yes line. Set MECH="pam". Also add:

PARAMS="-m /var/spool/postfix/var/run/saslauthd"

Restart saslauthd with: /etc/init.d/saslauthd

Next configure Postfix. Into /etc/postfix/main.cf add:

# SASL authentication setup
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination
smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname
broken_sasl_auth_clients = yes

Into /etc/postfix/sasl/smtpd.conf put:

pwcheck_method: saslauthd
mech_list: PLAIN LOGIN

Restart Postfix: /etc/init.d/postfix restart

Test the setup with pingability: http://pingability.com/smtptest.jsp

Running your domain's mail service on a separate server

Say your domain is example.com.  You want all your web and FTP etc to be handled on one server.  And your mail to be handled by another machine (maybe mail.example.com).

You want your example.com server to run a mail server though, so things like your webapps can send emails.  And apps like Logwatch can send you emails.  Just the server should not/will not be the final destination for emails addressed to user@example.com

But, when you send email from your example.com server to someuser@example.com your local postfix mail server grabs the email and tries to deliver it locally.  e.g. often resulting in an error like:

Feb 3 20:37:35 example postfix/local[7666]: 71824246B3: to=<jessicaw@example.com>, relay=local, delay=0, status=bounced (unknown user: "jessicaw")

In this case edit /etc/postfix/main.cf.

mydestination = $myhostname, localhost.$mydomain, localhost

mydestination = localhost.$mydomain, localhost

And change add a line like:

(i.e. just make sure myhostname is not the same as the domain to which you are addressing email).

Then restart postfix with /etc/init.d/postfix restart.

After that you should be able to send email to example.com and get a result in /var/log/maillog like:

Feb  4 14:50:49 ekreg postfix/smtp[19966]: 46A7E247E3: to=<jessicaw@example.com>, relay=MAIL.example.com[], delay=0, status=sent (250 2.6.0  <20070204225049.46A7E247E3@rimu.example.com> Queued mail for delivery)

Resolving 'mail for example.com loops back to myself'

Are you getting an error like this in /var/log/maillog:

Feb  4 14:41:45 ekreg postfix/smtp[19678]: 0FA5D247E4: to=<root@example.com>, relay=MAIL.example.com[], delay=0, status=bounced (mail for example.com loops back to myself)

In this case it is likely because your main.cf myhostname setting is the same as the domain to which your email is addressed.  Change it per the above section.

Procmail spam filtering

Filtering by Subject

If you want all mail that is marked as spam put into its own directory then you can add the following to /etc/procmailrc
* ^Subject:.*\*\*\*\*\*SPAM\*\*\*\*\*.*

Filtering by Headers
# Put messages with scores of 3 or more into probable spam
# mailbox.  The three dots here match three or more asterisks.
* ^X-Spam-Level: ...

$DEFAULT is the directory of your mail, so it could be $HOME/Maildir/ or /var/mail/ etc depending on your setup.
If you leave the trailing / on the end it will use Maildir, otherwise it will put it in mbox format.

Rejecting backscatter mails

what is backscatter? a comprehensive docs about it here http://www.postfix.org/BACKSCATTER_README.html
for short it's an unwanted mails that are in your postfix queue and by thousands of it sending bounced mails to other recipients.

If your postfix is setup to use local delivery agent. e.g. using /etc/passwd to get account info.

Then just add this to your /etc/postfix/main.cf if it's not yet there.

    local_recipient_maps = proxy:unix:passwd.byname $alias_maps

for the changes to take effect restart postfix by running /etc/init.d/postfix restart
Then delete all mails in the queue, assuming these mails are backscatter as most legit mails don't stay in the queue for too long as they get delivered right away.

 postsuper -d ALL