Postfix is a MTA (Mail Transport Agent) developed by Wietse Venema as an alternative to the widely-used Sendmail program
; it attempts to be fast, easy to administer, and secure. The outside has a definite Sendmail-ish flavor, but the inside is completely different
. Postfix also comes with excellent documentation and lots of howtos.
Our mail server requirements will be quite simple: it will be final destination solely for its canonical domains and it will only relay mail from systems on the internal network (though we will also consider relaying from untrusted networks by means of SMTP authentication). Canonical domains include the hostname (in our case, "mail.kernel-panic.it") and the IP address (172.16.240.150) of the machine that Postfix runs on, and the parent domain of the hostname ("kernel-panic.it").
Canonical domains are usually implemented with the Postfix local domain address class, which, unfortunately, has one major drawback for me: it requires that each e-mail account have a corresponding Unix account. On the contrary, I prefer:
Therefore, we will use Postfix Virtual Domain Hosting, which is normally used for hosting multiple internet domains on the same server, but will also allow us to achieve the above goals.
In this paragraph, we will configure Postfix to work standalone, with no back-end database. Then, in the next chapter, when everything will be working fine, we will hook up Postfix to a MySQL database; this will allow us to centrally store configuration information that both Postfix and Courier-IMAP will need to access.
There are a few packages we need to install:
Note: if you're planning to use SMTP authentication, you will need to compile Postfix from the ports, because there's no pre-compiled package available with both MySQL and SASL support:
# cd /usr/ports/mail/postfix/snapshot # env FLAVOR="mysql sasl2" make install
The installation will create the /etc/postfix directory, containing all the configuration files. Postfix has several hundred configuration parameters that are controlled via the /etc/postfix/main.cf file, but don't worry: for the vast majority of these parameters, the default value is the best option (see postconf(5) for a detailed list of all the available configuration parameters, their description and default value) and we will only have to override a very small subset of them:
# Directory containing all the post* commands command_directory = /usr/local/sbin # Directory containing all the Postfix daemon programs daemon_directory = /usr/local/libexec/postfix # Location of the Postfix queue and root directory of chrooted Postfix daemons queue_directory = /var/spool/postfix # Full pathnames of various Postfix commands sendmail_path = /usr/local/sbin/sendmail newaliases_path = /usr/local/sbin/newaliases mailq_path = /usr/local/sbin/mailq # Directories containing documentation html_directory = /usr/local/share/doc/postfix/html manpage_directory = /usr/local/man readme_directory = /usr/local/share/doc/postfix/readme # The owner of the Postfix queue and of most Postfix daemon processes mail_owner = _postfix # The group for mail submission and queue management commands setgid_group = _postdrop # The myhostname parameter specifies the internet hostname of this mail system. It is # used as default for many other configuration parameters (default = system's FQDN) myhostname = mail.kernel-panic.it # The internet domain name of this mail system. Used as default for many other # configuration parameters (default = $myhostname minus the first component) mydomain = kernel-panic.it # The domain name that locally-posted mail appears to come from, and that locally posted # mail is delivered to. As you can see, a parameter value may refer to other parameters myorigin = $myhostname # Network interface addresses that this mail system receives mail on inet_interfaces = all # Network interface addresses that this mail system receives mail on by way of a # proxy or NAT unit proxy_interfaces = router.kernel-panic.it # List of domains that this machine considers itself the final destination for. # Virtual domains must not be specified here mydestination = $myhostname, localhost.$mydomain, localhost # List of "trusted" SMTP clients allowed to relay mail through Postfix. mynetworks = 127.0.0.0/8, 172.16.0.0/24, 172.16.240.0/24 # What destination (sub)domains this system will relay mail to relay_domains = $mydestination # The default host to send mail to when no entry is matched in the optional # transport(5) table. Square brackets turn off MX lookups relayhost = [smtp.isp.com] # List of alias databases used by the local delivery agent alias_maps = hash:/etc/postfix/aliases # Alias database(s) built with "newaliases" or "sendmail -bi". This is a separate # configuration parameter, because alias_maps may specify tables that are not # necessarily all under control by Postfix alias_database = hash:/etc/postfix/aliases # SMTP greeting banner smtpd_banner = $myhostname ESMTP $mail_name # Postfix is final destination for the specified list of "virtual" domains virtual_mailbox_domains = kernel-panic.it # Virtual mailboxes base directory virtual_mailbox_base = /var/vmail # Optional lookup tables with all valid addresses in the domains that match # $virtual_mailbox_domains. virtual_mailbox_maps = hash:/etc/postfix/vmailbox # The minimum user ID value accepted by the virtual(8) delivery agent virtual_minimum_uid = 2000 # User ID that the virtual(8) delivery agent uses while writing to the recipient's mailbox virtual_uid_maps = static:2000 # Group ID that the virtual(8) delivery agent uses while writing to the recipient's mailbox virtual_gid_maps = static:2000 # Optional lookup tables that alias specific mail addresses or domains to other local or # remote address virtual_alias_maps = hash:/etc/postfix/virtual
Let's take a closer look at some of the above configuration parameters.
One of our initial goals was to avoid having a separate Unix account for each e-mail account. We have achieved this by configuring Postfix to write to the mailboxes using uid 2000 and gid 2000 (see the virtual_uid_maps and virtual_gid_maps parameters above). Now we only have to create a user with this pair of uid and gid:
# useradd -d /var/vmail -g =uid -u 2000 -s /sbin/nologin \ > -c "Virtual Mailboxes Owner" -m vmail
Our second goal was to have all mailboxes grouped together in a single directory; this is achieved by setting the value of the virtual_mailbox_base parameter to the path of that directory (in our configuration, /var/vmail). In matter of fact, this parameter is a prefix that the virtual(8) agent prepends to all pathname results from virtual_mailbox_maps table lookups.
In our configuration, the virtual_mailbox_maps parameter refers to the /etc/postfix/vmailbox file, containing the list of all valid addresses in the virtual domains (virtual_mailbox_domains parameter) and the path to the corresponding mailboxes or maildirs (a mailbox is a single file containing all the emails; a maildir, instead, is a directory, with a particular structure, containing all the emails in separate files):
info@kernel-panic.it kernel-panic.it/info/ d.mazzocchio@kernel-panic.it kernel-panic.it/d.mazzocchio/ [...]
Please pay attention to the trailing slashes: they tell Postfix that the pathname refers to a maildir instead of a mailbox file, and maildirs are our only option, since Courier-IMAP doesn't support mailbox files.
The virtual_alias_maps parameter allows you to alias specific mail addresses or domains to other local or remote addresses. Its value is the pathname to a file (in our case /etc/postfix/virtual) containing the alias mappings:
root@kernel-panic.it root@localhost.kernel-panic.it postmaster@kernel-panic.it postmaster@localhost.kernel-panic.it abuse@kernel-panic.it postmaster@localhost.kernel-panic.it [...]
Finally, the /etc/postfix/aliases file contains the addresses to which Postfix will redirect mail for local recipients (see aliases(5)). Since many accounts point to root's email address, you should check root email frequently or forward it all to another account. E.g.:
root: d.mazzocchio@kernel-panic.it MAILER-DAEMON: postmaster postmaster: root bin: root [...]
Now we only have to update Postfix lookup tables:
# /usr/local/sbin/postmap /etc/postfix/vmailbox # /usr/local/sbin/postmap /etc/postfix/virtual # /usr/local/sbin/newaliases
replace Sendmail:
# /usr/local/sbin/postfix-enable old /etc/mailer.conf saved as /etc/mailer.conf.pre-postfix postfix /etc/mailer.conf enabled NOTE: do not forget to add sendmail_flags=NO to /etc/rc.conf.local to disable sendmail. NOTE: do not forget to add "-a /var/spool/postfix/dev/log" to syslogd_flags in /etc/rc.conf.local and restart syslogd. NOTE: do not forget to add postfix to pkg_scripts in /etc/rc.conf.local to start postfix automatically. NOTE: do not forget to remove the "sendmail clientmqueue runner" from root's crontab.
and follow the above advice, by commenting out the "sendmail clientmqueue runner" in root's crontab:
# sendmail clientmqueue runner #*/30 * * * * /usr/sbin/sendmail -L sm-msp-queue -Ac -q
and adding the appropriate configuration to /etc/rc.conf.local(8).
# Specify an additional syslogd(8) socket for Postfix syslogd_flags="-a /var/spool/postfix/dev/log" # Disable sendmail sendmail_flags="NO" # Start postfix on boot pkg_scripts="postfix"
Now we can change a few permissions and restart the processes (or simply reboot):
# pkill syslogd # syslogd -a /var/empty/dev/log -a /var/spool/postfix/dev/log # pkill sendmail # /etc/rc.d/postfix start postfix(ok)
# telnet mail.kernel-panic.it 25 Trying 172.16.240.150... Connected to mail.kernel-panic.it. Escape character is '^]'. 220 mail.kernel-panic.it ESMTP Postfix HELO somedomain.org 250 mail.kernel-panic.it mail from: someone@somedomain.org 250 Ok rcpt to: d.mazzocchio@kernel-panic.it 250 Ok data 354 End data with <CR><LF>.<CR><LF> From: someone@somedomain.org To: d.mazzocchio@kernel-panic.it Subject: Test mail It works! . 250 Ok: queued as 548D7286 quit 221 Bye Connection closed by foreign host. # tail /var/log/maillog Dec 16 15:26:35 mail postfix/smtpd[29212]: connect from ws1.lan.kernel-panic.it[172.16.0.15] Dec 16 15:26:53 mail postfix/smtpd[29212]: 57076222: client=ws1.lan.kernel-panic.it[172.16.0.15] Dec 16 15:27:02 mail postfix/cleanup[13428]: 57076222: message-id=<20070210142653.57076222@mail.kernel-panic.it> Dec 16 15:27:02 mail postfix/qmgr[26776]: 57076222: from=<someone@somedomain.org>, size=392, nrcpt=1 (queue active) Dec 16 15:27:02 mail postfix/virtual[14381]: 57076222: to=<d.mazzocchio@kernel-panic.it>, relay=virtual, delay=15, delays=15/0.28/0/0.03, dsn=2.0.0, status=sent (delivered to maildir) Dec 16 15:27:02 mail postfix/qmgr[26776]: 57076222: removed Dec 16 15:27:06 mail postfix/smtpd[29212]: disconnect from ws1.lan.kernel-panic.it[172.16.0.15] # cat /var/vmail/kernel-panic.it/d.mazzocchio/new/1118146014.V3I9448M811660.mail.kernel-panic.it Return-Path: <someone@somedomain.org> X-Original-To: d.mazzocchio@kernel-panic.it Delivered-To: d.mazzocchio@kernel-panic.it Received: from somedomain.org (ws1.lan.kernel-panic.it [172.16.0.15]) by mail.kernel-panic.it (Postfix) with SMTP id 57076222 for <d.mazzocchio@kernel-panic.it> Sat, 16 Dec 2007 15:26:47 +0100 (CET) From: someone@somedomain.org To: d.mazzocchio@kernel-panic.it Subject: Test mail Message-Id: <20070210142653.57076222@mail.kernel-panic.it> Date: Sat, 16 Dec 2007 15:26:47 +0100 (CET) It works! #