#!/usr/bin/perl
#
# qmHandle 0.4.0
#
# Copyright(c) 1998 Michele Beltrame <mick@io.com>
#
# You can freely use, modify and redistribute for free this program, as long
# as this notice remains intact. If you plan to resell this program, you have
# to contact me before doing that.

# Set this to your qmail queue directory (be sure to include the final slash!)
$queue = "/var/qmail/queue/";
$qmcmd = '/etc/rc.d/init.d/qmail start';
# Replace the above with this if you have qmail < 1.03:
## $qmcmd = '/var/qmail/bin/qmail-start ./Mailbox splogger qmail &';

# Print help
sub Usage {
  print "qmHandle v0.4.0\n";
  print "by Michele Beltrame\n\n";
  print "Wrong parameters entered, [$arg] available ones are:\n";
  print "  -l   : list message queues\n";
  print "  -L   : list local message queue\n";
  print "  -R   : list remote message queue\n";
  print "  -s   : show some statistics\n";
  print "  -vN  : display message number N\n";
  print "  -dN  : delete  message number N\n";
  print "Additional (optional) parameters are:\n";
  print "  -c   : display colored output\n";
  print "  -N   : list message numbers only queues\n";
  print "         (to be used either with -l, -L or -R)\n\n";
  print "You can view/delete multiple message eg -d123 -v456 -d567\n\n";
  exit (1);
}

