94 lines
2.8 KiB
Plaintext
94 lines
2.8 KiB
Plaintext
|
#
|
||
|
# 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->qp->connection->notes('count_relay_attempts') || 0) + 1;
|
||
|
$self->qp->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
|