#!/usr/bin/perl

use lib "../lib";
use Mail::Internet;
use Mail::SpamAssassin;

sub sortbynum {
  $a =~ m,\/(\d+).*$,; my $anum = $1;
  $b =~ m,\/(\d+).*$,; my $bnum = $1;
  ($anum <=> $bnum);
}

$rulesfile = "../spamassassin.cf";
if (-f "spamassassin.cf") { $rulesfile = "spamassassin.cf"; }

my $spamtest = new Mail::SpamAssassin ({
  'rules_filename'      => $rulesfile,
  'userprefs_filename'  => "../spamassassin.prefs",
  'local_tests_only'    => 1
});

foreach my $folder (@ARGV) {
  if (-d $folder && (-f "$folder/1" || -f "$folder/cyrus.index")) {
    # it's an MH folder or a Cyrus mailbox
    mass_check_mh_folder($folder);
  } elsif (-f $folder) {
    mass_check_mailbox($folder);
  }
}

sub mass_check_mh_folder {
  my $folder = shift;
  my @files = <$folder/[0-9]*>;

  foreach my $mail (sort sortbynum @files) {
    open (STDIN, "<$mail");
    my $ma = Mail::Audit->new();
    docheck ($mail, $ma);
  }
}

sub mass_check_mailbox {
  my $folder = shift;

  open (MBOX, "<$folder") or warn "open $folder failed $@";
  while (<MBOX>) { /^From \S+ +... ... / and last; }
  $count = 1;

  while (!eof MBOX) {
    my $tmpf = "/tmp/mass-check.$$";
    open (MSG, ">$tmpf");
    my $msgid = undef;
    while (<MBOX>) {
      /^Message-I[dD]: (.*)\s*$/ and $msgid = $1;
      /^From \S+ +... ... / and last;
      print MSG;
    }
    close MSG;

    if (defined ($msgid)) {
      $msgid =~ s/[^-_<>A-Za-z0-9\.\,\:\=\+\@]/_/gs;	# make safe
    } else {
      $msgid = "<".($count++)."\@no_msgid_in_msg>";
    }
    $msgid = "$folder:$msgid";		# so we can find it again

    open (STDIN, "<$tmpf");
    my $ma = Mail::Audit->new();
    docheck ($msgid, $ma);
    close STDIN;
  }
  close MBOX;
  unlink $tmpf;
}

sub docheck {
  my $id = shift;
  my $ma = shift;

  $ma->{noexit} = 1;
  my $status = $spamtest->check ($ma);
  $status->rewrite_mail ();

  $_ = $ma->get ("X-Spam-Status");
  /^(\S+), hits=(\S+) required=\S+ tests=(.+)\s*$/s;

  my $yorn = $status->is_spam();
  my $hits = $status->get_hits();
  my $tests = $status->get_names_of_tests_hit();

  $ma = undef;		# clean 'em up
  $status->finish();
  $status = undef;

  printf "%s %2d %s %s\n",
		    ($yorn ? 'Y' : '.'),
		    $hits, $id, $tests;
}
