Be default, qmail-smtpd doesn't log any messages. The following instructions will enable you to capture qmail-smtpd's 5XX and 4XX error messages as they are sent to the client. They are based on advice by Richard Lyons and Peter van Dijk.
The key to this approach is to run qmail-smtpd under Dan Bernstein's tcpserver program. There are various ways to do this, starting with the advice in the qmail FAQ, but it is important that you use multilog rather than splogger to capture your log messages. If you're already using multilog with qmail-smtpd, read steps #5 and #6, and adapt your existing script. If you aren't, and don't already have a preferred way of doing it, then do the following:
Download and install ucspi-tcp.
Download and install daemontools.
Create folders for the smtpd daemon and multilog:
mkdir /var/qmail/smtpd chmod 03755 /var/qmail/smtpd cd /var/qmail/smtpd mkdir log mkdir log/main touch log/status chown qmaill log/main log/status chgrp nofiles log/main log/status
Create a tcprules file, specifying who can access your smtp server. Follow the directions in the qmail FAQ to set up the file. Here's a simple example of an smtp.rules file:
192.168.1.:allow,RELAYCLIENT="" 127.:allow,RELAYCLIENT="" :allow
Call your rules file /etc/tcpcontrol/smtp.rules, and create the cdb file using the following commands:
cd /etc/tcpcontrol tcprules smtp.cdb smtp.tmp < smtp.rules
The final ":allow" rule allows outside hosts to connect to your server to deliver incoming mail to you. If you made a default ":deny" rule, then your server can only be used by clients from IP addresses you specifically allowed--e.g., clients on your local LAN.
Create a file named run, with permissions 0755, with the following contents:
#!/bin/sh exec tcpserver \ -x /etc/tcpcontrol/smtp.cdb \ -v -u 504 -g 501 0 smtp \ /usr/local/bin/recordio \ /var/qmail/bin/qmail-smtpd 2>&1
In this script, 504 is the uid of the qmaild user, and 501 is the gid of the nofiles group.
The recordio line is the key to logging 5XX messages. Recordio is part of ucspi-tcp, and it runs qmail-smtpd while logging all I/O to file descriptor 2. If we took no further steps, then the entire SMTP transaction would always be logged, including the contents of emails themselves. When you set up multilog in the next step, you will tell it to filter out all but rejection messages.
If you didn't want to record the server's 5XX messages, you could completely omit the second-to-last line. If you already run qmail-smtpd under tcpserver, then all you need to do is add this recordio line.
Note that if you run rblsmtpd or other wrappers around qmail-smtpd, then you need to insert the recordio command before any other wrapper program.
Create a file named log/run, with permissions 0755, and the following contents:
#!/bin/sh exec \ /usr/local/bin/setuidgid qmaill \ /usr/local/bin/multilog t '-* * > *' '-* * < *' '+* * > 5*' '+* * > 4*' ./main
The setuidgid program causes multilog to run as user qmaill. The "t" argument to multilog instructs it to prepend a timestamp on every line. The second argument tells multilog to ignore all input lines created by recordio to document data sent from the server to the client; the third argument tells multilog to ignore data sent from the client to the server. The fourth argument tells multilog to change its mind and log packets in which the server sent a "5XX" error code to the client. The fifth argument does the same for "4XX" error codes. The final argument tells multilog to log to files in the folder named "./main", as per multilog's default settings.
If you already run qmail-smtpd under tcpserver, and you already log using multilog, then you simply need to add the arguments between "t" and "./main" to capture 5XX messages in your logs.
Disable the current method of running qmail-smtpd. For example, if you're running it under inetd, then remove the lines mentioning qmail-smtpd from /etc/inetd.conf and send inetd a HUP signal.
Arrange for qmail-smtpd to be started by svscan:
ln -s /var/qmail/smtpd /service
Cat the log file /service/smtpd/log/main/current, and verify that the file contains an entry like "tcpserver: status: 0/40".
Attempt to send a message via SMTP that should succeed, and then a message that should fail. You should see the normal log messages in /service/smtpd/log/main/current, with the addition of a 5XX error message for the message that failed.
That's it!
