[tpop3d-discuss] bulletin support

Chris Lightfoot chris at ex-parrot.com
Tue, 5 Aug 2003 18:55:07 +0100

An off-list correspondent suggested that tpop3d should
have support for `server bulletins'. Personally I think
these are an ugly hack, but it turns out that a minor
change to tpop3d will enable them to be implemented with a
small perl script. The change is an option and support to
enable tpop3d to run an onlogin handler, and wait until it
has completed before opening (and locking) the user

I attach a description of this (from CVS); comments would
be appreciated:

Implementing POP3 server bulletins using tpop3d
$Id: README.bulletins,v 1.1 2003/08/01 12:11:38 chris Exp $

At many large sites it is useful to be able to distribute a `bulletin' message
to all mail users. tpop3d can provide this functionality by having user login
trigger delivery of any outstanding bulletin messages via the onlogin
handler mechanism, as for POP-before-SMTP.

This is new and untested functionality, but the basic idea is that you specify

    onlogin-child-wait: yes

in tpop3d.conf, then write an auth-perl or auth-other onlogin action to handle
bulletin delivery. Here is a sketch of a perl subroutine that could be used
for this:

    # onlogin_bulletins_handler REQUEST
    # Deliver any bulletins which are pending for the authenticated user
    # identified in the REQUEST. This subroutine is called by tpop3d, which
    # will set REQUEST->{local_part} and REQUEST->{domain} to the proper
    # values. Bulletins should be complete RFC822 messages stored in flat
    # text files under /etc/mail/bulletins, each with the extension .msg.
    # This function will use a GDBM database for each bulletin to record the
    # addresses of users to whom it has been delivered, so as to ensure that
    # each user receives only one copy of each bulletin. Bulletins are
    # delivered to user mailboxes using the local mail transport agent, though
    # this behaviour could be changed if required.
    sub onlogin_bulletins_handler ($) {
        my $req = shift;
        my $resp = { };
        # Iterate over list of bulletins.
        foreach my $bull (glob("/etc/mail/bulletins/*.msg")) {
            my $recips = $bull;
            # Obtain and tie delivery database, creating it if it does not
            # already exist.

            $recips =~ s/msg$/db/;
            my $r = "$req->{local_part}@$req->{domain}";
            my %rr;
            tie(%rr, 'GDBM_File', $recips, &GDBM_WRCREAT, 0600);a

            # Attempt delivery if this user has not already been sent a copy
            # of this message.

            if (!exists($rr{$r})) {

                # Invoke sendmail. There are better ways of doing this, but
                # this is simplest. Note that it wouldn't usually be safe to
                # call sendmail in this way, but tpop3d has already
                # authenticated somebody using the given local-part and
                # domain, so they're presumably safe strings.

                system("sendmail -oi '$r' < $bull");
                if ($? == 0) {

                    # Sendmail exits with code 0 on success.

                    $recips{$r} = 1;
                } else {

                    # Sendmail (or system(3)) failed. There's not a whole lot
                    # we can do here, but we log a message and abort sending
                    # any other bulletins to this user for the moment.

                    return { logmsg => "sendmail failed; error code $?" };
        # Don't log anything in case of success; we might want to note how
        # many bulletins were delivered or something, of course.
        return { };

``WATCH A REAL WAR from a glass-bottomed helicopter...
  More Realistic than DVD.'' (from `TV Go Home')