Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
HOWTO: A simple approach to virtual mail hosting (Postfix)
View unanswered posts
View posts from last 24 hours

Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks
View previous topic :: View next topic  
Author Message
Retired Dev
Retired Dev

Joined: 11 Oct 2002
Posts: 495
Location: New Hampshire

PostPosted: Thu Mar 25, 2010 7:49 pm    Post subject: HOWTO: A simple approach to virtual mail hosting (Postfix) Reply with quote

Not very Gentoo-specific, I threw this together after putting together some simple Debian hosts for friends.

This is in no way intended to be the 'best' way to put together a virtual mailhost with SASL/POP3(s)/IMAP(s)/SpamAss, it's not especially secure (static uid for all mailboxes), but it should work for people with very simple needs. Also, I hate courier-imap and cyrus-sasl.

Banged this out just now off the top of my head without coffee, I probably missed something.

Interested in critique.



# $Id: HOWTO_vmail_postfix_dovecot.txt,v 1.1 2010/03/25 19:38:52 avenj Exp avenj $

## Jon Portnoy
## free to redistribute, but please change the attribution above if you modify.

## rcs:
# $Revision: 1.1 $
# $Date: 2010/03/25 19:38:52 $
# $Author: avenj $

      Simple Virtual Mail Hosting

This is a very basic HOWTO on deploying a simple, full-featured virtual mail host.
We'll be setting up authenticated SMTP/IMAP(s)/POP3(s) and effective spam-killing.

This is definitely not a guide to the "best mail hosting solution" or any such thing.
The focus is on simplicity.

This guide assumes a working knowledge of Unix administration and how mail works in general.
The focus here is on quickly configuring mail.
There is not a lot of elaboration on what, exactly, you are doing.
Do yourself a favor, do not deploy mail before you've read your software's documentation.

We use the following software:
  - postfix-2.6 (SMTP -- using maildir delivery)
  - dovecot-1.2 (POP3(s), IMAP(s), dovecot-auth)
  - spamassassin-3.3

I'll be using a config based on the existing system as examples.


We'll be killing two birds with one stone here: SASL auth, and the virtual mail system.
SASL will hook into dovecot to handle authentication, so user auth credentials are
consistent between IMAP/POP3 and SMTP.

* Ensure that your $mydestination setting does not include your virtually hosted domains.
You can optionally set it to localhost and host _all_ mail including Unix mail via virtual mailboxes.
Alternately you can keep your Unix mailboxes separate from your virtual mailboxes.
My hosts use the latter option.

## /etc/postfix/ Unix mail destination for ##
  myhostname =
  mydestination =, localhost

You'll need this to authenticate SASL against your dovecot users later:

## /etc/postfix/ SASL via dovecot-auth ##
  smtpd_sasl_type = dovecot
  smtpd_sasl_path = private/auth
  smtpd_sasl_auth_enable = yes
  # stupid hack for old ms clients:
  broken_sasl_auth_clients = yes
  smtpd_sasl_security_options = noanonymous
  smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination

You'll probably want SSL/TLS.
You can create a self-signed /etc/postfix/ssl/smtpd.pem thusly:
 -sh$ mkdir /etc/postfix/ssl && cd /etc/postfix/ssl
 -sh$ openssl req -new -x509 -nodes -out smtpd.pem -keyout smtpd.pem -days 3650

## /etc/postfix/ TLS & SpamAssassin ##
  smtpd_tls_key_file = /etc/postfix/ssl/smtpd.pem
  smtpd_tls_cert_file = /etc/postfix/ssl/smtpd.pem
  smtpd_tls_CAfile = /etc/postfix/ssl/smtpd.pem
  smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
  smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

  spamassassin_destination_recipient_limit = 1

  # IMPORTANT: You might also have to uncomment the 'smtps' directive in /etc/postfix/

Finally, the important stuff: virtual mailboxes.

## /etc/postfix/ Virtual mailboxes ##
  virtual_mailbox_domains = /etc/postfix/vmail-hosts
  virtual_mailbox_base = /var/spool/vmail
  virtual_mailbox_maps = hash:/etc/postfix/vmail-maps
  virtual_alias_maps = hash:/etc/postfix/vmail-alias
  virtual_uid_maps = static:1008
  virtual_gid_maps = static:1008

This breaks down as follows:

virtual_mailbox_domains = /etc/postfix/vmail-hosts:
    This is a simple list of hosted destination domains, one per line.
    For example:

virtual_mailbox_base = /var/spool/vmail:
    This directory contains the actual mailboxes.
    The actual layout will look like:
    We'll set this up later.

