Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The ClamAV Plugin

Wiki MarkupThis plugin submits the entire email to a locally running \[http://www.clamav.net/ Clam AntiVirus\] server for virus detection. If a virus is found, it returns a positive return code to indicate spam and sets the header "X-Spam-Virus: Yes ($virusname)".

Code

clamav.cf:

No Format
loadplugin ClamAV clamav.pm
full CLAMAV eval:check_clamav()
describe CLAMAV Clam AntiVirus detected a virus
score CLAMAV 10
add_header all Virus _CLAMAVRESULT_

clamav.pm:

No Format
package ClamAV;
use strict;

# version 2.0, 2010-01-07
#   - use SA public interface set_tag() and add_header, instead of
#     pushing a header field directly into $conf->{headers_spam}

# our $CLAMD_SOCK = 3310;               # for TCP-based usage
our $CLAMD_SOCK = "/var/run/clamd.basic/clamd.sock";   # change me

use Mail::SpamAssassin;
use Mail::SpamAssassin::Plugin;
use Mail::SpamAssassin::Logger;
use File::Scan::ClamAV;
our @ISA = qw(Mail::SpamAssassin::Plugin);

sub new {
  my ($class, $mailsa) = @_;
  $class = ref($class) || $class;
  my $self = $class->SUPER::new($mailsa);
  bless ($self, $class);
  $self->register_eval_rule ("check_clamav");
  return $self;
}

sub check_clamav {
  my ($self, $permsgstatus$pms, $fulltext) = @_;
  dbg("ClamAV: invoking File::Scan::ClamAV, port/socket: %s", $CLAMD_SOCK);
  my $clamav = new File::Scan::ClamAV(port => 3310$CLAMD_SOCK);
  my ($code, $virus) = $clamav->streamscan(${$fulltext});
  my $isspam = 0;
  my $header = "";
  if (!$code) {
    my $errstr = $clamav->errstr();
    Mail::SpamAssassin::Plugin::dbg("ClamAV: Error scanning: $errstr");
    $header = "Error ($errstr)";
  } elsif ($code eq 'OK') {
    Mail::SpamAssassin::Plugin::dbg("ClamAV: No virus detected");
    $header = "No";
  } elsif ($code eq 'FOUND') {
    Mail::SpamAssassin::Plugin::dbg("ClamAV: Detected virus: $virus");
    $header = "Yes ($virus)";
    $isspam = 1;
   } # elseinclude {
the virus name in Mail::SpamAssassin::Plugin::dbg("ClamAV: Error, unknown return code: $code");SpamAssassin's report
    $pms->test_log($virus);
  } else {
    $header = "Error (Unknown return code from ClamAV: $code)";
  }
  $permsgstatus->{main}->{conf}->{headers_spam}->{"Virus"} = $header;
  $permsgstatus->{main}->{conf}->{headers_ham}->{"Virus"} = $headerdbg("ClamAV: result - $header");
  $pms->set_tag('CLAMAVRESULT', $header);
  # add a metadatum so that rules can match against the result too
  $pms->{msg}->put_metadata('X-Spam-Virus',$header);
  return $isspam;
}

1;

How To Use It

...

First of all, you need to install \[http://www.clamav.net/ ClamAV\] and ensure that scanning a mail with *clamscan* works.unmigrated-wiki-markup

Second, you need to install the \[http://search.cpan.org/~cfaber/File-Scan-ClamAV/lib/File/Scan/ClamAV.pm File::Scan::ClamAV\] perl module.

Finally, save the two files above into the /etc/mail/spamassassin/ directory. You can adjust the default score of 10 in clamav.cf if you like. You should edit the clamav.pm file and change the setting for '$CLAMD_SOCK' to match where your ClamAV installation has put its named pipe.

Restart the spamd daemon if you're using that, and you should be all set.

If you'd like to sort virus emails to a separate folder, create a rule looking for the "X-Spam-Virus: Yes" header.

To get a different score based on virus type, see ClamAVMultipleScores.

Caveats

...

Some find this plugin very useful. However \[http://bugzilla.spamassassin.org/show_bug.cgi?id=2408 others do have a different opinion\] of the safety or logic of such a plugin that you should probably read -- [AndrewFerrier]

actually, having a plugin that does this, rather than building support directly into the core, is exactly what the "others" in question preferred (wink). So this is good – JustinMason

Questions

ClamAV docs say to prefer using a local socket instead of a network socket. How would I change the plugin to use a local socket? – CameronBales

CategorySoftwareVery true (smile) I have to say my experiences with this plugin so far have been very promising, I can recommend it to anyone suffering from the increasingly blurred distinction between spam and viruses. – AndrewFerrier