nav-left cat-right
cat-right

Postfix

3.9 Postfix

Postfix is an excellent and simple way to run your mail system. I switched from an old version of Exim, as the configurations were just too much to deal with. I hear the newer Exims are a bit better, but I haven't tried them. Postfix is fairly standard these days, so unless you have specific mail system requirements, you can't go wrong with it.

3.9.1 Install Postfix

  • sudo su -
  • yum install postfix system-switch-mail
  • system-switch-mail

Choose postfix, then 'OK'. Postfix is now installed, with all the necessary configuration files in /etc/postfix. It's also been installed as a service, which I love so much. Start 'er up:

  • service postfix start

Log out of your root session.

3.9.2 Configuring Postfix

Since I run multiple web sites, but only have a few people who actually use the system for mail, I set up both virtual aliases and virtual mailboxes. For instance, I might host a small-business website, and they'll want a bunch of email addresses for their store, but I don't want them to have a user account on the machine. Virtual mailboxes to the rescue. Virtual aliases allow me to have the same address at different domains go to different mailboxes as well, which is handy from a user and maintenance perspective, and also for reducing spam (bob@domain1.com will go to a different place than bob@domain2.com). The key directives to set are in /etc/postfix/main.cf:

myhostname = mail.sitename.com
mydomain = sitename.com
inet_interfaces = all
relayhost =
mynetworks_style = host

#Blank, for virtual domains
mydestination =

#Blank, for virtual domains
local_recipient_maps =

#Some helpful spam settings
smtpd_helo_required = yes
smtpd_helo_restrictions =

reject_invalid_hostname
reject_non_fqdn_hostname

smtpd_sender_restrictions =
# hash:/etc/postfix/access

reject_non_fqdn_sender
reject_unknown_sender_domain

smtpd_data_restrictions =

reject_unauth_pipelining

#Other tweaks
max_idle = 300s
anvil_status_update_time = 1h
anvil_rate_time_unit = 300s
export_environment = TZ MAIL_CONFIG SENDER

Virtual mailboxes and aliases are acheived by adding all the following directives (at the end of main.cf):

#Virtual settings
virtual_mailbox_domains = $myhostname, localhost.$mydomain, localhost, your-domain-1.com, your-domain-2.com
#The virtual "spool" dir
virtual_mailbox_base = /var/mail/vhosts
#Maps file for delivery to virtual mailboxes (virtual domains + virtual users)
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_minimum_uid = 100
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
#Maps file for delivering to virtual aliases (virtual domains + real users)
virtual_alias_maps = hash:/etc/postfix/virtual1.hash

With all those virtual settings, we'd better set up what it needs in the real system. Still as root, run the following:

groupadd virtual -g 5000 -r
useradd virtual -u 5000 -g 5000 -r
usermod -s /sbin/nologin virtual
mkdir /var/mail/vhosts
chown virtual.virtual /var/mail/vhosts
3.9.2.1 Adding a Virtual Mailbox

For each domain you want to accept mail at:

  • sudo mkdir /var/mail/vhosts/domainname.com
  • sudo chown virtual.virtual /var/mail/vhosts/domainname.com

Each virtual user should have a spool file, and then you can point all the email addresses you want at it. Edit /etc/postfix/vmailbox

#mydomain.com mailboxes
blake@mydomain.com mydomain.com/blake

That puts the spool file for 'blake' into /var/mail/vhosts/mydomain.com/blake. If I want aliases to go to that spool, point them at my main email address by editing /etc/postfix/virtual.hash:

#aliases to blake
CentOS.guide@mydomain.com blake@mydomain.com
imnotwearingpants@mydomain.com blake@mydomain.com,webmaster@mydomain.com

When you're all done setting up mailboxes and aliases, run postmap on each file:

  • sudo postmap /etc/postfix/vmailbox /etc/postfix/virtual
3.9.2.2 Transports for piping mail with virtual aliases

This was a bit complex and it took me a long time to get right for my particular set up. Remember, this guide is pretty much a giant notepad for me to keep track of all my linux sysadmin fun! You can probably safely ignore this part if you want, unless you also need special piping procedures. While ensuring that I have virtual aliases and mailboxes, I also had to set up a special transport to allow incoming mail to a special address to be piped to a web script. That's the transport_maps setting below, which also goes into the main.cf file:

#Transport maps
#I discovered that you cannot do anything other than a local mailbox delivery using virtual aliases.
#To get piping, etc, I have to use transports.
transport_maps = hash:/etc/postfix/transport

Now, at the very bottom of the ever-so-fun /etc/postfix/master.cf (not main.cf), I created a transport named "mycatch":

#Blake's transport for dealing with mail-catcher scripts
#It sends the email to a script based on the local part, so if you catch an email
#to test@mydomain.com, it will redirect it to mailcatcher_test.php
mycatch unix -- n n -- -- pipe
  flags=Fq user=apache argv=/srv/www/mydomain/bin/mailcatcher_${mailbox}.php ${sender}

Almost there. Now we just have to set up the specific address in /etc/postfix/transport, like so:

#Incoming puppies -- mail is piped to /srv/www/mydomain/bin/mailcatcher_puppies.php
puppies@mydomain.com mycatch:Sent to puppy catcher
#Goblin attacks, oh no! -- mail is piped to /srv/www/mydomain/bin/mailcatcher_goblin_attacks.php
goblin_attacks@mydomain.com mycatch:Sent to goblin defender script
#etc

Note that these addresses also have to be set up in the virtual mailbox file as well, as the addresses need to be recognized. Transports happen after mail acceptance, but before delivery, so the email needs to be valid (ie. in the mailbox file) in order for it to be accepted. Edit /etc/postfix/vmailbox:

#These addresses generally use a transport that pipes the message to a script, and will not be delivered to the specified
#mailbox.
puppies@mydomain.com mydomain.com/devnull
goblin_catcher@mydomain.com mydomain.com/devnull

Note that the mail will never be delivered to the devnull mailbox, as the transport we just set up will intercept it. You get the idea. Now run:

  • sudo postmap /etc/postfix/transport

and try out your pipe scripts by sending an email.

Be Sociable, Share!