Postoffice smtp server -- mbox virtual hosts

Home | UNIX | Oracle | Code | Practical | Private

Postoffice smtp server -- mbox virtual hosts

pbraun.nethence.com/doc/mail/postoffice.html
pbraun.nethence.com/doc/mail/vm-pop3d.html
pbraun.nethence.com/doc/mail/dovecot.html
pbraun.nethence.com/doc/mail/spamass-milter.html
pbraun.nethence.com/doc/mail/procmail.html


Introduction
In this guide we're configuring the Postoffice smtp server (www.pell.portland.or.us/~orc/Code/postoffice/) for mbox virtual hosts. You can use vm-pop3d for a simple POP3 service, or dovecot if you need POP3 and IMAP.

Mbox is the traditional UNIX mailbox format. It's also the most convenient for data consistency, archiving and troubbleshooting, although it lacks multi-user access (it uses lock instead) and may cause bad performance on very large mailboxes. Combined with virtual hosts, we establish a clean cut separation between the domains and therefore its users.

Note. Postoffice now compiles fine on NetBSD/sparc64 (since 1.2.0 or 1.3.pre1).


Prepare the system for virtual and local mboxes
Look for mail user and group,
#on netbsd,
#groupadd -g 6 mail
#useradd -s /sbin/nologin -g 6 -u 6 mail
grep ^mail: /etc/passwd
grep ^mail: /etc/group

Prepare directories and fix permissions for virtual mboxes,
ls -l /var/spool/virtual
ls -l /var/spool/mqueue
ls -l /etc/virtual
mkdir -p /var/spool/virtual
mkdir -p /var/spool/mqueue
mkdir -p /etc/virtual
chown mail:mail /var/spool/virtual
chown mail:mail /var/spool/mqueue
chown mail:mail /etc/virtual
chmod 700 /var/spool/virtual
chmod 700 /var/spool/mqueue
chmod 700 /etc/virtual

Fix permissions for for local users,
cd /var/spool
#cd /var
chown mail:mail mail
chmod 1777 mail
cd mail
chgrp mail *
chmod 600 *


Other prerequisties
To install postoffice, you might also want to prepare that folder,
mkdir -p /usr/local/man

Postoffice will create the greylist database into /var/db/smtpauth.db, so make sure "/var/db" is writeable by root,
ls -ld /var/db


Postoffice installation
Check for dependencies :
- ndbm or gdbm (mandatory, on RHEL install gdbm-devel)
- tcpwrappers (optional, look for /etc/hosts.{allow,deny} files)

Download, and install Postoffice (www.pell.portland.or.us/~orc/Code/postoffice/),
wget wget github.com/Orc/postoffice/tarball/v1.5.3
tar xvzf Orc-postoffice-v1.5.3-0-g9ae3a8a.tar.gz
cd Orc-postoffice-1001eaf
./configure.sh --help
./configure.sh \
--with-tcpwrappers \
--with-queuedir=/var/spool/mqueue \
--with-auth \
--with-milter \
--with-vhost=/etc/virtual \
--with-vspool=/var/spool/virtual \
--with-vuser=mail
make clean
make
make install
note. add '--use-mailwrappers' on BSD systems
note. we dislike greylisting because of the arrival delay it produces
note. --with-gcc-patch patch the code to stop gcc -Wall from complaining
note. --with-auth enable smtp authentication (for AUTH LOGIN). No need for cyrus-sasl kluges & pain like other SMTP servers does: no configuration is needed. Also add '--with-auth=passwd' if you only want Unix users (no virtual users) to connect.

Make sure those commands point to postoffice. On BSD systems, mail wrappers do the job (NetBSD: /etc/mailer.conf, FreeBSD : /etc/mail/mailer.conf). But on Linux and non BSD-like systems, fix the paths,
cd /usr/bin
ls -l mailq newaliases sendmail
mv mailq mailq.dist
mv newaliases newaliases.dist
mv sendmail sendmail.dist
ln -sf /usr/local/bin/mailq
ln -sf /usr/local/bin/newaliases
ln -sf /usr/local/bin/sendmail
check,
which mailq
which newaliases
which sendmail
which runq


