# # This file is best read with ``perldoc advanced.pod'' # ### # Conventions: # plugin names: F<myplugin>, F<qpsmtpd-async> # constants: I<LOGDEBUG> # smtp commands, answers: B<HELO>, B<250 Queued!> # # Notes: # * due to restrictions of some POD parsers, no C<<$object->method()>> # are allowed, use C<$object-E<gt>method()> # =head1 Advanced Playground =head2 Discarding messages If you want to make the client think a message has been regularily accepted, but in real you delete it or send it to F</dev/null>, ..., use something like the following plugin and load it before your default queue plugin. sub hook_queue { my ($self, $transaction) = @_; if ($transaction->notes('discard_mail')) { my $msg_id = $transaction->header->get('Message-Id') || ''; $msg_id =~ s/[\r\n].*//s; return(OK, "Queued! $msg_id"); } return(DECLINED); } =head2 Changing return values This is an example how to use the C<isa_plugin> method. The B<rcpt_ok_maxrelay> plugin wraps the B<rcpt_ok> plugin. The B<rcpt_ok> plugin checks the F<rcpthosts> and F<morercpthosts> config files for domains, which we accept mail for. If not found it tells the client that relaying is not allowed. Clients which are marked as C<relay clients> are excluded from this rule. This plugin counts the number of unsuccessfull relaying attempts and drops the connection if too many were made. The optional parameter I<MAX_RELAY_ATTEMPTS> configures this plugin to drop the connection after I<MAX_RELAY_ATTEMPTS> unsuccessful relaying attempts. Set to C<0> to disable, default is C<5>. Note: Do not load both (B<rcpt_ok> and B<rcpt_ok_maxrelay>). This plugin should be configured to run I<last>, like B<rcpt_ok>. use Qpsmtpd::DSN; sub init { my ($self, $qp, @args) = @_; die "too many arguments" if @args > 1; $self->{_count_relay_max} = defined $args[0] ? $args[0] : 5; $self->isa_plugin("rcpt_ok"); } sub hook_rcpt { my ($self, $transaction, $recipient) = @_; my ($rc, @msg) = $self->SUPER::hook_rcpt($transaction, $recipient); return ($rc, @msg) unless (($rc == DENY) and $self->{_count_relay_max}); my $count = ($self->connection->notes('count_relay_attempts') || 0) + 1; $self->connection->notes('count_relay_attempts', $count); return ($rc, @msg) unless ($count > $self->{_count_relay_max}); return Qpsmtpd::DSN->relaying_denied(DENY_DISCONNECT, "Too many relaying attempts"); } =head2 Results of other hooks B<NOTE:> just copied from README.plugins If we're in a transaction, the results of a callback are stored in $self->transaction->notes( $code->{name})->{"hook_$hook"}->{return} If we're in a connection, store things in the connection notes instead. B<FIXME>: does the above (regarding connection notes) work? =cut # vim: ts=2 sw=2 expandtab