| version 1.2, 2004/10/21 18:28:55 |
version 1.3, 2004/10/29 23:02:30 |
|
|
| # 2004-10-19 - created |
# 2004-10-19 - created |
| # |
# |
| |
|
| # $Platon: perl-modules/Platon/Log/Mail/Postfix.pm,v 1.1 2004/10/21 17:37:49 rajo Exp $ |
# $Platon: perl-modules/Platon/Log/Mail/Postfix.pm,v 1.2 2004/10/21 18:28:55 rajo Exp $ |
| |
|
| package Platon::Log::Mail::Postfix; |
package Platon::Log::Mail::Postfix; |
| |
|
| Line 21 use base qw( Platon::Log::Mail ); |
|
| Line 21 use base qw( Platon::Log::Mail ); |
|
| use Carp; |
use Carp; |
| use Platon::Log::Mail; |
use Platon::Log::Mail; |
| use Platon::DBI; |
use Platon::DBI; |
| |
use Date::Parse; |
| |
use Date::Format; |
| |
|
| $VERSION = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/); |
$VERSION = sprintf("%d.%02d", q$Revision$ =~ /(\d+)\.(\d+)/); |
| $DEBUG = 0 unless defined $DEBUG; |
$DEBUG = 0 unless defined $DEBUG; |
|
|
| { # {{{ |
{ # {{{ |
| my ($self, $line) = @_; |
my ($self, $line) = @_; |
| my $xx = { }; |
my $xx = { }; |
| |
my $length = 24; |
| |
|
| if (( $xx->{created}, $xx->{host}, $xx->{log_level}, |
if ($line !~ m/^20/o) { |
| $xx->{process_name}, $xx->{pid}, $xx->{postfix_key}, $xx->{rest}) |
$length = 15; |
| = ($line =~ m/^(20[^ ]+) (\S+) \[(\S+)\] postfix\/(\S+)\[(\d+)\]: (\S+) (.*)$/o)) { |
} |
| |
my $time = str2time(substr($line, 0, $length)); |
| |
$xx->{created} = time2str('%Y-%m-%dT%X%z', $time); |
| |
#print 'input = "' , substr($line, 0, $length) , '" output = "' , $xx->{created}, "\"\n"; |
| |
$line = substr($line, $length); |
| |
|
| |
#return 1; |
| |
return 0 unless defined($xx->{created}); |
| |
|
| |
# first separate hostname |
| |
($xx->{host}, $line) = ($line =~ m/^\s+(\S+)\s+(.*)$/o); |
| |
|
| |
if ($line =~ m/^\[/) { # log level |
| |
($xx->{log_level}, $line) = ($line =~ m/^\[(\S+)\] (.*)$/o); |
| |
} |
| |
|
| |
($xx->{process_name}, $line) = ($line =~ m/^postfix\/([^[\s]+)(.*)$/o); |
| |
if ($line =~ s/^\[(\d+)\]: (.*)$/$2/o) { |
| |
$xx->{pid} = $1; |
| |
} |
| |
else { |
| |
$xx->{pid} = 0; |
| |
} |
| |
|
| |
if (( $xx->{postfix_key}, $xx->{rest}) |
| |
= ($line =~ m/\s*(\S+) (.*)$/o)) { |
| |
|
| $xx->{postfix_key} =~ s/:$//g; |
$xx->{postfix_key} =~ s/:$//g; |
| # postfix_key: connect disconnect warning fatal lost timeout refreshing terminating lost |
|
| if ($xx->{postfix_key} eq 'connect' or $xx->{postfix_key} eq 'disconnect') { |
# postfix_key: connect disconnect warning fatal lost timeout refreshing terminating lost reload |
| if ($xx->{rest} =~ s#from\s+(\S+)\[([\.0-9]+)\]$##o) { |
# process_name: postfix-script smtpd smtp cleanup qmgr pickup local master |
| ($xx->{client_hostname}, $xx->{client_ip}) = ($1, $2); |
|
| return $self->_savelog($xx); |
if ($xx->{process_name} eq 'smtpd') { # {{{ |
| |
if ($xx->{postfix_key} eq 'NOQUEUE') { |
| |
my ($status, $addr, $rest, $info); |
| |
($status, $addr, $rest, $info) = ($xx->{rest} =~ m/(\S+): ([^:]+): (.+); ([^;]*)$/o); |
| |
$xx->{rest} = $rest; |
| |
($xx->{client_hostname}, $xx->{client_ip}) = ($addr =~ m/(\S+)\[([\.0-9]+)\]$/o); |
| |
# $info = 'from=<> to=<webmaster@foobar.sk> proto=ESMTP helo=<rage.xyzt.net>' |
| |
_parse_by_equal($info, $xx); |
| |
$xx->{from} =~ s/[\<>]//go; |
| |
$xx->{to} =~ s/[\<>]//go; |
| |
$xx->{helo} =~ s/[\<>]//go; |
| |
} |
| |
elsif ($xx->{postfix_key} eq 'connect' |
| |
or $xx->{postfix_key} eq 'disconnect' |
| |
or $xx->{postfix_key} eq 'lost') { |
| |
($xx->{client_hostname}, $xx->{client_ip}) = ($xx->{rest} =~ m/(\S+)\[([\.0-9]+)\]$/o); |
| |
} |
| |
elsif ($xx->{rest} =~ m/^smtpd_peer_init:/o) { |
| |
($xx->{client_ip}, $xx->{client_hostname}) = ($xx->{rest} =~ m/smtpd_peer_init: (\S+): hostname (\S+)/o); |
| } |
} |
| else { |
else { |
| return $self->_savelog($xx); |
($xx->{client_hostname}, $xx->{client_ip}) = ($xx->{rest} =~ m/from (\S+)\[([\.0-9]+)\]/o); |
| |
if (!defined($xx->{client_hostname})) { |
| |
($xx->{client_hostname}, $xx->{client_ip}) = ($xx->{rest} =~ m/client=(\S+)\[([\.0-9]+)\]$/o); |
| |
} |
| } |
} |
| } |
|
| elsif ($xx->{postfix_key} !~ /^[0-9A-F]+$/) { # warning or error? |
|
| |
|
| return $self->_savelog($xx); |
return $self->_savelog($xx); |
| } |
|
| |
|
| # |
} # }}} |
| # else this is postfix key, parse rest of the line |
elsif ($xx->{process_name} eq 'local') { # {{{ |
| # |
# postfix/local[18616]: 1BB0F140064D: to=<spam@foobar.sk>, relay=local, delay=19, status=sent (delivered to command: procmail -a \"$EXTENSION\") |
| |
# postfix/local[17562]: 5FAD4140064D: to=<spam@foobar.sk>, orig_to=<webmaster@foobar.sk>, relay=local, delay=25, status=sent (delivered to command: procmail -a "$EXTENSION") |
| |
|
| |
my ($info); |
| |
($info, $xx->{rest}) = ($xx->{rest} =~ m/^([^(]+)\s*(\(.*\))$/o); |
| |
_parse_by_equal($info, $xx); |
| |
$xx->{to} =~ s/[\<>]//go; |
| |
$xx->{orig_to} =~ s/[\<>]//go; |
| |
|
| # process_name: postfix-script smtpd smtp cleanup qmgr pickup local master |
return $self->_savelog($xx); |
| if ($xx->{process_name} eq 'smtpd') { |
} # }}} |
| if (($xx->{client_hostname}, $xx->{client_ip}) = ($xx->{rest} =~ s#(\S+)\[([\.0-9]+)\]$##o)) { |
elsif ($xx->{process_name} eq 'smtp') { # {{{ |
| |
# postfix/smtp[16172]: connect to buling.com[216.168.41.237]: Connection timed out (port 25) |
| |
# postfix/smtp[16172]: 6D49F140B966: to=<webmaster@barfoo.com>, relay=none, delay=107781, status=deferred (connect to buling.com[216.168.41.237]: Connection timed out) |
| |
if ($xx->{postfix_key} eq 'connect') { |
| |
# TODO: incoming and and outgoing connections goes mixed here! seee 'to ' keyword on next line |
| |
($xx->{client_hostname}, $xx->{client_ip}) = ($xx->{rest} =~ m/to (\S+)\[([\.0-9]+)\]/o); |
| } |
} |
| else { |
else { |
| |
|
| |
my ($info); |
| |
if ($xx->{rest} =~ m/^([^(]+)\s*(\(.*\))$/o) { |
| |
($info, $xx->{rest}) = ($1, $2); |
| |
} |
| |
_parse_by_equal($info, $xx); |
| |
$xx->{from} =~ s/[\<>]//go; |
| |
$xx->{to} =~ s/[\<>]//go; |
| } |
} |
| } |
|
| elsif ($xx->{process_name} eq '') { |
return $self->_savelog($xx); |
| } |
} # }}} |
| elsif ($xx->{process_name} eq '') { |
elsif ($xx->{process_name} eq 'qmgr') { # {{{ |
| } |
# postfix/qmgr[17831]: 8FF9B140064D: from=<spam@foofoo.sk>, size=2906, nrcpt=1 (queue active) |
| elsif ($xx->{process_name} eq '') { |
# postfix/qmgr[17831]: 8BCF9140064D: removed |
| |
|
| |
my ($info); |
| |
if ($xx->{rest} =~ m/^([^(]+)\s*(\(.*\))$/o) { |
| |
($info, $xx->{rest}) = ($1, $2); |
| |
} |
| |
_parse_by_equal($info, $xx); |
| |
$xx->{from} =~ s/[\<>]//go; |
| |
|
| |
return $self->_savelog($xx); |
| |
} # }}} |
| |
elsif ($xx->{process_name} eq 'cleanup') { # {{{ |
| |
# postfix/cleanup[17494]: E21B8140064D: message-id=<Pine.GSO.4.10.10410121000130.14667-100000@barbar> |
| |
# postfix/cleanup[7123]: 8ED061400304: resent-message-id=<E1CIQ4i-0001Rh-24@foo.bar.sk> |
| |
|
| |
_parse_by_equal($xx->{rest}, $xx); |
| |
$xx->{"message-id"} =~ s/[\<>]//go; |
| |
$xx->{"resent-message-id"} =~ s/[\<>]//go; |
| |
undef $xx->{rest}; |
| |
|
| |
return $self->_savelog($xx); |
| |
} # }}} |
| |
elsif ($xx->{process_name} eq 'pickup') { # {{{ |
| |
_parse_by_equal($xx->{rest}, $xx); |
| |
$xx->{from} =~ s/[\<>]//go; |
| |
$xx->{client_hostname} = 'localhost'; |
| |
$xx->{client_ip} = '127.0.0.1'; |
| |
undef $xx->{rest}; |
| |
|
| |
return $self->_savelog($xx); |
| |
} # }}} |
| |
elsif ($xx->{postfix_key} !~ /^[0-9A-F]+$/o) { # warning, error, or fatal? |
| |
# search for IP address/hostname |
| |
($xx->{client_hostname}, $xx->{client_ip}) = ($xx->{rest} =~ m/from (\S+)\[([\.0-9]+)\]/o); |
| |
|
| |
return $self->_savelog($xx); |
| } |
} |
| |
|
| } |
} |
| Line 82 sub _savelog($$;) |
|
| Line 182 sub _savelog($$;) |
|
| my ($self, $data) = @_; |
my ($self, $data) = @_; |
| |
|
| $self->{sql_insert}->execute( |
$self->{sql_insert}->execute( |
| $data->{created}, $data->{hostname}, $data->{log_level}, $data->{process_name}, |
$data->{created}, $data->{host}, $data->{log_level}, $data->{process_name}, |
| $data->{pid}, $data->{postfix_key}, $data->{client_hostname}, $data->{client_ip}, |
$data->{pid}, $data->{postfix_key}, $data->{client_hostname}, $data->{client_ip}, $data->{uid}, |
| $data->{message_id}, $data->{resent_message_id}, $data->{mail_from}, $data->{mail_to}, |
$data->{"message-id"}, $data->{"resent-message-id"}, $data->{from}, $data->{to}, |
| $data->{mail_size}, $data->{mail_nrcpt}, $data->{relay}, $data->{delay}, |
$data->{size}, $data->{nrcpt}, $data->{relay}, $data->{delay}, |
| $data->{status}, $data->{proto}, $data->{helo}, $data->{rest} |
$data->{status}, $data->{proto}, $data->{helo}, $data->{rest} |
| ) or warn $self->{sql_insert}->errstr; |
) or warn $self->{sql_insert}->errstr; |
| |
|
|
|
| { # {{{ |
{ # {{{ |
| my ($self, $conf) = @_; |
my ($self, $conf) = @_; |
| |
|
| |
$self->prepare_keyword('sql_delete', "DELETE FROM " . $conf->table); |
| |
$self->{sql_delete}->execute(); |
| |
|
| |
|
| $self->prepare_keyword('sql_insert', " |
$self->prepare_keyword('sql_insert', " |
| INSERT INTO " . $conf->table . " |
INSERT INTO " . $conf->table . " |
| (created, hostname, log_level, process_name, |
(created, hostname, log_level, process_name, |
| pid, postfix_key, client_hostname, client_ip, |
pid, postfix_key, client_hostname, client_ip, client_uid, |
| message_id, resent_message_id, mail_from, mail_to, |
message_id, resent_message_id, mail_from, mail_to, |
| mail_size, mail_nrcpt, relay, delay, |
mail_size, mail_nrcpt, relay, delay, |
| status, proto, helo, message) |
status, proto, helo, message) |
| VALUES |
VALUES |
| (?, ?, ?, ?, |
(?, ?, ?, ?, |
| ?, ?, ?, ?, |
?, ?, ?, ?, ?, |
| ?, ?, ?, ?, |
?, ?, ?, ?, |
| ?, ?, ?, ?, |
?, ?, ?, ?, |
| ?, ?, ?, ?) |
?, ?, ?, ?) |
|
|
| |
|
| } # }}} |
} # }}} |
| |
|
| |
sub _parse_by_equal($$;) |
| |
{ # {{{ |
| |
my ($str, $hash) = @_; |
| |
|
| |
(my @params) = split(/([\s|,|;]+)/o, $str); |
| |
|
| |
foreach my $param (@params) { |
| |
if ($param =~ m/(.*)\=(.*)/) { |
| |
#my ($par, $val) = ($1, $2); |
| |
$hash->{$1} = $2; |
| |
} |
| |
} |
| |
|
| |
} # }}} |
| |
|
| 1; |
1; |
| |
|
| __END__ |
__END__ |