plugins.pod update
* hook_help * isa_plugin() example * some white space at EOL removed git-svn-id: https://svn.perl.org/qpsmtpd/trunk@829 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
parent
ce9e0cb740
commit
ce195bc5c2
109
docs/plugins.pod
109
docs/plugins.pod
@ -156,6 +156,9 @@ C<init()> subroutine.
|
|||||||
$self->SUPER::hook_rcpt($transaction, $recipient);
|
$self->SUPER::hook_rcpt($transaction, $recipient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
See also chapter C<Changing return values> and
|
||||||
|
F<contrib/vetinari/rcpt_ok_maxrelay> in SVN.
|
||||||
|
|
||||||
=head2 Config files
|
=head2 Config files
|
||||||
|
|
||||||
Most of the existing plugins fetch their configuration data from files in the
|
Most of the existing plugins fetch their configuration data from files in the
|
||||||
@ -1092,6 +1095,32 @@ is called. It's probably best not to try acessing it.
|
|||||||
|
|
||||||
Example plugin is F<tls>.
|
Example plugin is F<tls>.
|
||||||
|
|
||||||
|
=head2 hook_help
|
||||||
|
|
||||||
|
This hook triggers if a client sends the B<HELP> command, allowed return
|
||||||
|
codes are:
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item DONE
|
||||||
|
|
||||||
|
Plugin gave the answer.
|
||||||
|
|
||||||
|
=item DENY
|
||||||
|
|
||||||
|
Will result in a syntax error, probably not what you want, better use
|
||||||
|
$self->qp->respond(502, "Not implemented.");
|
||||||
|
return DONE;
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
Anything else will be send as help answer.
|
||||||
|
|
||||||
|
Arguments are
|
||||||
|
my ($self, $transaction, @args) = @_;
|
||||||
|
|
||||||
|
with C<@args> being the arguments from the client's command.
|
||||||
|
|
||||||
=head2 hook_vrfy
|
=head2 hook_vrfy
|
||||||
|
|
||||||
If the client sents the B<VRFY> command, this hook is called. Default is to
|
If the client sents the B<VRFY> command, this hook is called. Default is to
|
||||||
@ -1167,7 +1196,7 @@ B<FIXME>
|
|||||||
|
|
||||||
=pod
|
=pod
|
||||||
|
|
||||||
...documentation will follow later
|
See F<README.authentication> in the qpsmtpd base dir.
|
||||||
|
|
||||||
=head1 Writing your own plugins
|
=head1 Writing your own plugins
|
||||||
|
|
||||||
@ -1230,7 +1259,7 @@ The first step is to open a connection to the remote server.
|
|||||||
Proto => 'tcp')
|
Proto => 'tcp')
|
||||||
or $self->log(LOGERROR, "Failed to connect to "
|
or $self->log(LOGERROR, "Failed to connect to "
|
||||||
."$self->{_qmqp_server}:"
|
."$self->{_qmqp_server}:"
|
||||||
."$self->{_qmqp_port}: $!"),
|
."$self->{_qmqp_port}: $!"),
|
||||||
return(DECLINED);
|
return(DECLINED);
|
||||||
$sock->autoflush(1);
|
$sock->autoflush(1);
|
||||||
|
|
||||||
@ -1238,21 +1267,21 @@ The first step is to open a connection to the remote server.
|
|||||||
|
|
||||||
=item *
|
=item *
|
||||||
|
|
||||||
The client starts with a safe 8-bit text message. It encodes the message
|
The client starts with a safe 8-bit text message. It encodes the message
|
||||||
as the byte string C<firstline\012secondline\012 ... \012lastline>. (The
|
as the byte string C<firstline\012secondline\012 ... \012lastline>. (The
|
||||||
last line is usually, but not necessarily, empty.) The client then encodes
|
last line is usually, but not necessarily, empty.) The client then encodes
|
||||||
this byte string as a netstring. The client also encodes the envelope
|
this byte string as a netstring. The client also encodes the envelope
|
||||||
sender address as a netstring, and encodes each envelope recipient address
|
sender address as a netstring, and encodes each envelope recipient address
|
||||||
as a netstring.
|
as a netstring.
|
||||||
|
|
||||||
The client concatenates all these netstrings, encodes the concatenation
|
The client concatenates all these netstrings, encodes the concatenation
|
||||||
as a netstring, and sends the result.
|
as a netstring, and sends the result.
|
||||||
|
|
||||||
(from L<http://cr.yp.to/proto/qmqp.html>)
|
(from L<http://cr.yp.to/proto/qmqp.html>)
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
The first idea is to build the package we send, in the order described
|
The first idea is to build the package we send, in the order described
|
||||||
in the paragraph above:
|
in the paragraph above:
|
||||||
|
|
||||||
my $message = $transaction->header->as_string;
|
my $message = $transaction->header->as_string;
|
||||||
@ -1267,7 +1296,7 @@ in the paragraph above:
|
|||||||
}
|
}
|
||||||
$message .= join "", netstring_encode(@rcpt);
|
$message .= join "", netstring_encode(@rcpt);
|
||||||
print $sock netstring_encode($message)
|
print $sock netstring_encode($message)
|
||||||
or do {
|
or do {
|
||||||
my $err = $!;
|
my $err = $!;
|
||||||
$self->_disconnect($sock);
|
$self->_disconnect($sock);
|
||||||
return(DECLINED, "Failed to print to socket: $err");
|
return(DECLINED, "Failed to print to socket: $err");
|
||||||
@ -1298,7 +1327,7 @@ message is.
|
|||||||
We've got everything we need. Now build the netstrings for the full package
|
We've got everything we need. Now build the netstrings for the full package
|
||||||
and the message.
|
and the message.
|
||||||
|
|
||||||
First the beginning of the netstring of the full package
|
First the beginning of the netstring of the full package
|
||||||
|
|
||||||
# (+ 2: the ":" and "," of the message's netstring)
|
# (+ 2: the ":" and "," of the message's netstring)
|
||||||
print $sock ($msglen + length($msglen) + 2 + length($addrs))
|
print $sock ($msglen + length($msglen) + 2 + length($addrs))
|
||||||
@ -1373,23 +1402,23 @@ Message is at the server, now finish the package.
|
|||||||
We're done. Now let's see what the remote qmqpd says...
|
We're done. Now let's see what the remote qmqpd says...
|
||||||
|
|
||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
=item *
|
=item *
|
||||||
|
|
||||||
(continued from L<http://cr.yp.to/proto/qmqp.html>:)
|
(continued from L<http://cr.yp.to/proto/qmqp.html>:)
|
||||||
|
|
||||||
The server's response is a nonempty string of 8-bit bytes, encoded as a
|
The server's response is a nonempty string of 8-bit bytes, encoded as a
|
||||||
netstring.
|
netstring.
|
||||||
|
|
||||||
The first byte of the string is either K, Z, or D. K means that the
|
The first byte of the string is either K, Z, or D. K means that the
|
||||||
message has been accepted for delivery to all envelope recipients. This
|
message has been accepted for delivery to all envelope recipients. This
|
||||||
is morally equivalent to the 250 response to DATA in SMTP; it is subject
|
is morally equivalent to the 250 response to DATA in SMTP; it is subject
|
||||||
to the reliability requirements of RFC 1123, section 5.3.3. Z means
|
to the reliability requirements of RFC 1123, section 5.3.3. Z means
|
||||||
temporary failure; the client should try again later. D means permanent
|
temporary failure; the client should try again later. D means permanent
|
||||||
failure.
|
failure.
|
||||||
|
|
||||||
Note that there is only one response for the entire message; the server
|
Note that there is only one response for the entire message; the server
|
||||||
cannot accept some recipients while rejecting others.
|
cannot accept some recipients while rejecting others.
|
||||||
|
|
||||||
=back
|
=back
|
||||||
@ -1440,6 +1469,52 @@ like the following plugin and load it before your default queue plugin.
|
|||||||
return(DECLINED);
|
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 TBC... :-)
|
=head2 TBC... :-)
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
Loading…
Reference in New Issue
Block a user