Mail::IspMailGate::Filter::VirScan - Scanning emails for Viruses


 # Create a filter object
 my($scanner) = Mail::IspMailGate::Filter::VirScan->new({});

 # Call it for filtering the MIME entity $entity and pass it a
 # Mail::IspMailGate::Parser object $parser
 my($result) = $scanner->doFilter({
     'entity' => $entity,
     'parser' => $parser
 if ($result) { die "Error: $result"; }


This class implements a Virus scanning email filter. It is derived from the abstract base class Mail::IspMailGate::Filter. For details of an abstract filter see Mail::IspMailGate::Filter.

The virus scanner class needs an external binary which has the ability to detect viruses in given files, like VirusX from What the module does is extracting files from the email and passing them to the scanner. Extracting includes dearchiving .zip files, .tar.gz files and other known archive types by using external dearchiving utilities like unzip, tar and gzip. Known extensions and dearchivers are configurable, so you can customize them for your own needs.


The virus scanner module depends on some items in the Mail::IspMailGate::Config module:


Path of the AntiVir binary, for example

  $cfg->{'antivir_path'} = '/usr/bin/antivir';

A template for calling the external virus scanner; example:

    $cfg->{'virscan'}->{'scanner'} =
        '$antivir_path -rs -nolnk -noboot $ipaths';

The template must include either of the variable names $ipath or $ipaths; the former must be used, if the virus scanner cannot accept more than one file name with one call. Note the use of single quotes which prevent expanding the variable name!

Additionally the pattern $antivir_path may be used for the path to the antivir binary.


This is an array ref of known archive deflaters. Each element of the array is a hash ref with the attributes cmd, a template for calling the dearchiver and pattern, a Perl regular expression for detecting file names which refer to archives that this program might extract. An example which configures the use of unzip, tar and gzip:

    $cfg->{'virscan'}->{'deflater'} =
        [ { pattern => '\\.(tgz|tar\\.gz|tar\\.[zZ])$',
            cmd => '$gzip_path -cd $ipath | /bin/tar -xf -C $odir'
          { pattern => '\\.tar$',
            cmd => '$tar_path -xf -C $odir'
          { pattern => '\\.(gz|[zZ])$',
            cmd => '$gzip_path -cd $ipath >$opath'
          { pattern => '\\.zip$',
            cmd => '$unzip_path $ifile -d $odir'

Again, note the use of single quotes to prevent variable expansion and double backslashes for passing a single backslash in the Perl regular expressions. See perlre for details of regular expressions.

The command template can use the following variables:


Full filename of the archive being deflated


Directory and file name portion of the archive


Directory where the archive must be extracted to; if your dearchiver doesn't support an option --directory or something similar, you need to create a subshell. For example the following might be used for an LhA deflater:

    { 'pattern' => '\\.(lha|lzx)',
       'cmd' => '(cd $odir; lha x $ipath)'

Same as $ifile and $odir/$ofile; for example gzip needs this, when it runs as a standalone deflater and not as a backend of tar.


These are the paths of the corresponding binaries and read from $cfg->{'gzip_path'}, $cfg->{'tar_path'} and so on.


checkFile $ATTR, $FILE

This function is called for every part of a MIME-message from within the filterFile method. It receives the arguments $ATTR (same as the $ATTR argument of filterFile) and $FILE, the filename where the MIME part is stored. If it detects $FILE to be an archive, it calls checkArchive for deflating it and building a list of files contained in the archive. If another archive is found, it calls checkArchive again.

Finally, after building a list of files, it calls the virus scanner. If the scanner can handle multiple files, a single call occurs, otherwise the scanner will be called for any file. See CONFIGURATION above.

checkArchive $ATTR, $IPATH, $DEFLATER

This function is called from within checkFile to extract the archive $IPATH by using the $DEFLATER->{'cmd'} ($DEFLATER is an element from the deflater list). The $ATTR argument is the same as in checkFile.

The function creates a new temporary directory and extracts the archive contents into that directory. Finally it returns a list of files that have been extracted.

  $hasVirus = $self->HasVirus($OUTPUT)

(Instance method) This method takes the string $OUTPUT, which is a message emitted by the virus scanner and parses it for possible virus warnings. The method returns TRUE, if such warnings are detected or FALSE otherwise.

The default implementation knows about the output of the AntiVir virus scanner. To use the filter with other virus scanners, you typically dervice a subclass from it which overrides this method.


ispMailGate, Mail::IspMailGate::Filter