Mail-Toaster

 view release on metacpan or  search on metacpan

lib/Mail/Toaster/Logs.pm  view on Meta::CPAN


    # freebsd's maillog is rotated daily
    if ( $OSNAME eq "freebsd" ) {
        my $file = "/var/log/maillog.0";

        return -e "$file.bz2" ? "$file.bz2"
            : -e "$file.gz" ? "$file.gz"
            : croak "could not find yesterdays qmail-send logs! ";
    }

    if ( $OSNAME eq "darwin" ) {
        return "/var/log/mail.log"; # logs are rotated weekly.
    }

    my $file = "/var/log/mail.log.0";

    return -e "$file.gz" ? "$file.gz"
         : -e "$file.bz2" ? "$file.bz2"
         : croak "could not find your mail logs from yesterday!\n";
};

sub get_yesterdays_smtp_log {
    my $self  = shift;

    my $logbase = $self->toaster->get_log_dir;

    # set up our date variables for today
    my ( $dd, $mm, $yy ) = $self->util->get_the_date(bump=>0);

    # where todays logs are being archived
    my $today = "$logbase/$yy/$mm/$dd/smtplog";
    $self->audit( "updating todays symlink for smtplogs to $today" );
    unlink("$logbase/smtplog") if -l "$logbase/smtplog";
    symlink( $today, "$logbase/smtplog" );

    ( $dd, $mm, $yy ) = $self->util->get_the_date(bump=>1);

    # where yesterdays logs are being archived
    my $yester = "$logbase/$yy/$mm/$dd/smtplog.gz";
    $self->audit( "updating yesterdays symlink for smtplogs" );
    unlink("$logbase/smtplog.gz") if -l "$logbase/smtplog.gz";
    symlink( $yester, "$logbase/smtplog.gz" );

    return $yester;
};

sub verify_settings {
    my $self = shift;
    my %p = validate(@_, { $self->get_std_opts } );
    return $p{test_ok} if defined $p{test_ok};

    my $logbase  = $self->toaster->get_log_dir;
    my $counters = $self->conf->{logs_counters} || "counters";

    my $user  = $self->conf->{logs_user}  || 'qmaill';
    my $group = $self->conf->{logs_group} || 'qnofiles';

    if ( !-e $logbase ) {
        mkpath( $logbase, 0, oct('0755') )
            or return $self->error( "Couldn't create $logbase: $!", %p );
        $self->util->chown($logbase, uid=>$user, gid=>$group) or return;
    };

    if ( -w $logbase ) {
        $self->util->chown($logbase, uid=>$user, gid=>$group) or return;
    }

    my $dir = "$logbase/$counters";

    if ( ! -e $dir ) {
        eval { mkpath( $dir, 0, oct('0755') ); };
        return $self->error( "Couldn't create $dir: $!",fatal=>0) if $EVAL_ERROR;
        $self->util->chown($dir, uid=>$user, gid=>$group) or return;
    }
    $self->error( "$dir is not a directory!",fatal=>0) if ! -d $dir;

    my $script = "/usr/local/bin/maillogs";
       $script = '/usr/local/sbin/maillogs' if ! -x $script;

    return $self->error( "$script must be installed!",fatal=>0) if ! -e $script;
    return $self->error( "$script must be executable!",fatal=>0) if ! -x $script;
    return 1;
}

sub parse_cmdline_flags {
    my $self  = shift;

    my %p = validate(@_, {
        'prot' => { type=>SCALAR|UNDEF, optional=>1, },
        $self->get_std_opts,
    } );

    my $prot  = $p{prot} or pod2usage;

    my @prots = qw/ smtp send imap pop3 rbl yesterday qmailscanner
                    spamassassin webmail test /;
    my %valid_prots = map { $_ => 1 } @prots;

    pod2usage if !$valid_prots{$prot};

    return 1 if $prot eq "test";

    $self->audit( "parse_cmdline_flags: prot is $prot" );

    return $self->smtp_auth_count if $prot eq "smtp";
    return $self->rbl_count       if $prot eq "rbl";
    return $self->send_count      if $prot eq "send";
    return $self->pop3_count      if $prot eq "pop3";
    return $self->imap_count      if $prot eq "imap";
    return $self->spama_count     if $prot eq "spamassassin";
    return $self->qms_count       if $prot eq "qmailscanner";
    return $self->webmail_count   if $prot eq "webmail";
    return $self->report_yesterdays_activity if $prot eq "yesterday";
    pod2usage;
}

