Mail::Exim::MainLogParser ============================ Mail::Exim::MainLogParser - Parse log lines from the Exim Main Log Build and install this module: perl Makefile.PL make make test make install NAME Mail::Exim::MainLogParser - Parse log lines from the Exim Main Log SYNOPSIS use Mail::Exim::MainLogParser; use Data::Dumper; my $exlog = new Mail::Exim::MainLogParser; my $logline = "2017-06-08 11:17:56 1dJ08B-0003oP-5i <= do-not-reply@nowhere.com H=realmail.server.example.com (ehlo-name.example.com) [192.168.250.101] P=esmtp S=1364 id=266785270.3.2385849643852@peerhost.server.example.com"; $logLineHashStructure = $exlog->parse($logline); print Dumper($logLineHashStructure); $VAR1 = { 'eximid' => '1dJ08B-0003oP-5i', 'time' => '11:17:56', 'date' => '2017-06-08', 'args' => [ { 'H' => 'realmail.server.example.com (ehlo-name.example.com) [192.168.250.101]' }, { 'P' => 'esmtp' }, { 'S' => '1364' }, { 'id' => '266785270.3.2385849643852@peerhost.server.example.com' } ], 'address' => 'do-not-reply@nowhere.com', 'flag' => '<=' }; DESCRIPTION This module will parse log lines from Exim version 4, according to the source http://www.exim.org/exim-html-current/doc/html/spec_html/ch-log_files.ht ml as of 2017-06-08 REQUIREMENTS This module is pure perl and does not depend on other modules. But does depend on a log file from Exim version 4 main log output. * Exim 4 IMPORTED METHODS When the calling application invokes this module in a use clause, the following method can be imported into its space. * "EximMainLoglineParse" * "EximMainLoglineCompose" METHODS new Create a new object instances of this module. It is not necessary to create an object for this module, as the methods can be called outside of OO style programming. * *returns* An object instance of this module. my $eximlog = new Mail::Exim::MainLogParser(); EximMainLoglineParse See "parse()". parse Parse a line from the Exim main log file and return a hash structure. $exim_log_line_hash = $exlog->parse($exim_log_line_string); * exim_log_line_string This is a single line from the Exim main log output. The below example log line is split over several lines in order to fit it on the page. 2017-06-08 11:17:56 1dJ08B-0003oP-5i <= do-not-reply@nowhere.com H=realmail.server.example.com (ehlo-name.example.com) [192.168.250.101] P=esmtp S=1364 id=266785270.3.2385849643852@peerhost.server.example.com This method returns a hash structure of the parsed log line. print Dumper($exim_log_line_hash); $VAR1 = { 'eximid' => '1dJ08B-0003oP-5i', 'time' => '11:17:56', 'date' => '2017-06-08', 'args' => [ { 'H' => 'realmail.server.example.com (ehlo-name.example.com) [192.168.250.101]' }, { 'P' => 'esmtp' }, { 'S' => '1364' }, { 'id' => '266785270.3.2385849643852@peerhost.server.example.com' } ], 'address' => 'do-not-reply@nowhere.com', 'flag' => '<=' }; EximMainLoglineCompose See "compose()". compose Compose a log line from a parsed main log line hash and return as a string. $exim_log_line_composed = $exlog->compoe($exim_log_line_hash) * exim_log_line_hash This is a single parsed line from the Exim main log output represented as a HASH. $exim_parsed_main_log_line = { 'eximid' => '1dJ08B-0003oP-5i', 'time' => '11:17:56', 'date' => '2017-06-08', 'args' => [ { 'H' => 'realmail.server.example.com (ehlo-name.example.com) [192.168.250.101]' }, { 'P' => 'esmtp' }, { 'S' => '1364' }, { 'id' => '266785270.3.2385849643852@peerhost.server.example.com' } ], 'address' => 'do-not-reply@nowhere.com', 'flag' => '<=' }; This method returns a string composition of the parsed log line HASH structure. It is intended that the composed string matches the original log line that was parsed, minus trailing white space. print "$LoglineComposed"; 2017-06-08 11:17:56 1dJ08B-0003oP-5i <= do-not-reply@nowhere.com H=realmail.server.example.com (ehlo-name.example.com) [192.168.250.101] P=esmtp S=1364 id=266785270.3.2385849643852@peerhost.server.example.com EXAMPLES Show exim mail transactions for a particular email address use Mail::Exim::MainLogParser; $exilog = new Mail::Exim::MainLogParser(); my $emailaddress='me@example.com'; my $index = {}; my @mine_queued = (); my $line_count = 0; # open(EXIMLOG,"tail -f /var/log/exim/main.log |"); # Use `tail -f` to watch logs in real time open(EXIMLOG,"cat /var/log/exim/main.log |"); while (my $line = ) { $line_count++; chomp($line); my $parsed = $exilog->parse($line) || (warn "Warn: Could not parse line $line_count.\n" && next); # Add each transaction to an eximid index if (exists $parsed->{'eximid'}) { push(@{$index->{$parsed->{'eximid'}}}, $parsed); } # Track the exim transactions that send or deliver via my email address if ((exists $parsed->{'address'}) && ($parsed->{'address'} =~ /$emailaddress/i)) { push(@mine_queued,$parsed->{'eximid'}); } # Once a queued message is completed, print out transactions if mine, delete it if ((exists $parsed->{'message'}) && ($parsed->{'message'} =~ /Completed/i)) { my $eximid = $parsed->{'eximid'}; if (grep /$eximid/, @mine_queued) { foreach my $eximtransaction (@{$index->{$eximid}}) { print $exilog->compose($eximtransaction),"\n"; } @mine_queued = grep ! /$eximid/, @mine_queued; } delete $index->{$eximid}; } } if (scalar @mine_queued >= 1) { # Once we reach the end of the log, there may still be messages that have not completed yet print "#"x10," My Uncompleted Messages ","#"x10,"\n"; foreach my $eximid (@mine_queued) { foreach my $eximtransaction (@{$index->{$eximid}}) { print $exilog->compose($eximtransaction),"\n"; } } } close(EXIMLOG); AUTHOR Russell Glaue, http://russ.glaue.org SEE ALSO Exim4 log documentation: http://www.exim.org/exim-html-current/doc/html/spec_html/ch-log_files.ht ml COPYRIGHT Copyright (c) 2017-2020 Russell E Glaue, Center for the Application of Information Technologies, Western Illinois University All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The full text of the license can be found in the LICENSE file included with this module.