ckuser_cyrus.m4 - SENDMAIL+CYRUS address validation feature

Introduction

Imagine you have installed Sendmail as a MTA and Cyrus IMAPD as a local mailbox server on a busy mail server. I believe it's not that uncommon, because these two are very powerful and feature-rich open source products.

Although, in default configuration, Sendmail verifies destination of local recipients in UNIX user databases, it doesn't automagically happen when the standard local mailer gets replaced by the Cyrus mailer. So, every time a mail is not accepted (by various reasons) by the latter, Sendmail generates and sends a `Bounce' message back to the sender, having priorly accepted the original mail from him. And mail usually gets rejected by Cyrus because of a nonexistent or a nonpostable mailbox.

Inconveniences arise when (especially) some automated mailer, like a mail worm or some spammer's software, sends a lot of messages to your domain. Some of them, of course, you can filter out. But there will remain a portion of it that lets through and results in bounces, described above. Since there was no real sender of this mail, there will hardly be a server, willing to accept the bounces. Therefore, they end up in the postmaster's mailbox as bounces for the bounces, i.e. double bounces. I consider it useless to read tens of these. On the other hand, such situation usually doesn't occur with valid senders, because their return addresses are reachable.

Needless to say the MTA machine gets useless load, resulting from generating the bounces and trying to send them for many times before they time out.

If the verification of local addresses could happen before the mail is accepted, these problems would go.

Resolution

Luckily, there are useful hooks in configuration file of Sendmail, which one can utilize for this purpose. Another good news is that Cyrus people provide the `smmapd' daemon (since version 2.2.3) to verify destination mailboxes, which conforms to the `trivial query' protocol, supported as maps of type `socket' by Sendmail since version 8.13 (and in 8.12.7+ through a patch).

To complete the puzzle, one has to provide rules for sendmail to do the lookups at the `RCPT TO:' stage of its SMTP receiving phase.

Has anyone done this already?

I recently came across collections of rules by Andrzej Adam Filip at this site and was very happy with using them. Their installation, though, did not happen to be trivial. To help myself and the other users, I submitted a PR with patches to the FreeBSD mail/sendmail port to ease installation of his rules at least for FreeBSD users.

Later, I discovered that these rules didn't work well with milters that delete recipients' addresses while filtering (I strongly suspect, by their nature of rewriting the destination mailer).

And so, I decided to write something simple and sufficient for me and may be other people. Of course, Andrzej's rules were an excellent example of how to do it. This is how FEATURE(`ckuser_cyrus') came out. It is a very simple implementation of the idea. It doesn't (and wasn't meant to) necessarily help in every possible variant of Sendmail+Cyrus integration, but should work well in the default configuration, described in the Cyrus IMAPD documentation, which I and possibly many others use.

For configurations more complex than those using

define(`confLOCAL_MAILER',`cyrusv2')

(most notable example, I think, is supporting virtual domains in Cyrus), I recommend to look at Andrzej's method.

How to

  1. I assume you already have sendmail 8.13(or later) and Cyrus IMAPD 2.2.3(or later) installed.

    Note, that sendmail may have to be recompiled to include support for socket maps. FreeBSD users should use their ports to install a sendmail package with this feature turned on, while others may have to think of their way of doing it. In general, if you run

    sendmail -bv -d0.1 root

    and it doesn't mention `SOCKETMAP' in its compile-time options, you need to recompile it with

    APPENDDEF(`conf_sendmail_ENVDEF', `-DSOCKETMAP')
    

    included in `devtools/Site/site.config.m4'.

    As per the `install-configure' from Cyrus IMAP server's documentation, in the simplest case, you added:

        define(`confLOCAL_MAILER', `cyrusv2')dnl
        MAILER(`cyrusv2')dnl
    

    to your sendmail's .mc file to arrange for local delivery to Cyrus mailboxes.

  2. Insert the following lines to the SERVICES sections of `cyrus.conf'. I used to find it in `/usr/local/etc', but of course, it depends on your installation.

       
        # Sendmail socket map smmapd(8)
        smmap        cmd="smmapd"  listen="/var/imap/socket/smmapd" prefork=0
    

    A SIGHUP would make the Cyrus master(8) process catch this change on-the-fly.

  3. Copy the following file to the

    cf/feature

    configuration directory of sendmail. Mine is `/usr/local/share/sendmail/cf/feature', yours may be elsewhere.

    Include

    FEATURE(`ckuser_cyrus')dnl

    into the list of FEATUREs in your .mc configuration file, rebuild the `sendmail.cf', make sendmail read it, and enjoy!

    Please, also note, that if you've placed the smmapd's socket elsewhere or run sendmail and cyrus on separate machines, you will need to reflect the `listen=' setting of your `cyrus.conf' in the second argument to the FEATURE. The default

    FEATURE(`ckuser_cyrus')

    is equivalent to

    FEATURE(`ckuser_cyrus',`local:/var/imap/socket/smmapd')

    Also, consider mentioning

    FEATURE(`preserve_local_plus_detail')dnl

    if you intend to allow direct delivery to folders other than your users' `INBOX'es.

Post scriptum

Please, don't hesitate to send comments, critics, patches, etc. save spam to me. My address is

mike@tric.ru.

September 22th, 2004

Mike Boev

$Id: index.html,v 1.19 2005/03/08 18:51:31 m Exp $