Clamav scanner for qpsmtpd

Matts on 2002-10-18T13:34:08

Yesterday evening I installed Ask's qpsmtpd because I really really hated qmail-scanner-queue.pl (bad perl4 code, and horribly designed). The same evening I got most of a clamav plugin working. Today I got it working proper (and removed hundreds of lines of code in the process - I didn't realise that clamav had its own email parser in it, so I could discard all of that).

Anyway, if you want to stop (some) viruses at your gateway, here's the code (free software, blah blah - please put this in the distro if you like it, Ask):

#!/usr/bin/perl -w
# Clam-AV plugin.

use File::Temp qw(tempfile);

sub register { my ($self, $qp) = @_; $self->register_hook("data_post", "clam_scan"); }

sub clam_scan { my ($self, $transaction) = @_;

my ($temp_fh, $filename) = tempfile(); print $temp_fh $transaction->header->as_string; print $temp_fh "\n"; while (my $line = $transaction->body_getline) { print $temp_fh $line; } seek($temp_fh, 0, 0);

# Now do the actual scanning! my $cmd = "/usr/local/bin/clamscan --stdout -i --max-recursion=50 --disable-summary $ filename 2>&1"; $self->log(1, "Running: $cmd"); my $output = `$cmd`;

my $result = ($? >> 8); my $signal = ($? & 127);

unlink($filename); chomp($output);

$output =~ s/^.* (.*) FOUND$/$1 /mg;

$self->log(1, "clamscan results: $output");

if ($signal) { $self->log(1, "clamscan exited with signal: $signal"); return (DECLINED); } if ($result == 1) { $self->log(1, "Virus(es) found"); # return (DENY, "Virus Found: $output"); $transaction->header->add('X-Virus-Found', 'Yes'); $transaction->header->add('X-Virus-Details', $output); } elsif ($result) { $self->log(1, "ClamAV error: $result\n"); } $transaction->header->add('X-Virus-Checked', 'Checked'); return (DECLINED); }
Uncomment the "return (DENY,..)" if you never want those nasty viruses in your inbox (though I don't know how accurate clamav is, so you may want to be careful at first).


very cool!

ask on 2002-10-20T00:26:47


Great! :-) I was missing something like that. I will add it to the distribution.

I'll add a method in the transaction object so you can just get the filename of the spool file instead of having to copy it.

  - ask