if ($#ARGV == -1) { Usage(); }; # No arguments

# Make list of messages in remote queue
@dirlist = split (/\n/, `ls -1 -R ${queue}remote`);
for ($i=0; $i<=$#dirlist; $i++) {
  if ($dirlist[$i++] =~ /\/(\d+):$/) {
    while ($dirlist[$i] ne '') {
      push @msglist, "$1/$dirlist[$i]";
      $type{"$1/$dirlist[$i++]"} = 'R';
    }
  }
}

# Make list of messages in local queue
@dirlist = split (/\n/, `ls -1 -R ${queue}local`);
for ($i=0; $i<=$#dirlist; $i++) {
  if ($dirlist[$i++] =~ /\/(\d+):$/) {
    while ($dirlist[$i] ne '') {
      push @msglist, "$1/$dirlist[$i]";
      $type{"$1/$dirlist[$i++]"} = 'L';
    }
  }
}

# Get options & perform action
$color = 0;
$summary = 0;
foreach $arg(@ARGV) {
  SWITCH: {
    $arg eq '-l' && do { push @actions, "&ListMsg('A')"; last SWITCH; };
    $arg eq '-R' && do { push @actions, "&ListMsg('L')"; last SWITCH; };
    $arg eq '-L' && do { push @actions, "&ListMsg('R')"; last SWITCH; };
    $arg eq '-N' && do { $summary = 1; last SWITCH; };
    $arg eq '-c' && do { $color = 1; last SWITCH; };
    $arg eq '-s' && do { push @actions, "&Stats()"; last SWITCH; };
    $arg =~ /^-v(.+)/ && do { push @actions, "&ViewMsg($1)"; last SWITCH; };
    $arg =~ /^-d(.+)/ && do { push @actions, "&DelMsg($1)"; last SWITCH; };
    &Usage();
  }
}

foreach $action(@actions) {
  eval "$action";
}

exit(0);

# Display message list
# pass parameter of queue NOT to list! i.e. if you want remote only, pass L
# if you want local, pass R  if you want all pass anything else eg A
sub ListMsg {
  $q = shift;

  if ($summary == 0) {
    foreach $msg(@msglist) {
      # Read return path
      open (MSG, "${queue}info/$msg");
      $ret{$msg} = <MSG>;
      substr($ret{$msg}, 0, 1) = '';
      chop ($ret{$msg});
      close (MSG);

      # Get message (file) size
      $fsize{$msg} = (stat("${queue}mess/$msg"))[7];

      # Read something from message header (from, subject, date)
      open (MSG, "${queue}mess/$msg");
      while (<MSG>) {
        if ($_ =~ /^Date: /) {
          $date{$msg} = $';
          chop ($date{$msg});
        } elsif ( $_ =~ /^From: /) {
          $from{$msg} = $';
          chop ($from{$msg});
        } elsif ( $_ =~ /^Subject: /) {
          $subj{$msg} = $';
        chop ($subj{$msg});
        } elsif ( $_ =~ /^To: /) {
          $to{$msg} = $';
          chop ($to{$msg});
        } elsif ( $_ eq "\n") {
          last;
        }
      }
    }
  }

  if ($color == 1) {
    foreach $msg(@msglist) {
      unless ($q eq $type{$msg})  {
        ($dir, $rmsg) = split (/\//, $msg);
        print chr(27)."[01;34m$rmsg ($dir, $type{$msg})\n";
        if ($summary == 0) {
          print "  ".chr(27)."[01;31mReturn-path".chr(27)."[00m: $ret{$msg}\n";
          print "  ".chr(27)."[01;31mFrom".chr(27)."[00m: $from{$msg}\n";
          print "  ".chr(27)."[01;31mTo".chr(27)."[00m: $to{$msg}\n";
          print "  ".chr(27)."[01;31mSubject".chr(27)."[00m: $subj{$msg}\n";
          print "  ".chr(27)."[01;31mDate".chr(27)."[00m: $date{$msg}\n";
          print "  ".chr(27)."[01;31mSize".chr(27)."[00m: $fsize{$msg} bytes\n\n";
        }
      }
    }
  } else {
    foreach $msg(@msglist) {
      unless ($q eq $type{$msg})  {
        ($dir, $rmsg) = split (/\//, $msg);
        print "$rmsg ($dir, $type{$msg})\n";
        if ($summary == 0) {
          print "  Return-path: $ret{$msg}\n";
          print "  From: $from{$msg}\n";
          print "  To: $to{$msg}\n";
          print "  Subject: $subj{$msg}\n";
          print "  Date: $date{$msg}\n";
          print "  Size: $fsize{$msg} bytes\n\n";
        }
      }
    }
  }
  &Stats();
}

sub ViewMsg {
  $rmsg = shift;

  # Search message
  $ok = 0;
  foreach $msg(@msglist) {
    if ($msg =~ /$rmsg$/) {
      $ok = 1;
      print "\n --------------\nMESSAGE NUMBER $rmsg \n --------------\n"; 
      open (MSG, "${queue}mess/$msg");
      while (<MSG>) {
        print $_;
      }
      close (MSG);
      last;
    }
  }

  # If the message isn't found, print a notice
  if ($ok == 0) {
    print "Message $rmsg not found in the queue!\n";
  }
}

sub DelMsg {
  $rmsg = shift;

	system('/etc/rc.d/init.d/qmail stop');

  # Search message
  $ok = 0;
  foreach $msg(@msglist) {
    if ($msg =~ /$rmsg$/) {
      $ok = 1;
      unlink "${queue}mess/$msg";
      unlink "${queue}info/$msg";
      if ($type{$msg} eq 'R') {
        unlink "${queue}remote/$msg";
      } else {
        unlink "${queue}local/$msg";
      }
      last;
    }
  }

  # If the message isn't found, print a notice
  if ($ok == 0) {
    print "Message $rmsg not found in the queue!\n";
  }

	system($qmcmd);
}

# Make statistics
sub Stats {
  $l=0; $r=0;
  foreach $msg(@msglist) {
    if ($type{$msg} eq 'R') { $r++; }
    else { $l++; }
  }
  if ($color == 1) {
    print chr(27)."[01;31mMessages in local queue".chr(27)."[00m: $l\n";
    print chr(27)."[01;31mMessages in remote queue".chr(27)."[00m: $r\n";
  } else {
    print "Messages in local queue: $l\n";
    print "Messages in remote queue: $r\n";
  }

}

