http://www.perlmonks.org?node_id=730756


in reply to Simple (but robust) email server (receiver)

qpsmtpd is a Perl SMTP server, which is very extensible and based upon plugins.

It would be trivial to set it up to receive mails and process them.

I do use it on my commercial spam filtering site, and it is a real pleasure to work with.

THere is a simple introduction here, and move via the homepage and your favourite search engine.

Steve
--
  • Comment on Re: Simple (but robust) email server (receiver)

Replies are listed 'Best First'.
Re^2: Simple (but robust) email server (receiver)
by zby (Vicar) on Dec 17, 2008 at 13:20 UTC
    Thanks - it looks interesting. One question about the plugins - how do you maintain a database connection persistent for a worker process? The docs only say:
    There is no restriction, what you can do in “register()”, but creating database connections and reuse them later in the process may not be a good idea. This initialisation happens before any “fork()” is done. Therefore the file handle will be shared by all qpsmtpd processes and the database will probably be confused if several different queries arrive on the same file handle at the same time (and you may get the wrong answer, if any).
    So is there a way to initialize the connection just after the fork - and before any request is served?

      I don't maintain a database handle throughout the transaction - instead I use the connection object to make notes as the SMTP transaction is completed.

      e.g.

      sub hook_helo { my ( $self, $transaction, $host ) = @_; # # Make sure helo includes a domain # if ( $host !~ /\./ ) { $self->log( LOGWARN, "HELO $host doesn't contain a period." ); $transaction->notes( "reject", 1 ); $transaction->notes( "reason", "invalid helo" ); } return DECLINED; }

      Then I have a series of plugins which do different things at the last step, either forward the message or reject it, but archive a searchable copy for the recipients benefit. Here's a simplified version of the reject + archive plugin:

      sub hook_queue { my ( $self, $transaction ) = @_; # # We only log mails which have been rejected. # if ( 0 == ( $transaction->notes("reject") || 0 ) ) { return DECLINED; } # connect to DB # archive message # disconnect return ( DECLINED, "Rejected this is spam: " . $transaction-Notes +("reason" ) ); }

      (Actually this is a polite fiction. I actually archive messages to local disk, if they were to be rejected, then later rsync them to a central location - and import them to MySQL there.

      Steve
      --