virtual_mailbox_maps = hash:/etc/postfix/vmail-maps
    This file lists the actual mailbox mappings.
    Each user with a virtual mail account needs an entry in this file, thusly:
    This is easily managed with some simple scripting.
    The trailing slash is important; this implies we are using maildir mailboxes.
    NOTE: After editing hash: files, you MUST run `postmap` on the file.

virtual_alias_maps = hash:/etc/postfix/vmail-alias
    The "virtual" equivalent of /etc/aliases.
    Format is simple:
    Like above, this file must be fed to postmap.

    This is important. We'll be using one user to manage virtual mailboxes.
    This could be considered a security risk.
    Use your best judgement. We're going for simplicity here.
    Create a user named 'vmail' with a unique UID/GID and specify 'static:<id>' for both of these.
    (If you don't know how to do this on your own, don't run a mailserver.)


Now, for this host we also want to push mail through SpamAssassin.
This assumes you have SpamAssassin configured and spamd is running.
(That part is your problem. It's easy, but varies from one distribution to another. Google it.)

This is called 'after-queue' inspection. After queue mail is pushed to a filter script.
The filter script feeds SpamAssassin, then decides what to do with the mail.

We want to do filtering as an unprivileged user.
-sh$ useradd -s /bin/false mailfilter

Now we need our filter script.
Here's an example that sends messages flagged as spam by SpamAssassin to a spam dump address.
You can tweak as-needed to just trash spam, do something more complex like filter into user .Junk
maildirs, whatever -- it's pretty easy to understand (of course, a severely complex script
will negatively impact mail performance quite noticably...)

#### /etc/postfix/ ####

 # must be chmod +x
 # also see
 SPAMTRAP='spamtrap@my.domain.example'  ## !!! EDIT THIS !!!
 SENDMAIL="/usr/sbin/sendmail -i"
 SPAMASSASSIN="/usr/bin/spamc -u mailfilter"

 # Exit codes from <sysexits.h>

 umask 077

 OUTPUT="`mktemp -p /tmp mailfilter.XXXXXXXXXX`"
 if [ "$?" != 0 ]; then
     /usr/bin/logger -s -p mail.warning -t filter \
         "Unable to create temporary file."
     exit $EX_TEMPFAIL

 # Clean up when done or when aborting.
 trap "rm -f $OUTPUT" EXIT TERM
 # toss it at spamtrap if flagged, throw it back to post queue on error
 # otherwise pass it
 if [ "$return" = 1 ]   # spam
    /usr/bin/logger -s -p -t filter \
          "Redirected SPAM to spamtrap."
  elif [ "$return" != 0 ]; then   # borked
     /usr/bin/logger -s -p mail.warning -t filter \
         "Temporary SpamAssassin failure (spamc returned $return)"
     exit $EX_TEMPFAIL
  else  # we're cool, not spam, feed it back to postfix
    $SENDMAIL "$@" < $OUTPUT
 exit $?

#### EOF ####

Okay, so we've got a workable filter script.
Let's tell Postfix to push incoming mail through it.
Edit /etc/postfix/ and find the 'smtp' directive.
Add '-o content_filter=spamass' as follows:

## /etc/postfix/ ##

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


Now browse towards the end of the file, where external interfaces are defined.
Add a new interface as follows:

## /etc/postfix/ ##

spamass   unix  -       n       n       -       -       pipe
  flags=Rq user=mailfilter argv=/etc/postfix/ -oi -f ${sender} ${recipient}


That should be all you need.


dovecot is great; simple, lightweight, and can handle authentication for us.
We already set up Postfix to hook SASL authentication into dovecot-auth.
Now we need something to auth against.

The following is a fairly complete dovecot.conf.

