#!/usr/bin/perl
use lib "/usr/local/atmail/webmail/library/"; 

# Place the process into the background
# More reliable log-daemon then PHP copy

fork && exit;

open(F,">/usr/local/atmail/mailserver/spool/atmail-lprocess.pid");
print F $$;
close(F);

$ENV{SCRIPT_NAME} = "log-daemon.pl";

use File::Tail;
use Atmail::SQL;
use Atmail::Log;

my $log = new Atmail::Log;
my %trace;

#$name="/var/log/syslog" unless $name=shift @ARGV;
$debug=shift @ARGV || 0;
$version=shift @ARGV || 0;

# IMAP/POP3
push(@files,File::Tail->new(name=>"/usr/local/atmail/mailserver/spool/log/dovecot_info_log",debug=>$debug, interval=>1,maxinterval=>3,adjustafter=>20));

# SMTP
push(@files,File::Tail->new(name=>"/usr/local/atmail/mailserver/spool/log/mainlog",debug=>$debug, interval=>1,maxinterval=>3,adjustafter=>20));

# CalDAV - If installed
if(-e "/usr/local/atmail/calendarserver/server/logs/access.log") {
push(@files,File::Tail->new(name=>"/usr/local/atmail/calendarserver/server/logs/access.log",debug=>$debug, interval=>1,maxinterval=>3,adjustafter=>20));
}

# Spamassassin ( use Exim spam log output )
#push(@files,File::Tail->new(name=>"/usr/local/atmail/mailserver/spool/log/spamd_log",debug=>$debug, interval=>1,maxinterval=>3,adjustafter=>20));

my $rin='';
my %log;

