qmhandle-1.3/0000775000077600007760000000000011007067403010104 5ustar qmhandle-1.3/README0000664000077600007760000001165510645045726011007 0ustar qmHandle 1.3.0 ============== Copyright 1998-2003 Michele Beltrame Modified by Chan Chung Hang Christopher (June, 2007) INTRO ----- This is a simple perl script that helps you to view and manage (within some limits) the qmail queue. With this script you can: * Read the qmail queue, like you do with the qmail-qread program. However, the output of this script provides more information compared to qmail-qread such as the message subject and color capabilities. * Print queue statistics, similar to qmail-qstat, with color capabilities * View a message in the queue. * Remove a message from the queue. * Remove messages that meet a criterion. * Tell qmail to slot messages with recipients in a remote domain for earlier retry (at the cost of longer queue stay). CONFIGURATION ------------- There are only a few variables to configure, and this has to be done depending on your system and qmail installation. You can find the variables at the top of the Perl script qmHandle (there's a configuration section properly marked). The variables are: 1) my ($queue) = '/var/qmail/queue/'; This is the path of your qmail queue directory. It's located here on 99.9% of qmail installation. If yours seems not to be there, try using the "find" command to locate it. 2) my ($stopqmail) = '/etc/init.d/qmail stop'; This is the name of the script/command which stops qmail. The one you see works on Debian GNU/Linux, if you have other you need to change it. In the script configuration section you'll find some examples of common options, including the one using DJB's daemontools. If you don't have any script to stop qmail, you *must leave this string empty*: $stopqmail = ''; 3) my ($startqmail) = "/etc/init.d/qmail start"; This is the name of the script/command which stops qmail. The one you see works on Debian GNU/Linux, if you have other you need to change it. In the script configuration section you'll find some examples of common options, including the one using DJB's daemontools and the standard qmail distribution. 4) my ($pidcmd) = 'pidof qmail-send'; This is the command used to obtain qmail process id. The default should work on most Unix systems, but if on yours doesn't you can change it. Please note that variables from 2 to 4 are only needed to set properly if you need to use qmHandle to delete messages in the queue. The first one is however needed in any case. USAGE ----- Usage is fairly simple. Here goes the help screen: Available parameters are: -a : try to send all queued messages now (qmail must be running) -l : list message queues -L : list local message queue -R : list remote message queue -s : show some statistics -mN : display message number N -dN : delete message number N -fsender : delete message from sender -f're' : delete message from senders matching regular expression re -Stext : delete all messages that have/contain text as Subject -h're' : delete all messages with headers matching regular expression re (case insensitive) -b're' : delete all messages with body matching regular expression re (case insensitive) -H're' : delete all messages with headers matching regular expression re (case sensitive) -B're' : delete all messages with body matching regular expression re (case sensitive) -t're' : flag messages with recipients in regular expression 're' for earlier retry (note: this lengthens the time message can stay in queue) -D : delete all messages in the queue (local & remote) -V : print program version Additional (optional) parameters are: -c : display colored output -N : list message numbers only (to be used either with -l, -L or -R) It's possible to specify multiple parameters for multiple actions, in any order. Please note that you'll have to be superuser (root) in order to use this program. A typical output of the command: qmHandle -l could be: ------------------------------------------------- 143874 (9, R) Return-path: m.beltrame@betamag.com From: Michele Beltrame To: beta-reg@nice.it Subject: Re: [beta-reg] Server news pubblico. Date: Fri, 10 Apr 1998 09:04:32 +0200 Size: 1600 bytes ------------------------------------------------- The first line shows the number the message has in queue (the name of the files in which it's stored) and, between parentheses, the directory number where it's located and the queue he's in (L=local, R=remote). GPL SOFTWARE ------------ This is open source software under the GPL (see 'GPL' file included in the distribution). For more information on the license have a look at: http://www.gnu.org ***For any problem, just drop an e-mail to mb@italpro.net.*** Michele Beltrame does not maintain qmhandle anymore. Please email cchan-freetown@users.sourceforge.net instead. This project is a SourceForge.Net shared project. For more information visit: http://qmhandle.sourceforge.net/ qmhandle-1.3/qmHandle0000775000077600007760000005342210650041061011564 0ustar #!/usr/bin/perl # # qmHandle # # Copyright(c) 1998 -> 2003 Michele Beltrame # # This program is distributed under the GNU GPL. # For more information have a look at http://www.gnu.org use strict; use warnings; use diagnostics; my $version = '1.3.2'; #################### USER CONFIGURATION BEGIN #################### ##### # Set this to your qmail queue directory (be sure to include the final slash!) my ($queue) = '/var/qmail/queue/'; my ($bigtodo) = (-d "${queue}todo/0") ? 0 : 1; # 1 means no big-todo ##### # If your system has got automated command to start/stop qmail, then # enter them here. # ### Be sure to uncomment only ONE of each variable declarations ### # For instance, this is if you have DJB's daemontools my ($stopqmail) = '/usr/local/bin/svc -d /service/qmail-deliver'; my ($startqmail) = '/usr/local/bin/svc -u /service/qmail-deliver'; # While this is if you have a Debian GNU/Linux with its qmail package #my ($stopqmail) = '/etc/init.d/qmail stop'; #my ($startqmail) = '/etc/init.d/qmail start'; # If you don't have scripts, leave $stopqmail blank (the process will # be hunted and killed by qmHandle): #my ($stopqmail) = ''; # However, you still need to launch qmail in a way or the other. So, # if you have a standard qmail 1.03 use this: #my ($startqmail) = "csh -cf '/var/qmail/rc &'"; # While, if you have a standard qmail < 1.03 you should use this: #my ($startqmail) = '/var/qmail/bin/qmail-start ./Mailbox splogger qmail &'; ##### # Enter here the system command which returns qmail PID. The following # should work on most Unixes: my ($pidcmd) = 'pidof qmail-send'; #################### USER CONFIGURATION END #################### # Print usage if no arguments if ($#ARGV == -1) { &Usage(); } # Get command line options my ($cmsg, $cstat, $cend) = ('', '', ''); my $summary = 0; my @actions = (); my $dactions = 0; foreach my $arg (@ARGV) { SWITCH: { $arg eq '-a' and do { push @actions, [\&SendMsgs]; last SWITCH; }; $arg eq '-l' and do { push @actions, [\&ListMsg, 'A']; last SWITCH; }; $arg eq '-L' and do { push @actions, [\&ListMsg, 'L']; last SWITCH; }; $arg eq '-R' and do { push @actions, [\&ListMsg, 'R']; last SWITCH; }; $arg eq '-N' and do { $summary = 1; last SWITCH; }; $arg eq '-c' and do { ($cmsg, $cstat, $cend) = ("\e[01;34m", "\e[01;31m", "\e[00m"); last SWITCH; }; $arg eq '-s' and do { push @actions, [\&Stats]; last SWITCH; }; $arg =~ /^-m(.+)/ and do { push @actions, [\&ViewMsg, $1]; last SWITCH; }; $arg =~ /^-f(.+)/ and do { push @actions, [\&DelMsgFromSender, $1]; $dactions++; last SWITCH; }; $arg =~ /^-F(.+)/ and do { push @actions, [\&DelMsgFromSenderR, $1]; $dactions++; last SWITCH; }; $arg =~ /^-d(.+)/ and do { push @actions, [\&DelMsg, $1]; $dactions++; last SWITCH; }; $arg =~ /^-S(.+)/ and do { push @actions, [\&DelMsgSubj, $1]; $dactions++; last SWITCH; }; $arg =~ /^-h(.+)/ and do { push @actions, [\&DelMsgHeaderR, 'I', $1]; $dactions++; last SWITCH; }; $arg =~ /^-b(.+)/ and do { push @actions, [\&DelMsgBodyR, 'I', $1]; $dactions++; last SWITCH; }; $arg =~ /^-H(.+)/ and do { push @actions, [\&DelMsgHeaderR, 'C', $1]; $dactions++; last SWITCH; }; $arg =~ /^-B(.+)/ and do { push @actions, [\&DelMsgBodyR, 'C', $1]; $dactions++; last SWITCH; }; $arg =~ /^-t(.+)/ and do { push @actions, [\&FlagRemote, $1]; last SWITCH; }; $arg eq '-D' and do { push @actions, [\&DelAll]; $dactions++; last SWITCH; }; $arg eq '-V' and do { push @actions, [\&Version]; last SWITCH; }; Usage(); } } # Set "global" variables my ($norestart) = 0; my (@todel) = (); my (@toflag) = (); my ($dmes) = 0; # Create a hash of messages in queue and the type of recipients they have and whether they are bouncing. my (%msglist) = (); my (%todohash) = (); my (%bouncehash) = (); my ($dirno, $msgno); opendir(DIR,"${queue}mess"); my (@dirlist) = grep !/\./, readdir DIR; closedir DIR; opendir(DIR,"${queue}todo"); my (@todolist) = grep !/\./, readdir DIR; closedir DIR; if ($bigtodo == 0) { foreach my $tododir (@todolist) { opendir (SUBDIR,"${queue}todo/$tododir"); my (@todofiles) = grep !/\./, map "$tododir/$_", readdir SUBDIR; foreach my $todofile (@todofiles) { $msglist{ $todofile }{ 'todo' } = $todofile; } } } else { foreach my $todofile (@todolist) { $todohash{$todofile} = $todofile; } } opendir(DIR,"${queue}bounce"); my (@bouncelist) = grep !/\./, readdir DIR; closedir DIR; foreach my $bouncefile (@bouncelist) { $bouncehash{$bouncefile} = 'B'; } foreach my $dir (@dirlist) { opendir (SUBDIR,"${queue}mess/$dir"); my (@files) = grep !/\./, map "$dir/$_", readdir SUBDIR; opendir (INFOSUBDIR,"${queue}info/$dir"); my (@infofiles) = grep !/\./, map "$dir/$_", readdir INFOSUBDIR; opendir (LOCALSUBDIR,"${queue}local/$dir"); my (@localfiles) = grep !/\./, map "$dir/$_", readdir LOCALSUBDIR; opendir (REMOTESUBDIR,"${queue}remote/$dir"); my (@remotefiles) = grep !/\./, map "$dir/$_", readdir REMOTESUBDIR; foreach my $infofile (@infofiles) { $msglist{$infofile}{'sender'} = 'S'; } foreach my $localfile (@localfiles) { $msglist{$localfile}{'local'} = 'L'; } foreach my $remotefile (@remotefiles) { $msglist{$remotefile}{'remote'} = 'R'; } foreach my $file (@files) { ($dirno, $msgno) = split(/\//, $file); if ($bouncehash{$msgno}) { $msglist{ $file }{ 'bounce' } = 'B'; } if ($bigtodo == 1) { if ($todohash{$msgno}) { $msglist{ $file }{ 'todo' } = "$msgno"; } } } closedir SUBDIR; closedir INFOSUBDIR; closedir LOCALSUBDIR; closedir REMOTESUBDIR; } # In case of deletion actions, stop qmail if ($dactions) { stopQmail() or die "Could not stop qmail: $!\n"; } # Execute actions foreach my $action (@actions) { my $sub = shift @$action; # First element is the sub $sub->(@$action); # Others the arguments, if any } # In case of deletion actions, restart qmail if ($dactions) { startQmail() or die "Could not stop qmail: $!\n"; } # ##### SERVICE FUNCTIONS ##### # Stop qmail sub stopQmail { my ($qmpid) = qmailPid(); # If qmail is running, we stop it if ($qmpid != 0) { # If there is a system script available, we use it if ($stopqmail ne '') { print "Calling system script to terminate qmail...\n"; if (system($stopqmail) > 0) { return 0; } # sleep 1; while (qmailPid()){ sleep 1; } # Otherwise, we're killers! } else { print "Terminating qmail (pid $qmpid)... this might take a while if qmail is working.\n"; kill 'TERM', $qmpid; while (qmailPid()){ sleep 1; } } # If it isn't, we don't. We also set a flag which assures we don't # restart it later either (the user might not want this) } else { print "Qmail isn't running... no need to stop it.\n"; $norestart = 1; } return 1; } # Start qmail sub startQmail { my ($qmpid) = qmailPid(); # If qmail is running, why restart it? if ($qmpid != 0) { print "Qmail is already running again, so it won't be restarted.\n"; # If it wasn't running before qmHandle was launched, it's better leave is this way } elsif ($norestart == 1) { print "Qmail wasn't running when qmHandle was started, so it won't be restarted.\n"; # In any other case, we restart it } else { print "Restarting qmail... "; system($startqmail); print "done (hopefully).\n"; } return 1; } # Returns the subject of a message sub getSubject { my $msg = shift; my $msgsub; open (MSG, "${queue}mess/$msg") or die("cannot open message $msg! Is qmail-send running?\n"); while () { if ( $_ =~ /^Subject: /) { $msgsub = $'; chop ($msgsub); } elsif ( $_ eq "\n") { last; } } close (MSG); return $msgsub; } sub getSender { my $msg = shift; my $sender; open (MSG, "${queue}/info/$msg") or die("cannot open info file ${queue}/info/$msg! Is qmail-send running?\n"); $sender = ; substr($sender, 0, 1) = ''; chop ($sender); close (MSG); return $sender; } # ##### MAIN FUNCTIONS ##### # Tries to send all queued messages now # This is achieved by sending an ALRM signal to qmail-send sub SendMsgs { my ($qmpid) = qmailPid(); # If qmail is running, we force sending of messages if ($qmpid != 0) { kill 'ALRM', $qmpid; } else { print "Qmail isn't running, can't send messages!\n"; } } sub showMessageInfo { my (%ret, %date, %from, %subj, %to, %cc, %fsize); my $msg = shift; # Read return path open (MSG, "${queue}info/$msg"); $ret{$msg} = ; substr($ret{$msg}, 0, 1) = ''; chop ($ret{$msg}); close (MSG); my ($dirno, $rmsg) = split(/\//, $msg); print "$rmsg ($dirno, $msg)\n"; # Get message (file) size $fsize{$msg} = (stat("${queue}mess/$msg"))[7]; # Read something from message header (sender, receiver, subject, date) open (MSG, "${queue}mess/$msg"); while () { 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 ( $_ =~ /^Cc: /) { $cc{$msg} = $'; chop ($cc{$msg}); } elsif ( $_ eq "\n") { last; } } close(MSG); defined($ret{$msg}) and print " ${cmsg}Return-path${cend}: $ret{$msg}\n"; defined($from{$msg}) and print " ${cmsg}From${cend}: $from{$msg}\n"; defined($to{$msg}) and print " ${cmsg}To${cend}: $to{$msg}\n"; defined($cc{$msg}) and print " ${cmsg}Cc${cend}: $cc{$msg}\n"; defined($subj{$msg}) and print " ${cmsg}Subject${cend}: $subj{$msg}\n"; defined($date{$msg}) and print " ${cmsg}Date${cend}: $date{$msg}\n"; defined($fsize{$msg}) and print " ${cmsg}Size${cend}: $fsize{$msg} bytes\n\n"; } # 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 { my ($q) = shift; # if ($summary == 0) { # for my $msg(keys %msglist) { # } # } for my $msg (keys %msglist) { if ($summary == 0) { if ($q eq 'L') { if ($msglist{$msg}{'local'}) { showMessageInfo($msg); } } if ($q eq 'R') { if ($msglist{$msg}{'remote'}) { showMessageInfo($msg); } } if ($q eq 'A') { if ($msglist{$msg}{'local'}) { showMessageInfo($msg); } if ($msglist{$msg}{'remote'}) { showMessageInfo($msg); } } } ## end if ($summary == 0) } ## end foreach my $msg (@msglist) Stats(); } # View a message in the queue sub ViewMsg { my ($rmsg) = shift; unless ($rmsg =~ /^\d+$/) { print "$rmsg is not a valid message number!\n"; } else { # Search message my ($ok) = 0; for my $msg(keys %msglist) { if ($msg =~ /\/$rmsg$/) { $ok = 1; print "\n --------------\nMESSAGE NUMBER $rmsg \n --------------\n"; open (MSG, "${queue}mess/$msg"); while () { 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 TrashMsgs { my @todelete = (); my $dirno; my $msgno; my $grouped = 0; my $deleted = 0; foreach my $msg (@todel) { $grouped++; $deleted++; ($dirno, $msgno) = split(/\//, $msg); if ($msglist{$msg}{'bounce'}) { push @todelete, "${queue}bounce/$msgno"; } push @todelete, "${queue}mess/$msg"; push @todelete, "${queue}info/$msg"; if ($msglist{$msg}{'remote'}) { push @todelete, "${queue}remote/$msg"; } if ($msglist{$msg}{'local'}) { push @todelete, "${queue}local/$msg"; } if ($msglist{$msg}{'todo'}) { push @todelete, "${queue}todo/$msglist{$msg}{'todo'}"; push @todelete, "${queue}intd/$msglist{$msg}{'todo'}"; } if ($grouped == 11) { unlink @todelete; @todelete = (); $grouped = 0; } } if ($grouped != 0) { unlink @todelete; } print "Deleted $deleted messages from queue\n"; } sub FlagMsgs { my $now = time; my @flagqueue = (); my $flagged = 0; foreach my $msg (@toflag) { push @flagqueue, "${queue}info/$msg"; $flagged++; if ($flagged == 30) { utime $now, $now, @flagqueue; $flagged = 0; @flagqueue = (); } } if ($flagged != 0) { utime $now, $now, @flagqueue; } } # Delete a message in the queue sub DelMsg { my ($rmsg) = shift; unless ($rmsg =~ /^\d+$/) { print "$rmsg is not a valid message number!\n"; } else { # Search message my ($ok) = 0; for my $msg(keys %msglist) { if ($msg =~ /\/$rmsg$/) { $ok = 1; $dmes = 1; push @todel, $msg; print "Deleting message $rmsg...\n"; last; } } # If the message isn't found, print a notice if ($ok == 0) { print "Message $rmsg not found in the queue!\n"; } if ($dmes == 1) { if ($dactions == 1) { TrashMsgs(); } else { $dactions--; } } } } sub DelMsgFromSender { my $badsender = shift; my $dirno; my $msgno; my $sender; print "Looking for messages from $badsender\n"; my ($ok) = 0; for my $msg (keys %msglist) { if ($msglist{$msg}{'sender'}) { $sender = getSender($msg); if ($sender eq $badsender) { $ok = 1; $dmes = 1; ($dirno, $msgno) = split(/\//, $msg); print "Message $msgno slotted for deletion\n"; push @todel, $msg; } } } # If no messages are found, print a notice if ($ok == 0) { print "No messages from $badsender found in the queue!\n"; } if ($dmes == 1) { if ($dactions == 1) { TrashMsgs(); } else { $dactions--; } } } sub DelMsgFromSenderR { my $badsender = shift; my $dirno; my $msgno; my $sender; print "Looking for messages from senders matching $badsender\n"; my ($ok) = 0; for my $msg (keys %msglist) { if ($msglist{$msg}{'sender'}) { $sender = getSender($msg); if ($sender =~ /$badsender/) { $ok = 1; $dmes = 1; ($dirno, $msgno) = split(/\//, $msg); print "Message $msgno slotted for deletion\n"; push @todel, $msg; } } } # If no messages are found, print a notice if ($ok == 0) { print "No messages from senders matching $badsender found in the queue!\n"; } if ($dmes == 1) { if ($dactions == 1) { TrashMsgs(); } else { $dactions--; } } } sub DelMsgHeaderR { my $case = shift; my $re = shift; my $dirno; my $msgno; print "Looking for messages with headers matching $re\n"; my ($ok) = 0; for my $msg (keys %msglist) { open (MSG, "${queue}mess/$msg") or die("cannot open message $msg! Is qmail-send running?\n"); while () { if ($case eq 'C') { if ($_ =~ /$re/) { $ok = 1; $dmes = 1; ($dirno, $msgno) = split(/\//, $msg); print "Message $msgno slotted for deletion.\n"; push @todel, $msg; last; } elsif ( $_ eq "\n") { last; } } else { if ($_ =~ /$re/i) { $ok = 1; $dmes = 1; ($dirno, $msgno) = split(/\//, $msg); print "Message $msgno slotted for deletion.\n"; push @todel, $msg; last; } elsif ( $_ eq "\n") { last; } } } close (MSG); } # If no messages are found, print a notice if ($ok == 0) { print "No messages with headers matching $re found in the queue!\n"; } if ($dmes == 1) { if ($dactions == 1) { TrashMsgs(); } else { $dactions--; } } } sub DelMsgBodyR { my $case = shift; my $re = shift; my $dirno; my $msgno; my $nomoreheaders = 0; print "Looking for messages with body matching $re\n"; my ($ok) = 0; for my $msg (keys %msglist) { open (MSG, "${queue}mess/$msg") or die("cannot open message $msg! Is qmail-send running?\n"); while () { if ($nomoreheaders == 1) { if ($case eq 'C') { if ($_ =~ /$re/) { $ok = 1; $dmes = 1; ($dirno, $msgno) = split(/\//, $msg); print "Message $msgno slotted for deletion.\n"; push @todel, $msg; last; } } else { if ($_ =~ /$re/i) { $ok = 1; $dmes = 1; ($dirno, $msgno) = split(/\//, $msg); print "Message $msgno slotted for deletion.\n"; push @todel, $msg; last; } } } else { if ($_ eq "\n") { $nomoreheaders = 1; } } } close (MSG); $nomoreheaders = 0; } # If no messages are found, print a notice if ($ok == 0) { print "No messages with body matching $re found in the queue!\n"; } if ($dmes == 1) { if ($dactions == 1) { TrashMsgs(); } else { $dactions--; } } } sub DelMsgSubj { my $subject = shift; my $msgsub; my $dirno; my $msgno; print "Looking for messages with Subject: $subject\n"; # Search messages my ($ok) = 0; for my $msg (keys %msglist) { ($dirno, $msgno) = split(/\//, $msg); $msgsub = getSubject($msg); if ($msgsub and $msgsub =~ /$subject/) { $ok = 1; $dmes = 1; print "Deleting message: $msgno\n"; push @todel, $msg; } } # If no messages are found, print a notice if ($ok == 0) { print "No messages matching Subject \"$subject\" found in the queue!\n"; } if ($dmes == 1) { if ($dactions == 1) { TrashMsgs(); } else { $dactions--; } } } # Delete all messages in the queue (thanks Kasper Holtze) sub DelAll { # Search messages my ($ok) = 0; my ($dirno, $msgno); for my $msg (keys %msglist) { $ok = 1; $dmes = 1; ($dirno, $msgno) = split(/\//, $msg); print "Message $msgno slotted for deletion!\n"; push @todel, $msg; } # If no messages are found, print a notice if ($ok == 0) { print "No messages found in the queue!\n"; } if ($dmes == 1) { if ($dactions == 1) { TrashMsgs(); } else { $dactions--; } } } sub FlagRemote { my $re = shift; my $dirno; my $msgno; my $recipients; print "Looking for messages with recipients in $re\n"; my ($ok) = 0; for my $msg (keys %msglist) { if ($msglist{$msg}{'remote'}) { open (MSG, "${queue}remote/$msg") or die("cannot open remote file for message $msg! Is qmail-send running?\n"); $recipients = ; chop($recipients); close (MSG); if ($recipients =~ $re) { $ok = 1; push @toflag, $msg; print "Message $msg being tagged for earlier retry (and lengthened stay in queue)!\n" } } } # If no messages are found, print a notice if ($ok == 0) { print "No messages with recipients in $re found in the queue!\n"; } else { FlagMsgs(); } } # Make statistics sub Stats { my ($total) = 0; my ($l) = 0; my ($r) = 0; my ($b) = 0; my ($t) = 0; foreach my $msg(keys %msglist) { $total++; if ($msglist{$msg}{'local'} ) { $l++; } if ($msglist{$msg}{'remote'} ) { $r++; } if ($msglist{$msg}{'bounce'} ) { $b++; } if ($msglist{$msg}{'todo'} ) { $t++; } } print "${cstat}Total messages${cend}: $total\n"; print "${cstat}Messages with local recipients${cend}: $l\n"; print "${cstat}Messages with remote recipients${cend}: $r\n"; print "${cstat}Messages with bounces${cend}: $b\n"; print "${cstat}Messages in preprocess${cend}: $t\n"; } # Retrieve pid of qmail-send sub qmailPid { my $qmpid = `$pidcmd`; chomp ($qmpid); $qmpid =~ s/\s*//g; if ($qmpid =~ /^\d+$/) { return $qmpid; } return 0; } # Print help sub Usage { print "qmHandle v$version\n"; print "Copyright 1998-2003 Michele Beltrame\n\n"; print "Available parameters:\n"; print " -a : try to send queued messages now (qmail must be running)\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 " -mN : display message number N\n"; print " -dN : delete message number N\n"; print " -fsender : delete message from sender\n"; print " -f're' : delete message from senders matching regular expression re\n"; print " -Stext : delete all messages that have/contain text as Subject\n"; print " -h're' : delete all messages with headers matching regular expression re (case insensitive)\n"; print " -b're' : delete all messages with body matching regular expression re (case insensitive)\n"; print " -H're' : delete all messages with headers matching regular expression re (case sensitive)\n"; print " -B're' : delete all messages with body matching regular expression re (case sensitive)\n"; print " -t're' : flag messages with recipients in regular expression 're' for earlier retry (note: this lengthens the time message can stay in queue)\n"; print " -D : delete all messages in the queue (local and remote)\n"; print " -V : print program version\n"; print "\n"; print "Additional (optional) parameters:\n"; print " -c : display colored output\n"; print " -N : list message numbers only\n"; print " (to be used either with -l, -L or -R)\n"; print "\n"; print "You can view/delete multiple message i.e. -d123 -v456 -d567\n\n"; exit; } # Print help sub Version { print "qmHandle v$version\n"; } qmhandle-1.3/HISTORY0000664000077600007760000001002310645045726011177 0ustar qmHandle history (c) Michele Beltrame -------------------- 1.3.2 by Chan Chung Hang Christopher * Printing message no: was code not tested prior to 1.3.1 release...perl compilation errors. Fixed. 1.3.1 by Chan Chung Hang Christopher * Reworked qmhandle left out printing message no: when detailed listing of messages is requested! Fixed. 1.3.0 by Chan Chung Hang Christopher * Reworked qmhandle to be more accurate in reporting queue information (todo state, bouncing...) * Reworked qmhandle to be more efficient in handling message deletion when more than one message will be deleted * Added big-todo support (required since todo files need to be handled) * Added delete from sender support (both regular expression and string matching) * Added touch info file for messages to remote domain for earlier retry (at the cost of longer queue life) * Added delete if message header or body line matches regular expression (case sensitive and insensitive matching) 1.2.3 * Fix: queue display transpose bug 1.2.2 * Fix: added deletion routines to handle files in bounce subdirectory * Fix: added whitespace remove line for pidof output reported by Charlies (cng-oz) 1.2.1 * Corrested an error in the README, and on in the HISTORY 1.2.0 (December 11, 2003) * CHANGED SWITCH NAME: "-m" is now used to view messages (no more "-v") * Added "-V" switch to print program version * Added switch to delete messages based on subject [thanks Arne Bernin] * Included GPL licence in the distribution * Now qmail is stopped only once for multiple deletions of messages, which makes things a bit faster * Corrected a bug which might have caused wrong messages to be deleted * Corrected several minor bugs 1.1.1 (July 10, 2003) * Corrected a bug which caused the -a switch not not work. 1.1.0 (June 4, 2003) * First release as a Sourceforge.Net community project... development resumes!!! * Added -a option to immediately send queued messages. 1.0.0 (December 17, 2001) * Made several functional and stylish adjustments to the code. [Thanks Mike Marseglia] * Much better handling of start/stop: qmHandle now can use system scripts or DBJ daemontools if they are available. Also, it won't restart qmail if it wasn't running when qmHandle was called. [Thanks Philippe Gay] * Updated the documentation. * Finally named it version 1.0.0!!! Seems pretty stable, well I hope it is. ;-) 0.5.1 (July 23, 2001) * Added a -D option which deletes al message in both local and remote queue. [Thanks Kasper Holtze] * Fixed a bug with the CC field when displaying message list. [Thanks anonymous qmHandle user] 0.5.0 (May 11, 2001) * Added syntax check on message numbers passed to -v and -d, so that qmHandle does not stop qmail or lookup messages if the argument is not valid. [Thanks Bertu Barnard] * Formatted the code in a more "Perlish" way. * Added display of "Cc" fields in message list (-l). * Empty fields in message list -l are not shown anymore. 0.4.1 (October 22, 1999) [Thanks Franky Van Liedekerke]: * Fixed a bug that caused messages in queue subdir "0" not to be displayed. 0.4.0 (February 2, 1999) [Thanks Rob]: * Added multiple paramters and actions support. * Added a more condensed queue display option. * The program now show statistics also when listing queues. * Added $pidcmd configuration variable, which allows to customize the command used to get qmail process id (needed when deleting messages). 0.3.0 (October 25, 1998): * Fixed to support qmail 1.03. If you're using an older version, be sure to change the $qmcmd variable if using previous version. * Now when listing messages also message size is displayed. Thanks to Jodok Sutterluety. 0.2.0 (May 18, 1998): * Fixed (with Rob help) a major problem in message deletion: qmHandle now terminates qmail before deleting a message, and restarts it after doing it. * Improved documentation in README file. * Changed executable file name from qmHandle.pl to qmHandle. 0.1.0 (March 10, 1998): * First release. qmhandle-1.3/GPL0000664000077600007760000004313110645045726010466 0ustar GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. qmhandle-1.3/debian/0000755000175000017500000000000011074504122012536 5ustar mltmltqmhandle-1.3/debian/compat0000644000175000017500000000000210623773163013750 0ustar mltmlt5 qmhandle-1.3/debian/dirs0000644000175000017500000000001010741770012013414 0ustar mltmltusr/bin qmhandle-1.3/debian/control0000644000175000017500000000067611007041076014152 0ustar mltmltSource: qmhandle Section: contrib/mail Priority: optional Maintainer: Marcela Tiznado Standards-Version: 3.7.3 Build-Depends: debhelper (>= 4.0.0) Package: qmhandle Architecture: all Depends: perl Description: tool to manage the qmail message queue qmHandle is a tool which can be used to manage the qmail message queue. It's written in Perl (so fully customizable) and has more features than qmail-qread and qmail-qstat. qmhandle-1.3/debian/changelog0000644000175000017500000000026511074504104014413 0ustar mltmltqmhandle (1.3.2-1) unstable; urgency=low * Initial release (Closes: #458976) * Added qmhandler manpage -- Marcela Tiznado Sun, 12 Oct 2008 20:28:29 -0300 qmhandle-1.3/debian/rules0000755000175000017500000000233611007056472013630 0ustar mltmlt#!/usr/bin/make -f # Sample debian/rules that uses debhelper. # GNU copyright 1997 to 1999 by Joey Hess. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 # This is the debhelper compatability version to use. build: build-stamp build-stamp: dh_testdir # Add here commands to compile the package. touch build-stamp clean: dh_testdir dh_testroot rm -f build-stamp # Add here commands to clean up after the build process. dh_clean install: build dh_testdir dh_testroot dh_clean -k dh_installdirs # Add here commands to install the package into debian/qmhandle. install -m755 qmHandle debian/qmhandle/usr/bin/ mv debian/qmhandle/usr/bin/qmHandle debian/qmhandle/usr/bin/qmhandle # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. # Build architecture-dependent files here. binary-arch: build install dh_testdir dh_testroot dh_installdocs dh_installexamples dh_installmenu dh_installman debian/qmhandle.1 dh_installchangelogs dh_link dh_strip dh_compress dh_fixperms dh_installdeb # dh_perl dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install qmhandle-1.3/debian/copyright0000644000175000017500000000055511007040177014477 0ustar mltmltThis package was debianized by Marcela Tiznado It was downloaded from http://sourceforge.net/projects/qmhandle Upstream Authors: Copyright 1998-2003 Michele Beltrame Modified by Chan Chung Hang Christopher (June, 2007) This software is distributed under the GNU General Public License, which can be found at /usr/share/common-licenses/GPL-2. qmhandle-1.3/debian/qmhandle.10000644000175000017500000000306611006751175014425 0ustar mltmlt.TH "Qmhandle" 1 .SH NAME qmhandle \- tool to manage the qmail message queue .SH SYNOPSIS .B qmhandle [--help] [--version] .SH DESCRIPTION qmHandle is a tool which can be used to manage the qmail message queue. It's written in Perl (so fully customizable) and has more features than qmail-qread and qmail-qstat. .RS .SH OPTIONS .TP \fB\-a\fR try to send queued messages now (qmail must be running) .TP \fB\-l\fR list message queues .TP \fB\-L\fR list local message queue .TP \fB\-R\fR list remote message queue .TP \fB\-s\fR show some statistics .TP \fB\-mN\fR display message number N .TP \fB\-dN\fR delete message number N .TP \fB\-fsender\fR delete message from sender .TP \fB\-f're\fR delete message from senders matching regular expression re .TP \fB\-Stext\fR delete all messages that have/contain text as Subject .TP \fB\-h're'\fR delete all messages with headers matching regular expression re (case insensitive) .TP \fB\-b're'\fR delete all messages with body matching regular expression re (case insensitive) .TP \fB\-H're'\fR delete all messages with headers matching regular expression re (case sensitive) .TP \fB\-B're'\fR delete all messages with body matching regular expression re (case sensitive) .TP \fB\-t're'\fR flag messages with recipients in regular expression 're' for earlier retry (note: this lengthens the time message can stay in queue) .TP \fB\-D\fR delete all messages in the queue (local and remote) .TP \fB\-V\fR print program version .TP \fB\-c\fR display colored output .TP \fB\-N\fR list message numbers only .SH AUTHORS Marcela Tiznado qmhandle-1.3/debian/docs0000644000175000017500000000002310741770137013417 0ustar mltmltGPL HISTORY README