smeserver-qpsmtpd/root/usr/share/qpsmtpd/plugins/logging/logterse

173 lines
4.6 KiB
Plaintext

=pod
=head1 SYNOPSIS
logterse [prefix char] [loglevel level]
This plugin is not a logging replacement, but rather an adjunct to the normal logging
plugins or builtin logging functionality. Specify it in config/plugins not
config/logging or you'll get "interesting" results.
The idea is to produce a one-line log entry that summarises the outcome of a
transaction. A message is either queued or rejected (bizarre failure modes are
not of interest). What is of interest is the details of the sending host and the
message envelope, and what happened to the message. To do this we hook_deny and
hook_queue and grab as much info as we can.
This info is then passed to the real logging subsystem as a single line with
colon-separated fields as follows:
=over 4
=item 1. remote ip
=item 2. remote hostname
=item 3. helo host
=item 4. envelope sender
=item 5. recipient (comma-separated list if more than one)
=item 6. name of plugin that called DENY, or the string 'queued' if message was accepted.
=item 7. return value of DENY plugin (empty if message was queued).
=item 8. the DENY message, or the message-id if it was queued.
=item 9. details of spammassassin scores if messaged was accepted or denied due to score requiring rejection
or 'msg denied before queued' if other rejections occur.
=back
As with logging/adaptive, a distinctive prefix (the backquote character by default) is
used to make it easy to extract the lines from the main logfiles, or to take advantage
of multilog's selection capability as described in the logging/adaptive plugin:
=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
exec multilog t n10 \
$LOGDIR \
'-*' '+*` *' $LOGDIR/summary
which will have the following effects:
=over 4
=item 1. All lines will be logged in ./main as usual.
=item 2. ./main/summary will contain only the lines output by this plugin.
=back
=head1 AUTHORS
Written by Charles Butcher who took a lot from logging/adaptive by John Peacock.
Added to by Brian Read (March 2007) to add in the spamassassin scores.
=head1 VERSION
This is release 1.1
=cut
#
# I chose tab as the field separator to help with human-readability of the logs and hopefully minimal
# chance of a tab showing up _inside_ a field (although they are converted if they do).
# If you change it here, remember to change it in qplogsumm.pl as well.
#
my $FS = "\t";
#my $FS = "\&";
sub register {
my ( $self, $qp, %args ) = @_;
$self->{_prefix} = '`';
if ( defined $args{prefix} and $args{prefix} =~ /^(.+)$/ ) {
$self->{_prefix} = $1;
}
$self->{_loglevel} = LOGALERT;
if ( defined( $args{loglevel} ) ) {
if ( $args{loglevel} =~ /^\d+$/ ) {
$self->{_loglevel} = $args{loglevel};
}
else {
$self->{_loglevel} = log_level( $args{loglevel} );
}
}
}
sub hook_deny {
my ( $self, $transaction, $prev_hook, $retval, $return_text ) = @_;
my $disposition = join($FS,
$prev_hook,
$retval,
$return_text,
);
$self->_log_terse($transaction, $disposition);
return DECLINED;
}
sub hook_queue {
my ( $self, $transaction ) = @_;
my $msg_id = $transaction->header->get('Message-Id') || '';
$msg_id =~ s/[\r\n].*//s; # don't allow newlines in the Message-Id here
$msg_id = "<$msg_id>" unless $msg_id =~ /^<.*>$/; # surround in <>'s
my $disposition = "queued$FS$FS$msg_id";
$self->_log_terse($transaction, $disposition);
return DECLINED;
}
sub _log_terse {
my ( $self, $transaction, $disposition ) = @_;
my $recipients = join(',', $transaction->recipients);
my $remote_ip = $self->qp->connection->remote_ip() || '';
my $remote_host = $self->qp->connection->remote_host() || '';
my $hello_host = $self->qp->connection->hello_host() || '';
my $tx_sender = $transaction->sender() || '';
my $spamscore = 'msg denied before queued';
if (substr($disposition,0,6) =~ 'queued|spamas') {
$spamscore = $transaction->header->get('X-Spam-Status') || '';
# just pull out scores
$spamscore = substr($spamscore,0,index($spamscore,'tests')-1);
map(s/\n/_/g,$spamscore)
}
my @log_message;
push(@log_message,
$remote_ip,
$remote_host,
$hello_host,
$tx_sender,
$recipients
);
#
# Escape any $FS characters anywhere in the log message
#
map {s/$FS/_/g} @log_message;
push(@log_message, $disposition);
push(@log_message, $spamscore);
$self->log($self->{_loglevel}, $self->{_prefix}, join($FS, @log_message));
}