Installing qpsmtpd on SuSE 10.0 with Plesk 8.0

[14-01: Here's an update to these instructions.
[08-11: New installation on 10.3/8.6.0]

The qpsmtpd daemon started as a replacement daemon for the qmail-smtpd SMTP receiver from the qmail mail transport agent (MTA), but it can also be used with other MTAs. qpsmtpd is written in pure Perl and can be customized easily. It consists of a core that implements a complete SMTP server, and a number of plug-ins that enhance the operations of the server. These plug-ins allow for the checking of recipients and senders, as well as virus scanning, spam checking, blocking lists (DNS and RHS), SMTP AUTH and TLS. If you like to tweak, you can adapt qpsmtpd to almost any environment and task.

In this article I collect information that I've gathered from various sources and customized for installing qpsmtpd on Suse and Plesk.

The best sources I've found:

What I'm writing here is what has worked for me. It may or may not work for you — be sure to know what you're doing!

Get qpsmtpd and read the README with perldoc README as long as you still can. I've noticed that the qpsmtpd install sequence somehow trashes perldoc, but no one seems to know why and how to resurrect it...

Installing qpsmtpd

Test Drive

Add a group and user called smtpd, and expand qpsmtpd in his home directory:

groupadd smtpd
useradd -d /home/smtpd -s /sbin/nologin -g smtpd -m smtpd
cd ~smtpd

remove all skeleton files
get qpsmtpd (I use subversion to retrieve the latest development version — you may want to use the stable version instead):

svn co http://svn.perl.org/qpsmtpd/trunk qpsmtpd

I prefer to create the config directory above the qpsmtpd tree and create a soft link where qpsmptd expects it:

mkdir config
cp qpsmtpd/config.sample/* config
ln -s ../config qpsmtpd/config

You may need to customize config/IP, and possibly remove config/rcpthosts to get qpsmtpd to use qmail's control/rcpthosts.

If you can't wait to try out qpsmtpd, then it's possible to run it under the root acount at this point (did I mention that it breaks your perldoc?), but the following steps will allow you to run it more safely under the new smtpd user: smtpd needs write access to ~smtpd/tmp/ and ~smtpd/log/ but no other directory, so do something like this:

echo /home/smtpd/tmp >~smtpd/qpsmtpd/config/spool_dir
chown -R root.smtpd ~smtpd
find ~smtpd -type d -exec chmod 750 {} \;
mkdir ~smtpd/tmp
chown smtpd ~smtpd/tmp
chmod 700 ~smtpd/tmp
mkdir /var/log/qpsmtpd
chown smtpd /var/log/qpsmtpd
chmod 700 /var/log/qpsmtpd
ln -s /var/log/qpsmtpd ~smtpd/log

Setting spool_dir is essential for running qpsmtpd — I had to ask the friendly specialists on the qpsmtpd mailing list to get this piece of the puzzle.

08-11: I had to install the Net::DNS and Mail::Header Perl modules (see How to Install a CPAN Perl Module).

Now you can test drive qpsmtpd — this is an essential step because it allows you to see any error messages due to installation problems that you need to solve before you can proceed.

cd qpsmtpd
./qpsmtpd-forkserver -u smtpd

Connect through a second terminal (or telnet remotely):

telnet localhost 2525

qpsmtpd greets you and you can try an interactive SMTP session if you like:

220 example.com ESMTP qpsmtpd 0.3x ready; send us your mail, but not your spam.
helo dude
250 example.com Hi example.com [127.0.0.1]; I am so happy to meet you.
quit
221 example.com closing connection. Have a wonderful day.
Connection closed by foreign host.

Running qpsmtpd as a Daemon under xinetd

Of course an MTA is not intended to be run interactively. It's purpose is to be ready day and night to accept email on your behalf and to reject the junk. Under Plesk the installed SMTP receiver is qmail-smtpd, and it is managed by xinetd. The control file is /etc/xinetd.d/smtp_psa:

service smtp
{
    socket_type = stream
    protocol = tcp
    wait = no
    disable = no
    user = root
    instances = UNLIMITED
    server = /var/qmail/bin/tcp-env
    server_args = /var/qmail/bin/relaylock /var/qmail/bin/qmail-smtpd /var/qmail/bin/smtp_auth /var/qmail/bin/true /var/qmail/bin/cmd5checkpw /var/qmail/bin/true
}

There are a number of ways to run qpsmtpd. My MTA only needs to handle a few hundred emails per day and I chose to run qpsmtpd under xinetd, because that's what I already have, and I'll show you how to do it:

You can install qpsmtpd using

perl Makefile.PL
make
make test
make install
make clean

or just run it from ~smtpd. There seems to be no advantage to installing it, but if you go that route, you'll probably need to put the fully qualified name of the plugin directory into config/plugin_dir.

Let's run qpsmtpd from ~smtpd instead...

To focus on getting qpsmtpd running, comment out all the plugins in config/plugins, except for the following:
    hosts_allow
    dont_require_anglebrackets
    rcpt_ok
    queue/qmail-queue

Create ~smtpd/in.qpsmtpd as follows:

cat - >~smtpd/in.qpsmtpd <<EOF
#!/bin/sh
cd ~smtpd/qpsmtpd
exec ./qpsmtpd 2>/dev/null
EOF
chown root.root ~smtpd/in.qpsmtpd
chmod 0755 ~smtpd/in.qpsmtpd

Finally create the file to configure xinetd to run qpsmtpd:

cat - >/etc/xinetd.d/qpsmtpd-xinetd <<EOF
#
# description: The qpsmtpd server serves smtp sessions
#
service qpsmtpd
{
        type            = UNLISTED
        port            = 2525
        flags           = REUSE
        socket_type     = stream
        protocol        = tcp
        wait            = no
        user            = smtpd
        groups          = yes
        server          = /home/smtpd/in.qpsmtpd
        log_on_failure  += USERID
        disable         = no
        rlimit_as       = 128M
        rlimit_cpu      = 100
        instances       = 40
        per_source      = 10
        cps             = 50 10
}
EOF
chown root.root /etc/xinetd.d/qpsmtpd-xinetd
chmod 0644      /etc/xinetd.d/qpsmtpd-xinetd

This tells xinetd to run qpsmtpd on port 2525, which is great for testing the daemon without disturbing the SMTP server running on port 25. Restart xinetd to make it happen:

/etc/init.d/xinetd restart

Now, telnetting to port 2525 should work:

telnet localhost 2525
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 example.com ESMTP qpsmtpd 0.3x ready; send us your mail, but not your spam.
QUIT
221 example.com closing connection. Have a wonderful day.
Connection closed by foreign host.

If there is a problem, try removing the redirection to /dev/null in in.qpsmtpd to get more information.

To get a sense of what kind of and how much logging information is available, add the following lines to ~smtpd/config/plugins:

logging/file:0          loglevel LOGEMERG       nosplit /var/log/qpsmtpd/0-emergency-%Y.log
logging/file:1          loglevel LOGALERT       nosplit /var/log/qpsmtpd/1-alert-%Y.log
logging/file:2          loglevel LOGCRIT        nosplit /var/log/qpsmtpd/2-crit-%Y-%m.log
logging/file:3          loglevel LOGERROR       nosplit /var/log/qpsmtpd/3-error-%Y-%m.log
logging/file:4          loglevel LOGWARN        nosplit /var/log/qpsmtpd/4-warn-%Y-%m-%d.log
logging/file:5          loglevel LOGNOTICE      nosplit /var/log/qpsmtpd/5-notice-%Y-%m-%d.log
logging/file:6          loglevel LOGINFO        nosplit /var/log/qpsmtpd/6-info-%Y-%m-%d.log
logging/file:7          loglevel LOGDEBUG       nosplit /var/log/qpsmtpd/7-debug-%Y-%m-%d-%H%M%S.log

This will create lots of logging information, separated by severity and date, and you'll probably want to comment out the more verbose levels as soon as you've seen what they do.

Send Yourself a Test Message

Now try to send yourself a test message by talking directly to qpsmtpd.

telnet localhost 2525
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 example.com ESMTP qpsmtpd 0.3x ready; send us your mail, but not your spam.
HELO dude
250 example.com Hi example.com [127.0.0.1]; I am so happy to meet you.
MAIL FROM: <sender@example.com>
250 <sender@example.com>, sender OK - how exciting to get mail from you!
RCPT TO: <postmaster@example.com>
250 <postmaster@example.com>, recipient ok
DATA
354 go ahead
From: <someone@example.com>
Subject: testing

test
.
250 Queued! 1170241128 qp 14147 <>
QUIT
221 example.com closing connection. Have a wonderful day.
Connection closed by foreign host.

Congratulations, you should now see your first qpsmtpd-relayed message in your inbox!

Configure qpsmtpd

Configure qpsmtpd for your environment. If you have a /var/qmail/control/rcpthosts file, you probably want to remove qpsmtpd's rcpthosts file, which blocks all incoming mail!

Go live!

Change the top of /etc/xinetd.d/qpsmtpd-xinetd to

#service qpsmtpd
service smtp
{
#       type            = UNLISTED
#       port            = 2525

Disable the qmail-smtpd SMTP receiver by setting its disable=yes and restart xinetd:

edit /etc/xinetd.d/smtp_psa
/etc/init.d/xinetd restart

Want more?

Continue with Implementing SMTP Authorization with qpsmtpd.