## /etc/dovecot/dovecot.conf ##
  protocols = imap pop3 imaps pop3s
  disable_plaintext_auth = no
  ssl = yes
  # generate these w/ openssl:
  ssl_cert_file = /etc/dovecot/ssl/cert/dovecot.pem
  ssl_key_file = /etc/dovecot/ssl/key/dovecot.pem
  ssl_verify_client_cert = no

  log_path = /var/log/dovecot
  info_log_path = /var/log/
  login_chroot = yes
  login_user = dovecot
  login_greeting = dovecot ready

  valid_chroot_dirs = /var/spool/vmail
  # maildir in /domain/name
  mail_location = maildir:/var/spool/vmail/%d/%n

  protocol imap {
    login_executable = /usr/lib/dovecot/imap-login
    mail_executable = /usr/lib/dovecot/imap

  protocol pop3 {
    login_executable = /usr/lib/dovecot/pop3-login
    mail_executable = /usr/lib/dovecot/pop3
    # outlook sucks hard:
    pop3_client_workarounds = outlook-no-nuls oe-ns-eoh

  # dovecot-auth for SASL:
  auth default {
   mechanisms = plain digest-md5 login

   passdb passwd-file {
     args = /etc/dovecot/users
   userdb passwd-file {
     args = username_format=%n /etc/dovecot/users
   # needed for postfix to hook into dovecot-auth:
   socket listen {
    client {
      path = /var/spool/postfix/private/auth
      mode = 0660
      user = postfix
      group = postfix

The passdb/userdb directives above tell dovecot that auth will be handled by
a simple '/etc/passwd'-style flatfile.
The format of /etc/dovecot/users is as follows:{plain}j0ema1l:1008:1008::/var/spool/vmail/{plain}b0bmail:1008:1008::/var/spool/vmail/

Fairly self-explanatory format.
First field is the username (including the domain in login names cuts down confusion)
Second field is the password ({plain} specifies plaintext method -- you should probably at least use crypt...).
Use the ID for your 'vmail' user created during Postfix configuration in place of '1008'
The directory field should be the path to the domain this user is on.

IMPORTANT: You definitely do not want anyone reading /etc/dovecot/users:
  -sh$ chgrp dovecot /etc/dovecot/users && chmod o-rwx /etc/dovecot/users

Now we have virtual mail. Create the spool directory for your domains:
  -sh$ mkdir -p /var/spool/vmail/
  -sh$ mkdir -p /var/spool/vmail/
We want the vmail user we created earlier to own this:
  -sh$ chown -R vmail:vmail /var/spool/vmail
Check permissions on /etc/dovecot/users -- definitely make sure it isn't world-readable...
Add a user or two using the script below or similar.
Verify that everything looks correct after adding, then fire up postfix and dovecot.

If you're looking for simple and reasonably good webmail, try the Roundcube project.


Adding users manually sucks.

Here's an example script that handles adding a new user.
Read, understand, modify as appropriate:

## /etc/postfix/ ##

 # quick ugly hack for adding virtual mailboxes



 if [[ `id -u` != 0 ]]
   echo "Need to be superuser, sorry!"
 echo "**** Available domains:"
 cat ${postfix_vdomains}
 echo -n "** New mailbox domain: "
 read domain
 echo -n "** User name: "
 read username
 echo -n "** Passwd: "
 read passwd
 echo "*** Adding ${username}@${domain} to ${postfix_vmaps}"
 echo "${username}@${domain} ${domain}/${username}/" >> ${postfix_vmaps}
 postmap ${postfix_vmaps}
 echo "*** Creating mailboxes on disk in ${spool_dir}/${domain}/${username}"
 mkdir -p ${spool_dir}/${domain}/${username}/{new,cur,tmp} || echo "mkdir failed"
 mkdir -p ${spool_dir}/${domain}/${username}/.Trash/{new,cur,tmp}
 mkdir -p ${spool_dir}/${domain}/${username}/.Junk/{new,cur,tmp}
 mkdir -p ${spool_dir}/${domain}/${username}/.Sent/{new,cur,tmp}
 mkdir -p ${spool_dir}/${domain}/${username}/.Drafts/{new,cur,tmp}
 echo -e "Trash\nJunk\nSent\nDrafts" >> ${spool_dir}/${domain}/${username}/subscriptions
 chown -R ${vmail_usr}:${vmail_usr} ${spool_dir}/${domain}/${username}
 chmod -R 700 ${spool_dir}/${domain}/${username}
 echo "*** Adding user to ${user_db}"
 echo "${username}@${domain}:{plain}${passwd}:${vmail_uid}:${vmail_gid}::${spool_dir}/${domain}/:/bin/false::" >> ${user_db}
 echo "*** Reloading mail servers"
 /etc/init.d/postfix reload
 /etc/init.d/dovecot reload
 # EOF


Deletion is as easy as removing from postfix/vmail-maps (+ run postmap) and dovecot/users.
(...and archival/deletion of the appropriate mailbox in /var/spool/vmail)

Jon Portnoy
avenj/ #eris
Back to top
View user's profile Send private message

Joined: 04 Oct 2006
Posts: 743
Location: Brooklyn, New York

PostPosted: Tue Aug 17, 2010 2:10 pm    Post subject: Reply with quote

thanks for this script.
Back to top
View user's profile Send private message

Joined: 25 Jul 2004
Posts: 912
Location: Pompano Beach, Florida

PostPosted: Mon Aug 23, 2010 4:11 pm    Post subject: Reply with quote

Yes thanks, lots of good info ++
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Documentation, Tips & Tricks All times are GMT
Page 1 of 1

Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum