[Techtalk] Procmail spam recipes (was simple mail filtering via
whitelist)
John Clarke
johnc+linuxchix at kirriwa.net
Tue Mar 9 18:06:39 EST 2004
On Mon, Mar 08, 2004 at 04:31:22PM -0800, Akkana Peck wrote:
> As long as we're discussing procmail filtering and spam: I've been
> googling for procmail recipes to block messages with attachments of
> certain types, or attachments with filenames that include patterns like
> .exe and .pif. I haven't had much luck. Most of my existing procmail
As it happens, I've done this. I wrote a simple and crude little perl
program to do the work (attached), and the procmail recipe is simply:
# check for nasty attachments - .pif, .scr, .exe
:0 W
| $HOME/bin/viruscheck.pl
I wrote this a long time ago and can't remember why I've commented out
the alternative version using MIME::Parser. I think it was because
MIME::Parser wasn't installed on the machine I wanted to run it on and
I couldn't install it at the time. It might have been because it
didn't work though, so be careful :-)
Or you could install amavis and have it do it for you.
Cheers,
John
--
"Introducing Voodoo, for MS-Windows programmers. You are already familiar
with the basic principles of placating unknown gods..."
-- Roger Burton West
-------------- next part --------------
#!/usr/bin/perl -w
#
# Expects a multipart message on STDIN. Checks for attachments named
# *.pif, *.scr, *.exe which are usually viruses. Returns 1 if no attachments
# with such names are found, 0 if one or more is found. This allows it to
# be run as a delivering recipe in .procmailrc - any virus will be discarded
# and legitimate mail will be delivered by rules which follow.
#
use strict;
my ($line, $nasty, $boundary);
sub parse_headers
{
my $content_header;
$content_header = "";
while (1)
{
if ($line =~ /^Content-(?:Type|Disposition):/)
{
chomp($content_header = $line);
}
elsif ($content_header and $line =~ /^\s/)
{
chomp($content_header .= $line);
}
else
{
$content_header = "";
}
$nasty = 1
if ($content_header =~ /(?:;|\s)(?:file)?name="[^"]+\.(?:pif|scr|exe)"/);
$boundary = "\Q$1\E"
if (!$boundary and $content_header =~ /(?:;|\s)boundary="([^"]+)"/);
$line = <STDIN>;
last if !defined($line);
chomp $line;
last if $line eq "";
}
}
sub parse_body
{
my $next_part;
$next_part = 0;
while (!$next_part)
{
$next_part = 1 if $line =~ /^--$boundary$/;
$line = <STDIN>;
last if !defined($line);
chomp $line;
}
}
$nasty = 0;
$boundary = "";
$line = <STDIN>;
chomp $line;
while ($line)
{
parse_headers();
last if $nasty;
parse_body();
last if $nasty;
}
# read the rest of the message and discard (stops 'broken pipe' errors)
while ($line = <STDIN>)
{
}
exit !$nasty;
#
# Alternate version using MIME::Parser. I can't remember why it's commented
# out - possibly because MIME::Parser wasn't available on the machine I
# wanted to run this on, but it could have been because it didn't work.
#
#use MIME::Parser;
#
##
#my ($parser, $entity, $part, $filename, $nasty, $IO, $line, $content_header);
#
#$nasty = 0;
#
## create the parser
#$parser = new MIME::Parser;
#
## tell it not to store files on disc
#$parser->output_to_core(1);
#
## and parse the input stream
#$entity = $parser->parse(\*STDIN) or die "parse failed\n";
#
## if not multipart then no attachment, so OK
#exit 0 if !$entity->is_multipart();
#
## now deal with each part
#foreach $part ($entity->parts)
#{
# # get the name of the attached file
#
# $filename = $part->head()->get('Content-Type');
#
# if (defined($filename) and $filename =~ /name=".*\.(?:pif|scr|exe)"/)
# {
# # is a nasty attachment
# $nasty = 1;
# last;
# }
#
# $filename = $part->head()->get('Content-Disposition');
#
# if (defined($filename) and $filename =~ /name=".*\.(?:pif|scr|exe)"/)
# {
# # is a nasty attachment
# $nasty = 1;
# last;
# }
#}
#
#exit $nasty;
More information about the Techtalk
mailing list