Quickly filter mail using Qmail's .qmail files

If you want to filter mail through an external program when mail reaches a mailbox, you can use a .qmail file like this:

|/var/qmail/bin/preline /fullpath/filter.pl joe@bloggs.co.uk
/home/mailusers/username/Maildir/

In the example above the preline command is used to pipe the contents of the message into our custom script (see the preline manpage for more info) with one argument (sender to block). The filter.pl script is run first and if it returns an exit code of "0" (success) then qmail will process the next line, which will deliver the mail in the users mailbox as normal.

The custom script can be any program that will run from the command line, with some requirements:

  • If you need to read the mail message it will need to read from STDIN.
  • If you want to access some qmail variables such as sender then you will need to access the environment variables of the program.
  • The return codes determines what happens to the message eg. 0 = process next .qmail line, 99 = drop etc..

Here is a quick perl program to drop any mail from the sender specified as the first argument

#!/usr/bin/perl -w
#.qmail filter on senders email address
use strict;
if($#ARGV == 0){        #need one command line argument = senders email address
   if(open(LOG, ">>/tmp/filter.log")){   #we need a log just incase this breaks and we can get any mail back
     print LOG "ARGV#########\n";
     foreach(@ARGV){print LOG "$_\n";}   #log all command line arguments
     print LOG "ENV##########\n";
     foreach (keys(%ENV)){print LOG "$_ = $ENV{$_}\n";}  #log all the environment variables
     print LOG "STDIN########\n";
     while(<STDIN>){print LOG $_;}       #log the actual message
     close(LOG);
   }
   if($ENV{'SENDER'} eq $ARGV[0]){exit(99);}     #dont save this message to the users mailbox
}
else{print "Usage: $0 <senders email address>\n";}      #print usage info
exit(0);        #message ok

Last updated: 11/04/2005