back to index


Wed Oct 29 2003, 6:45 PM

PicoQMAIL is a very very trivial send-only mailserver. Its purpose is to be a very simple device serving as an interface between "sendmail" utility and a SMTP relay.


Takes mail from sendmail's stdin, formats it for consumption by a SMTP relay, open TCP connection to a selected one, and feed it with the mail.


The system uses unmodified sendmail and qmail-inject utilities from the qmail package. The qmail-queue is replaced by a symlink to minismtpq.

sendmail serves as a wrapper of qmail-inject. qmail-inject takes the mail from stdin, extracts the From: and To:/Cc:/Bcc: headers, spawns qmail-queue, feeds the mail body with headers to its descriptor 0 and the from and to addresses to descriptor 1. Here qmail's original parts end.

qmail-queue is replaced with minismtpq. It takes the list from descriptor 1, extracts the From: address and the To: addresses, and for every To: address copies the mail body to a file with a filename composed of the current date-time, script's PPID (to prevent namespace collisions), From:, and To:, located in a spool directory. Then launches minismtpsend on each of them. If the file still exists after being processed by minismtpsend, :.spool is appended to its filename.

minismtpsend is fed by the filename. Parses it, extracts the From: and To: address (colons act as separators), formats the input file for SMTP, and pipes it through Netcat to the configured relay server. Netcat's output, the server's responses, is piped to a file. The result file is then grepped for error codes. If there is no error code in and a 250 response is present, the mail is considered delivered and is erased. If there is a 4xx response code present, the result file is stored aside in Undelivered directory, and an attempt will be done next time. If there is 5xx response present, the mail is moved to Undelivered directory together with its result file.

minisendcron is the script responsible for repeated delivery attempts. It is intended to be run every couple minutes from crontab. If there is its lockfile present, it checks if the lockfile's age is less than 30 minutes. If no, the lockfile is removed, otherwise the script ends, presuming other its copy already runs. The script then runs minismtpsend on every file in the spool directory that ends on .spool (which together with renaming them with minismtpq makes sure that minisendcrond won't attempt to send a file just received by minismtpq; it's handed over to minisendcron's care only if the immediate send by minismtpsend doesn't work.


The mandatory file is /var/qmail/control/me, where the name of the server is stored (eg. Various configuration details are stored in /var/qmail/control/minivars, which is included in all three mini* scripts. The IP address of the mail relay is stored in /var/qmail/control/relayip.


Untar the archive from root directory (this will create the /var/qmail/ hierarchy with the necessary permissions). Remove the eventually present Put the configuration line to /etc/crontab (the line is described in the comment of minisendcron), reload or restart crontab.


The error handling is rather rudimentary.

The spool directories have to be world-writable until better way will be figured out - setuid bit somehow doesn't work on shell scripts. Maybe a simple binary suid app that will reside on place of qmail-queue, and execve()s the minismtpq?

Rather crude, but very simple and not requiring any separate daemon, and with trivial maintenance.


picoqmail.tar.gz - directory structure,

this README, two Linux binaries and three shell scripts. The source code for qmail-inject and sendmail binaries is not included, extracting it from the complete qmail package would be too much of hassle. If you need to rebuild it, get the qmail sources from The binaries included in the archive are compiled for Linux. If you want other OS, compile the binaries yourself.

If you have any comments or questions about the topic, please let me know here:
Your name:
Your email:
Leave this empty!
Only spambots enter stuff here.