while (1) {
        ($nfound,$timeleft,@pending) = File::Tail::select(undef,undef,undef,60,@files);

        unless ($nfound) {
            my @ints;
            foreach(@files) {
                push(@ints,$_->interval);
            }
        }

        foreach (@pending) {

		my $line = $_->read;

		# Log when a user logs in via imap successfully
	    if($_->{"input"} =~ /dovecot_info_log/ && $line =~ /(imap|pop3)-login: Info: Login: user=<(.*?)>, method=.*?, rip=(.*?), lip=(.*)/i)  {
		$log->{Account} = $2;

		my %msg;
		$msg{'LogIP'} = $3;
		
		# Which logtype are we, pop3/imap, or pop3s/imaps connection
		my $type = $1;
		$msg{'LogType'} = 1 if($type eq "pop3");
		$msg{'LogType'} = 3 if($type eq "imap");

		$connection = $4;
		
		# Check if the connection is SSL
		$msg{'LogType'} = 4 if($connection =~ /, TLS/ && $type eq "imap");
		$msg{'LogType'} = 2 if($connection =~ /, TLS/ && $type eq "pop3");
		
		my $user = $1;
		my $time = time();
		
			if(!$log{$msg{'LogIP'}} || time() - $log{$msg{'LogIP'}} > 300)	{			
			$log->log_raw("Login", %msg);
			$log->updatelastlogin($log->{Account});
			$log->addrelay($msg{'LogIP'}) if($log->{smtp_popimaprelay});	
			$log{$user} = $time;
			}

		}

		# Log a mail-delivery into Atmail, do not log deferred attempts
		elsif($_->{"input"} =~ /mainlog/ && $line =~ /(\w+-\w+-\w+) => .*? <(.*?)> R=mysql_user T=mysql_delivery$/i)	{
		my %msg;
		$msg{'MessageID'} = $1;
		$msg{'EmailFrom'} = $trace{$1}; # Get the email sender from the trace, previous log line
		$msg{'LogIP'} = $trace{$1 . "ip"}; # Get the email sender from the trace, previous log line
		
		$log->{Account} = $2;
		$log->log_raw("RecvMail", %msg);
		}

		# A message thats moved to the Spam folder
		elsif($_->{"input"} =~ /mainlog/ && $line =~ /(\w+-\w+-\w+) => (.*?) R=mysql_spamfolder T=mysql_delivery_spamfolder/i)	{
		# 1st log the request
		my %msg;
		$msg{'MessageID'} = $1;
		$msg{'EmailFrom'} = $trace{$1}; # Get the email sender from the trace, previous log line
		$msg{'LogIP'} = $trace{$1 . "ip"}; # Get the email sender from the trace, previous log line

		$log->{Account} = $2;
		$log->log_raw("RecvMail", %msg);

		# 2nd log its marked as Spam
		# TODO: Just read the Spamassassin log?
		$msg{'LogType'} = 3; # LogType 3 == Moved to Spam folder
		$log->log_raw("Spam", %msg);
		
		print "MOVED TO SPAM Msg from $trace{$1}\n";
		}

		# A message thats marked as Spam
		elsif($_->{"input"} =~ /mainlog/ && $line =~ /(\w+-\w+-\w+) => .*? <(.*?)> R=mysql_user_spam T=mysql_delivery$/i)	{
		# 1st log the request
		my %msg;
		$msg{'MessageID'} = $1;
		$msg{'EmailFrom'} = $trace{$1}; # Get the email sender from the trace, previous log line
		$msg{'LogIP'} = $trace{$1 . "ip"}; # Get the email sender from the trace, previous log line

		$log->{Account} = $2;
		$log->log_raw("RecvMail", %msg);

		# 2nd log its marked as Spam
		# TODO: Just read the Spamassassin log?
		$msg{'LogType'} = 1; # LogType 1 == Identified as spam
		$log->log_raw("Spam", %msg);

		print "MARKED AS SPAM Msg from $trace{$1}\n";
		}
		
		# Spam message purged from system
		
		# Over quota error
		elsif($_->{"input"} =~ /mainlog/ && $line =~ /(\w+-\w+-\w+) == (.*?) R=mysql_.*? T=mysql_.*? defer \(-22\): mailbox is full/i)	{
		$log->{Account} = $2;

		my %msg;
		$msg{'LogMsg'} = "Quota exceeded. Msg from $trace{$1}";
		$log->log_raw("Error", %msg);

		print "FULL MAILBOX Quota exceeded. Msg from $trace{$1}\n";
		}
		
		# RBL Log
		# 2009-06-28 05:29:24 H=([117.198.50.11]) [117.198.50.11] F=<cialisrene@atmail.com> rejected RCPT <cialisrene@atmail.com>: Rejected message because 117.198.50.11 is in a black list at sbl-xbl.spamhaus.org
		
		elsif($_->{"input"} =~ /mainlog/ && $line =~ /H=.*?\[(.*?)\] F=<(.*?)> rejected RCPT <(.*?)>: (Rejected message because.*)/i)	{
		$log->{Account} = $3;

		my %msg;
		$msg{'LogIP'} = $1;
		$msg{'EmailFrom'} = $2;
		$msg{'LogType'} = 4; # LogType 4 == RBL match
		$log->log_raw("Spam", %msg);
		}

		# Anti-Spam Log
		elsif($_->{"input"} =~ /mainlog/ && $line =~ /H=.*?\[(.*?)\] F=<(.*?)> .*? Spam-score too high : (.*?) spam/)	{
		my %msg;
		$msg{'LogIP'} = $1;
		$msg{'EmailFrom'} = $2;
		$msg{'SpamPoints'} = $3;
		$msg{'LogType'} = 2; # LogType 2 == SA Reject
		$log->log_raw("Spam", %msg);
		}
		
		# Log a DKIM failure ( Bad header )
		# 1MbSyN-0004oR-BI H=(myhost) [192.168.31.1] F=<ben@me.com> rejected after DATA: Bad DKIM Header
		elsif($_->{"input"} =~ /mainlog/ && $line =~ /H=.*?\[(.*?)\] F=<(.*?)> rejected after DATA: Bad DKIM Header/i)	{
		$log->{Account} = "";	# Exim does not log the RCPT on a DKIM rejection

		my %msg;
		$msg{'LogIP'} = $1;
		$msg{'EmailFrom'} = $2;
		$msg{'LogType'} = 5; # LogType 5 == DKIM Rejection
		$log->log_raw("Spam", %msg);
		}
		
		# Log an outgoing message requesth
		# 1HUFy9-0006Go-Ld <= p@uflexusa.com H=fl-71-2-132-113.dhcp.embarqhsd.net [71.2.132.113] P=smtp S=27639 
		elsif($_->{"input"} =~ /mainlog/ && $line =~ /(\w+-\w+-\w+) <= (.*?) H=.*? \[(.*?)\] P=e?smtp/i)	{
		$trace{$1} = $2; # Index the sender
		$trace{$1 . "ip"} = $3; # Index the IP
		}

		# Log each recipient of the message sent ( e.g via an external program or webmail )
		# TODO: Add smarthost router option
		elsif($_->{"input"} =~ /mainlog/ && $line =~ /(\w+-\w+-\w+) => (.*?) R=dnslookup/i)	{
		$log->{Account} = $trace{$1};
		next if(!$log->{Account});
		
		my %msg;
		$msg{'LogIP'} = $trace{$1 . "ip"};
		$msg{'MessageID'} = $1;
		$msg{'EmailTo'} = $2;
		
		$log->log_raw("SendMail", %msg);
		}

		# Match after an outgoing request is made, and cleanup our hash
		elsif($_->{"input"} =~ /mainlog/ && $line =~ /(\w+-\w+-\w+) Completed/i)	{
		delete $trace{$1};
		delete $trace{$1 . "ip"};
		}

		# Log a Virus report
		elsif($_->{"input"} =~ /mainlog/ && $line =~ /H=.*? \[(.*?)\] F=<(.*?)> rejected after DATA: Virus (.*?) detected/i)	{
		my %msg;
		$msg{'LogIP'} = $1;
		$msg{'EmailFrom'} = $2;
		$msg{'VirusName'} = $3;
		$log->log_raw("Virus", %msg);
		}
		
		# Log a CalDAV login
		#127.0.0.1 - 507714042@ben.com [17/Aug/2009:23:03:02 +1000] "PROPFIND /principals/users/507714042@ben.com/ HTTP/1.1" 207 898 "-" "Atmail 6.0" [11.0 ms] [8009 1]
		#127.0.0.1 - 507714042@ben.com [17/Aug/2009:23:16:26 +1000] "PROPFIND /calendars/users/507714042@ben.com/ HTTP/1.1" 207 5079 "-" "Atmail 6.0" [73.1 ms] [8009 1]
		#127.0.0.1 - 507714042@ben.com [17/Aug/2009:23:16:26 +1000] "PROPFIND /principals/users/507714042@ben.com/ HTTP/1.1" 207 898 "-" "Atmail 6.0" [143.5 ms] [8009 1]
		elsif($_->{"input"} =~ /calendarserver/ && $line =~ /(.*?) - (.*?) \[.*?\] "PROPFIND \/principals\/users\/(.*?)\/ HTTP\/1.1"/i)	{
		my %msg;
		$msg{'LogIP'} = $1;
		$msg{'LogType'} = '6';
		$log->{Account} = $2;
		my $login = $3;
		
		# Only match if login matches the PROPFIND url - Else duplicate logins for a single session
		$log->log_raw("Login", %msg) if($login eq $log->{Account});
			
		}
		

        }
    }
