http:// / relaying.shtml

Relaying with qmail

I've noticed that a lot of people don't seem to understand how qmail handles (or doesn't handle) relaying- deciding when to accept messages, especially if you're "sending mail out" to an email address which is part of a domain which isn't handled on the server itself.

Hopefully this page will clarify how it works.


As you may know, qmail itself is made up of several "smaller" programs, each of which does its one little piece of the overall mail server job, and does it well. The program which handles incoming SMTP is called qmail-smtpd.

By default, qmail-smtpd will accept ANY incoming message.

Let me repeat that.

By default, qmail-smtpd will accept ANY incoming message.

If you're thinking "this sounds like an open relay", you are correct. It IS an open relay. BY DEFAULT, qmail-smtpd is an open relay.

Of course, an open relay is a BAD THING(tm). This is why qmail has the /var/qmail/control/rcpthosts and /var/qmail/control/morercpthosts.cdb files. IF THESE FILES EXIST, qmail-smtpd will not accept mail for any domain which is not listed in them.

This is why almost every "run" script for an SMTP service, including my own, includes code which makes sure that the rcpthosts file exists, and refuses to start the SMTP service if it does not exist.

When a client connects to qmail-smtpd and wants to send a message to your server, qmail-smtpd walks through a set of tests to determine whether or not to accept the message. The logic behind those tests looks like this:

If none of these conditions are true, qmail-smtpd will refuse to accept the message and the SMTP client will receive an error message which looks like this:

553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)

While this is the most commonly seen message, other messages are possible depending on which anti-SPAM patches you are using. These other messages should be self-explanatory, this web page is not going to spend a lot of time trying to guess and explain every possible message.

The sections below provide more detail about each of the conditions which can make qmail-smtpd accept a message.


qmail-smtpd will accept an incoming message if an environment variable called RELAYCLIENT exists when qmail-smtpd starts. This variable normally does not exist, unless you are purposely setting up an open relay for some reason.

Normally qmail-smtpd runs as a child under a program called tcpserver. tcpserver works by listening to a specific TCP port, usually on a single IP address but by specifying the IP address 0 it will listen to every IP address on the machine.

tcpserver supports an access list mechanism (based on cdb files again) which controls the IP addresses which are and are not allowed to connect to your server. If the connection is allowed, tcpserver runs the actual command to provide your service (in this case, "qmail-smtpd") with the socket set up as stdin/stdout for that command. It also sets some environment variables to tell the command things like what the client's IP address is, since the command would otherwise have no way to tell.

The access control file can also be used to add your own environment variables when a client connects from a certain IP range. For example, if you have a machine or a set of machines which should always be allowed to send mail through your server, you can set their IP address in the access control file so that it creates a RELAYCLIENT environment variable (which qmail-smtpd recognizes as giving the client permission to relay, bypassing the rcpthosts check.)

For example...

:allow,RBLSMTPD="-We do not accept mail from IP addresses without reverse DNS."

What this means:

The choice of which environment variables you want to add will depend on what service program or programs you are running. For example, the RBLSMTPD variable is only useful if the rblsmtpd program is in the command line before qmail-smtpd.


qmail-smtpd will accept an incoming message if the client has sent a successful AUTH command in the current session.

The AUTH command allows a client to "prove" that they are authorized to relay, based on a userid and password (or other credentials, depending on how the server is configured.) Most servers use the same id/password database for the AUTH commands that they use for access to POP3 or IMAP mailboxes.

This page has more information on the AUTH command, including a walk-through of how to test your server to make sure the command is being properly advertised and/or accepted.


qmail-smtpd will accept an incoming message if the domain portion (the portion to the right of the "@" sign) of the recipient's address is listed in either the /var/qmail/control/rcpthosts or /var/qmail/control/morercpthosts.cdb file.

However, if the rcpthosts file does not exist, qmail-smtpd will assume that your intent is to run as an open relay, meaning that you wish to accept mail from anywhere in the world, FOR anybody in the world. Do not do this unless the machine itself is behind a firewall which blocks incoming traffic on TCP port 25, or your server WILL be found and abused by spammers.

Why two files? When qmail-smtpd starts, it has to read the entire contents of the rcpthosts file into memory so that it has the list of domains to check against. For servers with a small list (i.e. less than 50 domain names) this is fine, but for ISP mail servers which handle mail for hundreds or thousands of domain names, the time it takes to read the file and sort it into memory can slow down mail processing.

Because cdb files (which are read-only database files) are blindingly fast, it takes less time to check whether a given domain name exists in a 500-entry morercpthosts.cdb file than it does to read 500 lines of text into memory. Multiply this by the number of messages a busy mail server has to deal with (several messages per second in some cases) and you can see why using a cdb file is a good idea.

Many people have asked whether they should add their own email address, or hostname, or IP address, to these files... the answer is no. These files are only used to check the domain names from the recipient addresses on the messages which are sent to the server. For information on how to "add IP addresses", see the RELAYCLIENT section below.