setting up a qmail server

(please don't blame me for bad english,
it's not my mother language.
Corrections, however, are always welcome!)

   motivation  
  

Dan Bernstein's qmail package is a fast, secure and state of the art mail transfer agent (MTA). However, people often have problems setting it up for large systems with virtual domain handling, POP-boxes and forwarding via dialup connections.
Here are my thoughts on this and how we've handled it at SpaceNet

 

   getting started  
  

The whole setup ist done with a vanilla qmail-1.01 except for a modified checkpassword script based on Jos Backus' vqpop and additionally Dan Bernstein's serialmail package.

Throughout this file I will use example.com as the domain everything should be set up for.

As all the POP users (some 10000) should not be real users on the system but virtual one, we've created an user popusr that is the owner of all those files, directories and POP boxes.

 

   receiving email  
  

To accept email for other domains you have to add them to control/rcpthosts. To also cover all hosts and subdomains within this domain (and that is what you probably want), precede the domain with a dot and add this, too. Thus your control/rcpthosts file should contain:

    example.com
    .example.com
This file ist read by qmail-smtpd on each email it is receiving, so you don't have to restart anything.
Now your qmail system accepts emails for the domain example.com.
 

   delivering email  
  
  • the control/virtualdomains file

    Once qmail has accepted the email it needs to know what to do with it. We've chosen the virtualdomains/users mechanism of qmail to sort things out.
    For each of the domains you want to serve you have to add entries to the control/virtualdomains file. This file is organized as lines, containing a mapping from a domain to an id. For an easier reading and assigning we've chosen to use the name of the domain as the id.

    Note: the id could be any identifier that is kind of unique in identifying the domain it is mapped to. Choosing the domain name for the id was our layout decision.
    The same rules for domains and subdomains/hosts apply for control/virtualdomains as they do for control/rcpthosts. As we want domains and hosts/subdomains to be handled by the same id the entries in control/virtualdomains look like:
        example.com:example.com
        .example.com:example.com
    There are cases, where you have various delivery strategies for emails within one domain. In our example we want to have everything for example.com to be delivered via POP boxes, except for host some.example.com, to which email should be delivered via SMTP to a dialin account. So we add one more line to control/virtualdomains:
        some.example.com:some.example.com
    In order to make qmail know about your changes to the control/virtualdomains file you have to send a signal 1 to the qmail-send process (or restart it).

  • the users/assign file

    The next step is to actually define where to deliver the email to. This is done with the users/assign file. Qmail looks up this file with the id defined above to find a matching entry.

    We're using an unique handle for each of our customers and we've organized the filesystem making use of it. Example Inc. would have been assigned e.g. a handle of ex1.
    All the POP Boxes would physically be found in a directory
        /home/popmail/e/ex1/POP/
    and would be named ex1-0000, ex1-0001, ex1-0002, ...

    The .qmail control files for example.com would be located in the directory

        /home/popmail/e/ex1/DOMAINS/example.com/
    Note: Be sure that the above directory and all the .qmail files in there belong to the appropriate user (in our case popusr) and that they are neither world nor group writeable
    The SMTP deliveries are not organized within this structure, but are located in
        /home/serialmail/some.example.com/
    Although it would be no problem to have them in e.g. /home/popmail/e/ex1/SMTP/some.example.com or another place.

    This leads to a users/assign file that looks like:

        +example.com-:ex1:510:51:/home/popmail/e/ex1/DOMAINS/example.com:-::
        +some.example.com-:ex1:510:51:/home/serialmail/some.example.com:-::
        .
    Note:
    • 510 is the UID of the user popusr.
    • 51 is the GID of the user popusr.
    • ex1 is used by us as an identifier for our customer id. According to the qmail-users(5) man-page this should be popusr
    • Don't forget to have a dot on a line by itself as the last line in the file.
    qmail-local, which make use of the users/assign file, actually uses users/cdb. A change to users/assign will have no effect until /var/qmail/bin/qmail-newu is run and creates an uptodate cdb file.

  • delivery to POP boxes

    For POP users set up the boxes with

        $ cd /home/popmail/e/ex1/POP
        $ /var/qmail/bin/maildirmake ex1-0000
        $ /var/qmail/bin/maildirmake ex1-0001
        $ /var/qmail/bin/maildirmake ex1-0002
        $ chown -R popusr ex1-0000 ex1-0001 ex1-0002
    Then you have to create "mappings" to those Maildirs. This is done by creating .qmail files. To make qmail deliver all emails for joe@example.com to the POP box ex1-0001 simply
        $ cd /home/popmail/e/ex1/DOMAINS/example.com
        $ echo "/home/popmail/e/ex1/POP/ex1-0001/" > .qmail-joe
        $ chmod 644 .qmail-joe
        $ chown popusr .qmail-joe
    Note:
    Be sure to have a trailing slash ("/") after the name of the POP box directory (.../POP/ex1-0001) in the .qmail file, to have qmail deliver to a Maildir not to a Mailbox.
    As RFC ???? requires the existance of a
    postmaster address, you should set up a .qmail-postmaster file for each domain. Either map it to the appropriate mailbox in that domain or map it to yourself.
    You may also want to set up a .qmail-default file for a domain, that catches all unknown addresses, for which no .qmail file exists. A good way is to map it to the postmaster address of that domain.

  • SMTP deliveries

    For SMTP deliveries you have some choices:

    1. if you are only backup MX (i.e. it exists an host with a better MX priority in DNS) then simply add the domain to the control/rcpthosts file, all else will be handled by qmail automatically.
    2. if you are a relay for a customer (this might be useful if his mailer is behind a firewall, you are the best MX and so you get the mails and his mailer does only accept mails from your mailer) then you additionally have to add entries to the control/smtproutes file specifying the domain and the hostname of his mailer:
          second-example.com:mail.second-example.com
          .second-example.com:mail.second-example.com
      Again, delivery will be handled by qmail automatically.
    3. if the customer is connected through a dialup connection (like assumed for the above some.example.com) the quadratic retry strategy of qmail is bad for you, because the customer usually doesn't like to have to be online for a long period of time to receive his email.
      Dan Bernstein's serialmail package will be your friend in this setup.
      You could either have some mechanism to allow the customer to trigger the delivery (see http://www.qmail.org/ or the qmail mailing list archive for pointers) or do it on a regular basis via a script called from cron. The latter is, however, only usable, if your customers have static IP addresses.
    We've chosen the cron way. For that we've set up the /home/serialmail/some.example.com/ directory (this is defined in users/assign above) like the following:
        $ cd /home/serialmail/some.example.com
        $ echo "some.example.com" > RELAYHOST
        $ /var/qmail/bin/maildirmake ./Maildir
        $ chown -R popusr ./Maildir
        $ echo "./Maildir/" > .qmail-default
        $ chmod 644 .qmail-default
        $ chown popusr .qmail-default
    For delivery we have a "master script" that starts a "delivery script" for each directory within /home/serialmail/ with a grace period of 1 second. The delivery script checks if the RELAYHOST file is locked. If it is locked there is already a transfer underway, which has not yet finished. If it is not locked, it locks the file and checks whether Maildir/new/ contains any files. If not, it unlocks the RELAYHOST file and exits. If messages do exist, it starts serialmail, waits for it to complete and then unlocks RELAYHOST and exits.
    Starting the master script from cron every 2 minutes guarantees that a delivery is attempted every two minutes.
 

   credits  
  

  • D. J. Bernstein
  • Jos Backus
  • Harald Hanche-Olsen
  • Russell Nelson
  • Volker Paulsen
  • and all the members of the qmail mailing list
 

Copyright © 1997 Markus 'Maex' Stumpf
created: Thu Nov 6 21:15:01 CET 1997
last modified: Sat May 1 00:15:07 CEST 2004
Maex