sub what_am_i {
    my $self  = shift;
    $self->audit( "what_am_i: $0");
    $0 =~ /([a-zA-Z0-9\.]*)$/;
    $self->audit( "  returning $1" );
    return $1;
}

sub rbl_count {
    my $self  = shift;
    my $verbose = $self->{verbose};

    my $countfile = $self->set_countfile(prot=>"rbl");
    $spam_ref     = $self->counter_read( file=>$countfile );
    my $logbase = $self->toaster->get_log_dir;

    $self->process_rbl_logs(

lib/Mail/Toaster/Logs.pm  view on Meta::CPAN

        $activity =~ /^status: local ([0-9]*)\/([0-9]*) remote ([0-9]*)\/([0-9]*)/;

        $count_ref->{status_localp}  += ( $1 / $2 );
        $count_ref->{status_remotep} += ( $3 / $4 );

        $count_ref->{status}++;
    }
    elsif ( $activity =~ /^end msg/ ) {
        # end msg 71766
        # /^end msg ([0-9]*)$/

        # this line is useless, why was it here?
        #$count_ref->{local}++ if ( $3 && $3 eq "local" );

        $count_ref->{message_end}++;
    }
    elsif ( $activity =~ /^delivery/ ) {
        # delivery 136986: success: 67.109.54.82_accepted_message./Remote_host_said:
        #   _250_2.6.0__<000c01c6c92a$97f4a580$8a46c3d4@p3>_Queued_mail_for_delivery/

        $activity =~ /^delivery ([0-9]*): ([a-z]*): /;

           if ( $2 eq "success"  ) { $count_ref->{delivery_success}++  }
        elsif ( $2 eq "deferral" ) { $count_ref->{delivery_deferral}++ }
        elsif ( $2 eq "failure"  ) { $count_ref->{delivery_failure}++  }
        else { print "unknown " . $activity . "\n"; };

        $count_ref->{delivery}++;
    }
    elsif ( $activity =~ /^bounce/ ) {
        # /^bounce msg ([0-9]*) [a-z]* ([0-9]*)/
        $count_ref->{message_bounce}++;
    }
    else {
        #warn "other: $activity";
        $count_ref->{other}++;
    }

    return 1;
}


sub counter_create {
    my $self = shift;
    my $file = shift;

    my $verbose = $self->{verbose};
    carp "\nWARN: the file $file is missing! I will try to create it." if $verbose;

    if ( ! $self->util->is_writable( $file,verbose=>0,fatal=>0) ) {
        carp "FAILED.\n $file does not exist and the user $UID has "
            . "insufficent privileges to create it!" if $verbose;
        return;
    };

    $self->counter_write( log => $file, values => { created => time, },);

    my $user = $self->{conf}{logs_user} || "qmaill";
    my $group = $self->{conf}{logs_group} || "qnofiles";

    $self->util->chown( $file, uid=>$user, gid=>$group, verbose=>0);

    print "done.\n";
    return 1;
};

sub counter_read {
    my $self  = shift;
    my %p = validate(@_, { 'file' => SCALAR, $self->get_std_opts } );
    my %args = $self->get_std_args( %p );

    my $file  = $p{file} or croak "you must pass a filename!\n";
    my $verbose = $p{verbose};

    if ( ! -e $file ) {
        $self->counter_create( $file ) or return;
    }

    my %hash = (
            connect_last => 0,
            success_last => 0
            );

    foreach ( $self->util->file_read( $file, verbose=>$verbose ) ) {
        my ($description, $count) = split( /:/, $_ );
        $hash{ $description } = $count;
    }

    $self->audit( "counter_read: read counters from $file", %args );

    return \%hash;
}

sub counter_write {
    my $self  = shift;
    my %p = validate( @_, {
            'values' => HASHREF,
            'log'    => SCALAR,
            $self->get_std_opts,
        },
    );
    my %args = $self->get_std_args( %p );

    my ( $logfile, $values_ref ) = ( $p{log}, $p{values} );

    if ( -d $logfile ) {
        print "FAILURE: counter_write $logfile is a directory!\n";
    }

    return $self->error( "counter_write: $logfile is not writable",fatal=>0 )
        unless $self->util->is_writable( $logfile, %args  );

    unless ( -e $logfile ) {
        print "NOTICE: counter_write is creating $logfile";
    }

    # it might be necessary to wrap the counters
    #
    # if so, the 32 and 64 bit limits are listed below. Just
    # check the number, and subtract the maximum value for it.
    # rrdtool will continue to Do The Right Thing. :)



( run in 0.803 second using v1.01-cache-2.11-cpan-71847e10f99 )