Postoffice configuration
Edit Postoffice's configuration, here's an example,
cd /etc/
wget pbraun.nethence.com/code/mail/postoffice.cf
vi postoffice.cf
and change self= accordingly.

Note. 'debug' to allow the DEBUG ESMTP command

Note. "immediate" to process the queue immediately.
Note. qreturn=5h bounces undeliverable mail after 5 hours
Note. size=30m sets the largest message size that postoffice will accept, m for Megabytes

Note. checkhelo refuses clients that claim to be us
Note. paranoid to refuse mail from non resolvable sites
Note. under attack eventually use 'nodaemon' to reject mail from <>

Note. don't use "hops" or if you do, make sure it's a value above 10. "100" is the default
Note. if you do use greylisting (we don't), eventually define the delay,
delay=1m

Note. disable verify-from=1 if:
- you're using another smtp for outgoing messages
- AND you're sending mail as an unix box (non-virtual) user.
otherwise you might not get the delivery returns. Your outgoing smtp will try to send them as MAIL FROM unixuserexample@example.net and postoffice will refuse them as non-local.

Edit the global aliases and update the alias table,
vi /etc/aliases
#vi /etc/mail/aliases
which newaliases
newaliases

Eventually stop and unconfigure existing SMTP services,
#service sendmail stop
#chkconfig sendmail off
start the daemon,
/usr/local/lib/postoffice -bd -q5
#/usr/local/sbin/smtpd -q5
note. "-q5" for queue processing interval of 5 minutes
and enable at boot time,
cat >> /etc/rc.local <<EOF9
echo -n starting postoffice...
/usr/local/lib/postoffice -bd -q5 && echo done
#/usr/local/sbin/smtpd -q5 && echo done
EOF9


Virtual hosts
Configure a vhost,
mkdir -p /etc/virtual/example.net
mkdir -p /var/spool/virtual/example.net
vi /etc/virtual/domains.cf
like e.g.,
mainuser:example.net:1:comment


Virtual users management
Create a password file for it,
cd /etc/virtual
mkdir -p example.net
htpasswd -c example.net/passwd USERNAME
and eventually configure its virtual aliases,
vi example.net/aliases
newaliases example.net
Note. if you don't want to use htpasswd, there are some alternatives :
- pop_passwd.pl (www.reedmedia.net/software/virtualmail-pop3d/#passwords)
#!/usr/bin/perl
# pop_passwd username password >> password file
$name = $ARGV[0];
@salt_chars = ('a'..'z','A'..'Z','0'..'9');
$salt = $salt_chars[rand(62)] . $salt_chars[rand(62)];
$passwd = crypt ($ARGV[1], $salt);
print "$name:$passwd\n";
- vpasswd (www.pell.portland.or.us/%7Eorc/Code/post/)


Local users management
Simple (POP3) account no MDA
To simply enable /var/spool/mail/%u delivery,
useradd -s /sbin/nologin -M -g mail MAILUSER
Note. -M for user's home directory not to be created

MDA capable account
Note. MDA delivery is only possible with local UNIX accounts
To pass user's mail through an MDA (e.g. procmail),
useradd -s /sbin/nologin -m -g mail MDAUSER
note. -m to create user's home directory
cd /home/MDAUSER
vi .procmailrc
... (see pbraun.nethence.com/doc/mail/procmail.html)
vi .forward
like,
"|IFS=' '&&p=/usr/bin/procmail&&test -f $p&&exec $p -f-||exit 75"
fix perms,
chown MDAUSER:mail .forward .procmailrc
chmod 400 .forward .procmailrc
note. .procmailrc.log will eventually be created (procmailrc: LOGFILE=) with perms 600

MDA + IMAP account
Same as above plus, to keep dovecot vhost configuration intact, although it's possible to force mail_location for specific users, we tell procmail to send the messages to the vhost.

Dovecot will see the vhost, Postoffice won't (/etc/virtual/domains.cf).

Note. you'll have to use specific permissions to let both, user's procmail AND the pop/imap daemon write to the vhost (see below).


Permissions
Fix permssions which where altered during the vhost configuration,
chown -R mail:mail /etc/virtual
chown -R mail:mail /var/spool/virtual
find /etc/virtual -type d -exec chmod 700 {} \;
find /etc/virtual -type f -exec chmod 600 {} \;
find /var/spool/virtual -type d -exec chmod 700 {} \;
find /var/spool/virtual -type f -exec chmod 600 {} \;

For specific vhosts *only*, not all of them, the following permission changes are required if :
- you want to access a vhost locally e.g. with Pine (or Mutt)
- and/or you want some unix user's procmail to write to the vhost
enable ACL (edit fstab) on the required filesystem and proceed,
setfacl -m u:unixuser:x /var/spool/virtual
setfacl -m u:unixuser:x /var/spool/virtual/example.net
find /var/spool/virtual/example.net/user.imap -type d -exec setfacl -m u:unixuser:rwx {} \;
find /var/spool/virtual/example.net/user.imap -type d -exec setfacl -dm u:unixuser:rw {} \;
find /var/spool/virtual/example.net/user.imap -type f -exec setfacl -m u:unixuser:rw {} \;
Note. Dovecot doesn't read the symlink but user.imap's content only. So no need to fix the symlink


MX record
Postoffice skips /etc/hosts and system DNS resolution. It has its own resolver so you absolutely need to have the right MX or A records for the domains you're willing to host.


Usage
Eventually deploy this handy restart script,
cd ~/
mkdir -p bin
cd bin
cat > restart_postoffice.ksh <<EOF9
#!/bin/ksh

ps ax | egrep 'smtpd|postoffice' | egrep -v 'restart|grep'
pkill postoffice
#pkill smtpd
print ''
/usr/local/lib/postoffice -bd -q5
#/usr/local/sbin/smtpd -q5
sleep 1
ps ax | egrep 'smtpd|postoffice' | egrep -v 'restart|grep'
EOF9
chmod +x restart_postoffice.ksh

Note. if you enabled greylisting at compilation time (we don't), check it's working :
- Send an email to some hosted address
- Check the greylisting database is created by postoffice,
ls -l /var/db/smtpauth.db    # root / -rw-------
- After a while, check the message has been received,
tail /var/spool/virtual/example.net/username

Check the queue and force its immediate processing,
mailq
#cd /var/spool/mqueue
#ls -l
runq

Update all aliases at once,
newaliases
cd /etc/virtual
for domain in `cut -f2 -d: domains.cf`; do newaliases $domain; done


Update procedure
Follow the installation procedure to overwrite Postoffice binaries,
/usr/local/lib/postoffice -V
wget www.pell.portland.or.us/~orc/Code/postoffice/postoffice-1.5.5.tar.bz2
tar xjf postoffice-1.5.5.tar.bz2
cd postoffice-1.5.5/
./configure.sh \
--with-tcpwrappers \
--with-queuedir=/var/spool/mqueue \
--with-auth \
--with-milter \
--with-vhost=/etc/virtual \
--with-vspool=/var/spool/virtual \
--with-vuser=mail
make
make install
/usr/local/lib/postoffice -V
note. add '--use-mailwrappers' on BSD systems
and restart the daemon,
restart_postoffice.ksh


Milters
For milters, either a UNIX socket e.g.,
filter=/path/to/unix.socket
or a TCP socket e.g.,
filter=hostname:port
note. DNS hosts only


Backup MX
On the backup MX, same configuration but simply add this to /etc/postoffice.cf,
mxpool=1
Note. and change qreturn= to something much bigger, like 3 days


Smart host
To define an outgoing smtp (untested),
relay-host=host
#forward-all


SMTP relay
Interesting options (untested),
#localmx
#relay
#trusted=host


MDA
Local users are allowed to use external MDA through the ~/.forward file,
vi ~/.forward
like,
"|IFS=' '&&p=/usr/local/bin/procmail&&test -f $p&&exec $p -f-||exit 75"
Ref. mirror.ncsa.illinois.edu/procmail-faq/mini-faq.html#forward

However, in your procmailrc, don't use the USER variable. Hard code the username e.g.,
ORGMAIL=/var/spool/mail/USERNAME
Note. otherwise we would get something like,
/var/spool/mail/new/1282953512.2676_1.mx.example.net


Mail quotas
Simply use LVM for mail quotas, one LV per imap user (inbox is symlinked),
LV /var/spool/virtual/example.net/user.imap
symlink /var/spool/virtual/example.net/inbox -> user.imap/inbox
Note. there's also LVM for NetBSD (www.netbsd.org/docs/guide/en/chap-lvm.html)
Note. use the minfree= configuration option
Note. you may do daily script to let users know if they're reaching their maximum space usage


Additional notes
Looks like Postoffice works this way when receiving a valid message :
- checks for MX or A record with its own resolver
- looks for virtual host matching domain and virtual user
- looks for local users
Note. when using an IP instead of a domain name through telnet, you need to embrace the IP e.g.,
rcpt to:user@[XX.XX.XX.XX]

Note. add double quotes when using piped aliases,
"|/usr/bin/msgs -s"

Note. edit smtpd welcome message,
vi /etc/issue.smtp

Note. postoffice doesn't provide /var/log/mail.stat


Troubbleshooting
Check you've got the latest version,
/usr/local/lib/postoffice -V

Find out what's using /var/spool/mqueue (in case it's not even a lying runq process),
lsof | grep mqueue

Some other UNICES use "/var/mail/" instead of "/var/spool/mail". Adapt your MAIL or MAILPATH variable or make sure there's a symlink to one another. That's for local users. Virtual hosts are usually hosted into /var/spool/virtual.

Eventually test your server remotely by telnet,
helo check
helo check
mail from:<>
rcpt to:email@example.net
data
from:<>
to:email@example.net
subject:check

check
.
quit


Mail server migration
Assuming the old MX is currently in production, and either you just configured a new one, or you have a backup MX standing by. Either way you want to migrate the service to the new MX.

Update the DNS records but force the old behaviour
- configure vhosts's DNS MX records so the new MX has a higher priority
- do not configure the wanted vhosts on the new MX yet
- don't change old MX's configuration (no mxpool)

Migrate the data and switch MXes
Proceed once the MX records are propagated (approx. 4 hours).

On old MX :
- empty the queue and disable the vhosts you need to migrate
- make an archive of their configuration and mbox folders
- rename the mbox folder to .old (no need to create a new-empty one)
- send the archives to the new MX
- reenable the vhost
- fix perms
- update postoffice to get the mxpool feature
- start the daemon with mxpool

On the new MX :
- deploy vhost's archives
- configure the vhost
- apply vhost's aliases
- fix perms

Notes
Note. this may happen : greylisting db isn't as up to date on the new MX as it is on the old one. So the new MX may refuse temporarily some messages, which will be hence sended to the backup (old) MX. The latter will keep them for the new one.
Note. unfortunately you can't enable mxpool for one vhost and keep it disabled for another.
Note. this will go smoothly on the client side, username and passwords don't change, hostname don't change (update the pop server DNS record), e.g. thunderbird just proceeds on the new host w/o warning nor errors.
Note. only thing is, you might get emails twice (those who where intetionnaly kept on the server) if you don't migrate all at once.


References
www.milter.org/
www.faqs.org/rfcs/rfc2554.html
www.pell.portland.or.us/%7Eorc/Code/post/
www.washington.edu/imap/documentation/formats.txt.html
www.washington.edu/imap/documentation/formats.txt.html

Postfix with mbox virtual hosts (untested)
www.postfix.org/VIRTUAL_README.html#virtual_mailbox
unixdoc.ua-i.net/articles/mail/postfix/virtual-hostsninstall.txt
www.inter7.com/index.php?page=vpopmail
www.steki.net/code/download/
christian.caleca.free.fr/qmail/vpopmail.htm


Home | UNIX | Oracle | Code | Practical | Private | Donate | Print | html/css
© 2012 Pierre-Philipp Braun