2012-04-29 10:35:59 +02:00
|
|
|
#!perl -w
|
2005-03-29 22:15:53 +02:00
|
|
|
# Adaptive logging plugin - logs at one level for successful messages and
|
|
|
|
# one level for DENY'd messages
|
|
|
|
|
|
|
|
sub register {
|
2013-04-21 06:50:39 +02:00
|
|
|
my ($self, $qp, %args) = @_;
|
2005-06-22 16:42:09 +02:00
|
|
|
|
|
|
|
$self->{_minlevel} = LOGERROR;
|
2013-04-21 06:50:39 +02:00
|
|
|
if (defined($args{accept})) {
|
|
|
|
if ($args{accept} =~ /^\d+$/) {
|
2005-06-22 16:42:09 +02:00
|
|
|
$self->{_minlevel} = $args{accept};
|
|
|
|
}
|
|
|
|
else {
|
2013-04-21 06:50:39 +02:00
|
|
|
$self->{_minlevel} = log_level($args{accept});
|
2005-06-22 16:42:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$self->{_maxlevel} = LOGWARN;
|
2013-04-21 06:50:39 +02:00
|
|
|
if (defined($args{reject})) {
|
|
|
|
if ($args{reject} =~ /^\d+$/) {
|
2005-06-22 16:42:09 +02:00
|
|
|
$self->{_maxlevel} = $args{reject};
|
|
|
|
}
|
|
|
|
else {
|
2013-04-21 06:50:39 +02:00
|
|
|
$self->{_maxlevel} = log_level($args{reject});
|
2005-06-22 16:42:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$self->{_prefix} = '`';
|
2013-04-21 06:50:39 +02:00
|
|
|
if (defined $args{prefix} and $args{prefix} =~ /^(.+)$/) {
|
2005-06-22 16:42:09 +02:00
|
|
|
$self->{_prefix} = $1;
|
|
|
|
}
|
|
|
|
|
|
|
|
# If you want to capture this log entry with this plugin, you need to
|
|
|
|
# wait until after you register the plugin
|
2013-04-21 06:50:39 +02:00
|
|
|
$self->log(LOGINFO, 'Initializing logging::adaptive plugin');
|
2005-03-29 22:15:53 +02:00
|
|
|
}
|
|
|
|
|
2013-04-21 06:50:39 +02:00
|
|
|
sub hook_logging { # wlog
|
|
|
|
my ($self, $transaction, $trace, $hook, $plugin, @log) = @_;
|
2005-06-22 16:42:09 +02:00
|
|
|
|
|
|
|
# Don't log your own log entries! If this is the only logging plugin
|
|
|
|
# then these lines will not be logged at all. You can safely comment
|
|
|
|
# out this line and it will not cause an infinite loop.
|
|
|
|
return DECLINED if defined $plugin and $plugin eq $self->plugin_name;
|
|
|
|
|
2013-04-21 06:50:39 +02:00
|
|
|
if (defined $self->{_maxlevel} && $trace <= $self->{_maxlevel}) {
|
2005-06-22 16:42:09 +02:00
|
|
|
warn join(
|
2013-04-21 06:50:39 +02:00
|
|
|
" ",
|
|
|
|
$$
|
|
|
|
. (
|
|
|
|
defined $plugin ? " $plugin plugin:"
|
|
|
|
: defined $hook ? " running plugin ($hook):"
|
|
|
|
: ""
|
|
|
|
),
|
|
|
|
@log
|
|
|
|
),
|
2005-06-22 16:42:09 +02:00
|
|
|
"\n"
|
|
|
|
unless $log[0] =~ /logging::adaptive/;
|
2013-04-21 06:50:39 +02:00
|
|
|
push @{$transaction->{_log}}, [$trace, $hook, $plugin, @log]
|
|
|
|
if (defined $self->{_minlevel} && $trace <= $self->{_minlevel});
|
2005-06-22 16:42:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return DECLINED;
|
2005-03-29 22:15:53 +02:00
|
|
|
}
|
|
|
|
|
2013-04-21 06:50:39 +02:00
|
|
|
sub hook_deny { # dlog
|
|
|
|
my ($self, $transaction, $prev_hook, $return, $return_text) = @_;
|
2005-06-22 16:42:09 +02:00
|
|
|
$self->{_denied} = 1;
|
2005-03-29 22:15:53 +02:00
|
|
|
}
|
|
|
|
|
2013-04-21 06:50:39 +02:00
|
|
|
sub hook_reset_transaction { # slog
|
2005-06-22 16:42:09 +02:00
|
|
|
|
|
|
|
# fires when a message is accepted
|
2013-04-21 06:50:39 +02:00
|
|
|
my ($self, $transaction, @args) = @_;
|
2005-06-22 16:42:09 +02:00
|
|
|
|
|
|
|
return DECLINED if $self->{_denied};
|
|
|
|
|
2013-04-21 06:50:39 +02:00
|
|
|
foreach my $row (@{$transaction->{_log}}) {
|
2005-06-22 16:42:09 +02:00
|
|
|
next unless scalar @$row; # skip over empty log lines
|
2013-04-21 06:50:39 +02:00
|
|
|
my ($trace, $hook, $plugin, @log) = @$row;
|
2005-06-22 16:42:09 +02:00
|
|
|
warn join(
|
2013-04-21 06:50:39 +02:00
|
|
|
" ", $$,
|
|
|
|
$self->{_prefix}
|
|
|
|
. (
|
|
|
|
defined $plugin ? " $plugin plugin:"
|
|
|
|
: defined $hook ? " running plugin ($hook):"
|
|
|
|
: ""
|
|
|
|
),
|
|
|
|
@log
|
|
|
|
),
|
2005-06-22 16:42:09 +02:00
|
|
|
"\n"
|
2013-04-21 06:50:39 +02:00
|
|
|
if ($trace <= $self->{_minlevel});
|
2005-06-22 16:42:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return DECLINED;
|
2005-03-29 22:15:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
|
|
|
adaptive - An adaptive logging plugin for qpsmtpd
|
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
|
|
|
|
A qpsmtpd plugin for logging at different levels depending on success or
|
|
|
|
failure of any given message.
|
|
|
|
|
|
|
|
=head1 INSTALL AND CONFIG
|
|
|
|
|
|
|
|
Place this plugin in the plugin/logging directory beneath the standard
|
|
|
|
qpsmtpd installation. Edit the config/logging file and add a line like
|
|
|
|
this:
|
|
|
|
|
|
|
|
logging/adaptive [accept minlevel] [reject maxlevel] [prefix char]
|
|
|
|
|
|
|
|
where the optional parameters are:
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item B<accept>
|
|
|
|
|
|
|
|
This is the level at which messages which are accepted will be logged. You
|
|
|
|
can use either the loglevel number (as shown in config.sample/loglevels) or
|
|
|
|
you can use the text form (from the same file). Typically, you would set
|
|
|
|
this to LOGERROR (4) so that the FROM and TO lines would be logged (with the
|
|
|
|
default installation). If absent, it will be set to LOGERROR (4).
|
|
|
|
|
|
|
|
=item B<reject>
|
|
|
|
|
|
|
|
This is the level which messages which are rejected for any reason will be
|
|
|
|
logged. This would typically be set as high as reasonable, to document why a
|
|
|
|
message may have been rejected. If absent, it defaults to LOGWARN (5), which
|
|
|
|
is probably not high enough for most sites.
|
|
|
|
|
|
|
|
=item B<prefix>
|
|
|
|
|
|
|
|
In order to visually distinguish the accepted from rejected lines, all
|
2005-06-22 16:42:09 +02:00
|
|
|
log lines from a accepted message will be prefixed with the character
|
2005-03-29 22:15:53 +02:00
|
|
|
listed here (directly after the PID). You can use anything you want as
|
|
|
|
a prefix, but it is recommended that it be short (preferably just a single
|
|
|
|
character) to minimize the amount of bloat in the log file. If absent, the
|
2005-06-22 16:42:09 +02:00
|
|
|
prefix defaults to the left single quote (`).
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
=head1 TYPICAL USAGE
|
|
|
|
|
|
|
|
If you are using multilog to handle your logging, you can replace the system
|
|
|
|
provided log/run file with something like this:
|
|
|
|
|
|
|
|
#! /bin/sh
|
|
|
|
export LOGDIR=./main
|
|
|
|
mkdir -p $LOGDIR/failed
|
|
|
|
exec multilog t n10 \
|
|
|
|
'-*` *' $LOGDIR/detailed \
|
|
|
|
'-*' '+*` *' $LOGDIR/accepted
|
|
|
|
|
|
|
|
which will have the following effects:
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item 1. All lines will be logged into the ./mail/detailed folder
|
|
|
|
|
|
|
|
=item 2. Log lines for messages that are accepted will go to ./main/accepted
|
2005-03-29 22:15:53 +02:00
|
|
|
|
|
|
|
=back
|
|
|
|
|
2005-06-22 16:42:09 +02:00
|
|
|
You may want to use the s####### option to multilog to ensure that the log
|
|
|
|
files are large enough to maintain a proper amount of history. Depending on
|
|
|
|
your site load, it is useful to have at least a week and preferrably three
|
|
|
|
weeks of accepted messages. You can also use the n## option to have more
|
|
|
|
log history files maintained.
|
|
|
|
|
2005-03-29 22:15:53 +02:00
|
|
|
=head1 AUTHOR
|
|
|
|
|
|
|
|
John Peacock <jpeacock@cpan.org>
|
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE
|
|
|
|
|
|
|
|
Copyright (c) 2005 John Peacock
|
|
|
|
|
|
|
|
This plugin is licensed under the same terms as the qpsmtpd package itself.
|
|
|
|
Please see the LICENSE file included with qpsmtpd for details.
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|