McAfee uvscan 6.0.0 - patches provided

Randal, Phil prandal at herefordshire.gov.uk
Wed Apr 21 10:45:39 IST 2010


There was one minor bug which resulted in incomplete reporting of some
phishing emails, e.g.

   Report: McAfee6: ./o3GA2bRn018830.message

with no virus name included.

A patch which fixes it follows:

[root at mx0 ~]# diff -Naur SweepViruses.pm.old SweepViruses.pm
--- SweepViruses.pm.old 2010-04-16 14:09:50.000000000 +0100
+++ SweepViruses.pm     2010-04-16 14:33:59.000000000 +0100
@@ -1913,6 +1913,15 @@
   $logout =~ s/\s{20,}/ /g;
   # note: '$dot' does become '.'
   ($dot, $id, $part, @rest) = split(/\//, $filename);
+
+  # Infections found in the header must be handled specially here  if 
+ ($id =~ /\.(?:header|message)/) {
+    # The attachment name is "" ==> infection is whole messsage
+      $part = "";
+    # Correct the message id by deleting all from .header onwards
+      $id =~ s/\.(?:header|message).*$//;  }
+
   my $notype = substr($part,1);
   $logout =~ s/\Q$part\E/$notype/;
   $report =~ s/\Q$part\E/$notype/;
@@ -1921,13 +1930,6 @@

   $report = $Name . ': ' . $report if $Name;

-  # Infections found in the header must be handled specially here
-  if ($id =~ /\.(?:header|message)/) {
-    # The attachment name is "" ==> infection is whole messsage
-    $part = "";
-    # Correct the message id by deleting all from .header onwards
-    $id =~ s/\.(?:header|message).*$//;
-  }
   $infections->{"$id"}{"$part"} .= $report . "\n";
   $types->{"$id"}{"$part"} .= "v";
   return 1;

Cheers,

Phil 

--
Phil Randal | Networks Engineer
NHS Herefordshire & Herefordshire Council  | Deputy Chief Executive's
Office | I.C.T. Services Division
Thorn Office Centre, Rotherwas, Hereford, HR2 6JT
Tel: 01432 260160
email: prandal at herefordshire.gov.uk

Any opinion expressed in this e-mail or any attached files are those of
the individual and not necessarily those of Herefordshire Council.

This e-mail and any attached files are confidential and intended solely
for the use of the addressee. This communication may contain material
protected by law from being passed on. If you are not the intended
recipient and have received this e-mail in error, you are advised that
any use, dissemination, forwarding, printing or copying of this e-mail
is strictly prohibited. If you have received this e-mail in error please
contact the sender immediately and destroy all copies of it.

-----Original Message-----
From: mailscanner-bounces at lists.mailscanner.info
[mailto:mailscanner-bounces at lists.mailscanner.info] On Behalf Of Michael
Miller
Sent: 15 April 2010 10:51
To: mailscanner at lists.mailscanner.info
Subject: Re: McAfee uvscan 6.0.0 - patches provided

Hi,

Attached are a set of patches to add support for the McAfee uvscan
v6.0.0 command line scanner. The v5 and v4 versions of uvscan are no
longer receiving updates from McAfee and should be viewed as retired.
During the testing Phil and I noticed that uvscan sometimes outputs "...
Found " or "... Found: " when a virus is found - please be sure to test,
at a minimum, with an eicar signature to ensure your copy of uvscan v6
is parsed correctly.

I have updated the following files:
etc/virus.scanners.conf
lib/MailScanner/SweepViruses.pm
lib/mcafee-autoupdate
lib/mcafee-wrapper

I have added the following files:
lib/mcafee6-autoupdate
lib/mcafee6-wrapper

(Note that mcafee-autoupdate and mcafee6-autoupdate are identical, so
after patching mcafee-autoupdate, you need to copy the resulting file to
mcafee6-autoupdate)

Thanks to Phil Randal for testing and troubleshooting my initial
versions!

If the patches don't come through correctly, please let me know and I
can send as attachments.

Regards,
Mike

Patches against MailScanner-4.79.11-1 below:
########################################################################
#
# diff -u etc/virus.scanners.conf.47911 etc/virus.scanners.conf
--- etc/virus.scanners.conf.47911       2010-04-11 00:14:02.000000000
+0100
+++ etc/virus.scanners.conf     2010-04-15 10:36:18.000000000 +0100
@@ -37,6 +37,7 @@
 kaspersky      /opt/MailScanner/lib/kaspersky-wrapper  /opt/AVP
 kavdaemonclient        /opt/MailScanner/lib/kavdaemonclient-wrapper
/usr/local
 mcafee         /opt/MailScanner/lib/mcafee-wrapper
/usr/local/uvscan
+mcafee6                /opt/MailScanner/lib/mcafee6-wrapper   
/usr/local/uvscan
 # Now updated to handle nod32 2.01 and upwards
 #nod32-1.99    /opt/MailScanner/lib/nod32-wrapper      /usr/local/nod32
 nod32-1.99     /opt/MailScanner/lib/nod32-wrapper      /usr/sbin


# diff -u lib/MailScanner/SweepViruses.pm.47911
lib/MailScanner/SweepViruses.pm
--- lib/MailScanner/SweepViruses.pm.47911       2010-04-10
23:26:06.000000000 +0100
+++ lib/MailScanner/SweepViruses.pm     2010-04-13 16:14:52.000000000
+0100
@@ -127,6 +127,18 @@
     SupportScanning    => $S_SUPPORTED,
     SupportDisinfect   => $S_SUPPORTED,
   },
+  mcafee6              => {
+    Name               => 'McAfee6',
+    Lock               => 'mcafee6Busy.lock',
+    CommonOptions      => '--recursive --ignore-links --analyze --mime
' .
+                           '--secure --noboot',
+    DisinfectOptions   => '--clean',
+    ScanOptions                => '',
+    InitParser         => \&InitMcAfee6Parser,
+    ProcessOutput      => \&ProcessMcAfee6Output,
+    SupportScanning    => $S_SUPPORTED,
+    SupportDisinfect   => $S_SUPPORTED,
+  },
   command              => {
     Name               => 'Command',
     Lock               => 'commandBusy.lock',
@@ -1379,6 +1391,11 @@
   $currentline = '';
 }

+# Initialise any state variables the McAfee6 output parser uses sub 
+InitMcAfee6Parser {
+  ;
+}
+
 # Initialise any state variables the Command (CSAV) output parser uses
sub InitCommandParser {
   ;
@@ -1837,7 +1854,7 @@
   $logout = $report;
   $logout =~ s/%/%%/g;
   $logout =~ s/\s{20,}/ /g;
-  # note: '$dot' does not become '.'
+  # note: '$dot' does not become '.', but blank for rootdir
   ($dot, $id, $part, @rest) = split(/\//, $lastline);
   my $notype = substr($part,1);
   $logout =~ s/\Q$part\E/$notype/;
@@ -1858,6 +1875,64 @@
   return 1;
 }

+sub ProcessMcAfee6Output {
+  my($line, $infections, $types, $BaseDir, $Name) = @_;
+
+  my($report, $dot, $id, $part, @rest);  my($logout);  my($filename, 
+ $virusname);
+
+  chomp $line;
+
+  #MailScanner::Log::InfoLog("McAfee6 said \"$line\"");
+
+  # Should we worry about any warnings/errors?
+  return 0 unless $line =~ /Found/;
+
+  # McAfee prints the whole path including  # ./message/part so make it

+ the same  # eg: 
+ /var/spool/MailScanner/incoming/4118/./o3B07pUD004176/eicar.com
+  #
+  # strip off leading BaseDir
+  $line =~ s/^$BaseDir//;
+  # and then remaining /. (which may be removed in future as per v5 
+ uvscan)  $line =~ s/^\/\.//;  # and put the leading . back in place  
+ $line =~ s/^/\./;
+
+  $filename = $line;
+  $filename =~ s/ \.\.\. Found.*$//;
+
+  #get the virus name - not used currently  #$virusname = $line;  
+ #$virusname =~ s/^.* \.\.\. Found.?//;
+
+  $report = $line;
+  $logout = $line;
+  $logout =~ s/%/%%/g;
+  $logout =~ s/\s{20,}/ /g;
+  # note: '$dot' does become '.'
+  ($dot, $id, $part, @rest) = split(/\//, $filename);  my $notype = 
+ substr($part,1);  $logout =~ s/\Q$part\E/$notype/;  $report =~ 
+ s/\Q$part\E/$notype/;  $report =~ s/ \.\.\. Found/ Found/;  
+ MailScanner::Log::InfoLog($logout);
+
+  $report = $Name . ': ' . $report if $Name;
+
+  # Infections found in the header must be handled specially here
+  if ($id =~ /\.(?:header|message)/) {
+    # The attachment name is "" ==> infection is whole messsage
+    $part = "";
+    # Correct the message id by deleting all from .header onwards
+    $id =~ s/\.(?:header|message).*$//;
+  }
+  $infections->{"$id"}{"$part"} .= $report . "\n";
+  $types->{"$id"}{"$part"} .= "v";
+  return 1;
+}
+
 # This next function originally contributed in its entirety by  #
"Richard Brookhuis" <brookhuis at busschers.nl>  #



########################################################################
#
# diff -u lib/mcafee-autoupdate.47911 lib/mcafee-autoupdate
--- lib/mcafee-autoupdate.47911 2010-04-10 20:02:56.000000000 +0100
+++ lib/mcafee-autoupdate       2010-04-15 10:19:51.000000000 +0100
@@ -2,7 +2,15 @@
 #
 # Update the McAfee data files.
 #
+# As at 2010/04/10 the mcafee6-autoupdate and mcafee6-autoupdate 
+scripts # are identical. The logic to differentiate between versions is

+built in # to the script to enable only one version of the script to be
maintained.
+#
+# based on:
+#
 # $Cambridge: hermes/conf/build/bin/uvscan-update,v 1.52 2004/08/18
19:12:02 fanf2 Exp $
+# and patch from:
+#
http://lists.mailscanner.info/pipermail/mailscanner/2009-November/094019
.html

 # $PREFIX is the directory where the uvscan binary is (NOT a symlink to
# the binary), which is where it looks for its dat files. You may run @@
-17,13 +25,36 @@  # the subdirectory via a current link. The current
link is updated  # without locking on the assumption that this is
sufficiently unlikely  # to cause a problem.
+#
+
+# As of Apr 2010, McAfee is no longer publishing V1 DATs, and is only #

+publishing V2 DATs:
+#
+#   https://kc.mcafee.com/corporate/index?page=content&id=KB60404
+#   https://kc.mcafee.com/corporate/index?page=content&id=KB60772
+#
+# Version 6 of McAfee VirusScan Command Line Scanner for Unix uses V2
DATs.
+# Version 5, which uses V1 DATs, is EoL and no longer receives DAT
updates.
+#
+# If this script detects taht we are running VirusScan CLI version 6, 
+we # extract the DATs from the V2 DAT zip archive (avvdat-XXXX.zip).
+# Otherwise, we log an error about EoL scanner and no available
updates.
+#
+# As V1 DATs are no longer published, support for them has been removed

+# from this update script.

 # defaults
 OPTS="-d"
 PREFIX=/opt/uvscan
-FTPDIR=http://download.nai.com/products/datfiles/4.x/nai
+FTPDIR=http://update.nai.com/products/commonupdater
 RETRIES=1
 INTERVAL=300
+CLIVERSION=6
+
+wgetverbosity="--no-verbose"
+tarverbosity=""
+unzipverbosity="-q"
+unzipopts="-o"

 # handle the command line
 usage () {
@@ -61,7 +92,7 @@
                ;;
         /*)     PREFIX=$arg
                 ;;
-        http:)  ftp_proxy=$arg
+        http://*)  ftp_proxy=$arg
                 http_proxy=$arg
                 export ftp_proxy
                 export http_proxy
@@ -90,20 +121,32 @@
 option v VERBOSE
 case $FORCE in
 yes)    VERBOSE=yes
+       wgetverbosity=""
+       tarverbosity="v"
+       unzipverbosity=""
 esac

-# look for binaries and libraris in plausible places
+# look for binaries and libraries in plausible places
 PATH=$PREFIX:/usr/local/bin:/usr/bin:/bin
 # this is only necessary for broken setups  LD_LIBRARY_PATH=$PREFIX
export PATH LD_LIBRARY_PATH

+#setup sane umask, just in case...
+umask 022
+
 # where this script finds things
 DATDIR=$PREFIX/datfiles
-DATFILES="clean.dat extra.dat internet.dat names.dat scan.dat"
+
+# These are for CLI v6+:
+# Note that runtime.dat is not distributed; it is generated by uvscan 
+the # first time it runs (including with "uvscan --version").
+DATFILES6="avvclean.dat avvnames.dat avvscan.dat runtime.dat extra.dat"
+
 LINKNAME=current
 LINKREL=datfiles/$LINKNAME

+
 # wrapper functions for echo etc.
 timestamp () {
         case $TIME in
@@ -143,7 +186,11 @@
 say PREFIX=$PREFIX

 # check directory setup is correct
-for link in $LINKREL $DATFILES
+# At this point we do not know whether this is a CLI version 6 or 
+version 5 # installation, and more particularly what the filenames for 
+the DAT files # are.
+#for link in $LINKREL $DATFILES
+for link in $LINKREL
 do
         if ! is -h $PREFIX/$link
         then
@@ -181,12 +228,59 @@
         run rm -f $out $err
 }

+#this parses an ini file for the occurence of a value in the specified
section
+#parseini INIFILE SECTION ITEM
+parseini () {
+  myINIFILE="$1"
+  mySECTION="$2"
+  myITEM="$3"
+  if [ ! -s "${myINIFILE}" ]
+  then
+    echo "UNKNOWN"
+    return 1
+  fi
+
+  myINSEC="no"
+  while read line
+  do
+    #just incase input is in DOS format... (Is the case for avvdat.ini)
+    line="`echo $line|sed 's/\r//'`"
+
+    if [ "${line}" = "[${mySECTION}]" ]
+    then
+      myINSEC="yes"
+      continue
+    fi
+    if [ "`echo ${line}|cut -c1`"  = "[" ]
+    then
+      myINSEC="no"
+      continue
+    fi
+    [ "${myINSEC}" = "yes" ] || continue
+    if [ "`echo ${line}|cut -d= -f1`" = "${myITEM}" ]
+    then
+      echo "`echo ${line}|sed 's/^'"${myITEM}="'//'`"
+      return 0
+    fi
+  done < ${myINIFILE}
+  echo "UNKNOWN"
+  return 1
+}
+
 # work out latest dat version
 try=$RETRIES
 while :
-do      getver "wget --tries=$try --waitretry=$INTERVAL --passive-ftp
$FTPDIR/update.ini" update.ini "DATVersion="
-        VERSION=$VER
-        case $VERSION in
+do
+        rm -f avvdat.ini
+        if is $? != 0
+        then
+          say "Error deleting avvdat.init... update may not be
successful."
+        fi
+
+        run wget --tries=$try --waitretry=$INTERVAL --passive-ftp
$FTPDIR/avvdat.ini
+       NEWVER=`parseini avvdat.ini AVV-ZIP DATVersion` say New version 
+is $NEWVER
+        case $NEWVER in
         UNKNOWN)
                 if ! try=`expr $try - 1`
                 then break
@@ -201,40 +295,75 @@
 done

 # work out installed dat version
-getver "uvscan --version" version.err "Virus data file v"
+# CLI v5 is EoL so no point in checking for it first, # as no one 
+should still be using it getver "uvscan --version" version.err "Dat set

+version: "
+if is $VER = UNKNOWN
+then
+       # Might be CLI pre-v6:
+       getver "uvscan --version" version.err "Virus data file v"
+        if is $VER != UNKNOWN
+        then
+          VERBOSE=yes
+         say "uvscan earlier than v6 found. No DATs available.
ABORTING."
+          say "Please upgrade uvscan to at least v6.0.0"
+          if is $VER != 5937
+          then
+            say ""
+            say "You are not running the last released v1 DAT."
+            say "Please manually upgrade to DAT v5937 if possible."
+          fi
+          run exit 1
+        fi
+fi
 PREVIOUS=$VER

 case $FORCE in
 yes)    say Forced update from $PREVIOUS
         PREVIOUS=0000
         ;;
-*)      if is $VERSION -eq $PREVIOUS
-        then    say Already have $VERSION
+*)      if is $NEWVER -eq $PREVIOUS
+        then    say Already have $NEWVER
                 run exit 0
         fi
 esac

+# select appropriate archive name and DAT filenames # if this is CLI 
+v6, we use V2 DAT archive if is $CLIVERSION = 6 then
+        DISTARC=avvdat-$NEWVER.zip
+        DATFILES="$DATFILES6"
+else
+        say "Fatal Error. Unsupported CLI version found..."
+        exit 1
+fi
+
 VERBOSE=yes

+# We are performing an update, so be chatty (as opposed to explicitly #

+verbose as requested) CHATTY=yes
+
 say Installed dat file is $PREVIOUS
-say Latest dat file is $VERSION
+say Latest dat file is $NEWVER

-if is $VERSION = UNKNOWN
+if is $NEWVER = UNKNOWN
 then    say Problem with McAfee datfile update from $FTPDIR
         run exit 1
-elif is $VERSION -lt $PREVIOUS
+elif is $NEWVER -lt $PREVIOUS
 then    say Remote version $VERSION older than installed version
$PREVIOUS
         run exit 1
-elif is -d $VERSION
-then    say Cleaning away $VERSION directory
-        run rm -rf $VERSION
+elif is -d $NEWVER
+then    say Cleaning away $NEWVER directory
+        run rm -rf $NEWVER
 fi

 retry () {
         echo "$OUT"
         say Fetch or test failed -- removing bad McAfee data files
         run cd $DATDIR
-        run rm -rf $VERSION
+        run rm -rf $NEWVER
         if ! try=`expr $try - 1`
         then    say Giving up
                 run exit 1
@@ -248,19 +377,25 @@
 while :
 do
         # fetch and extract dat files
-        TARFILE=dat-$VERSION.tar
-        run mkdir $VERSION
-        run cd $VERSION
+        run mkdir $NEWVER
+        run cd $NEWVER
         run chmod 700 .
-        if ! run wget --tries=$try --waitretry=$INTERVAL --passive-ftp
--progress=dot:mega $FTPDIR/$TARFILE
+        if ! run wget $wgetverbosity --tries=$try --waitretry=$INTERVAL
--passive-ftp --progress=dot:mega $FTPDIR/$DISTARC
         then retry
         fi
-        run tar xvf $TARFILE
+       if is ! $CLIVERSION 6
+       then
+               run tar x${tarverbosity}f $DISTARC
+       else
+               run unzip $unzipverbosity $unzipopts $DISTARC
+       fi
         run chmod 644 *
         run chmod 755 .

         # verify the contents
-        CMD="uvscan --version --dat ."
+       # this will create runtime.dat too
+        # we use --decompress to speed up future runs...
+        CMD="uvscan --version --dat . --decompress"
         say "> $CMD"
         if ! OUT=`$CMD 2>&1`
         then    retry
@@ -280,21 +415,19 @@
                 s/^/# /;/@MM/s/$/ <--/' readme.txt  esac  # remove some
crap -run rm -f *.diz *.exe *.ini *.lst *.tar *.txt
+run rm -f *.diz *.exe *.ini *.lst *.tar *.txt *.zip

-# do remaining part of initial setup
-case $INIT in
-yes)    for file in $DATFILES
-        do
-                run rm -f $PREFIX/$file
-                run ln -s $LINKREL/$file $PREFIX/$file
-        done
-esac
+# Make sure symlinks are in place
+for file in $DATFILES
+do
+       run rm -f $PREFIX/$file
+       run ln -s $LINKREL/$file $PREFIX/$file done

 # update the current version link
 run cd $DATDIR
-run ln -s $VERSION $VERSION/$LINKNAME
-run mv $VERSION/$LINKNAME .
+run ln -s $NEWVER $NEWVER/$LINKNAME
+run mv $NEWVER/$LINKNAME .

 # maybe delete old dat files
 case $DELETE in


########################################################################
######
# diff -u lib/mcafee-wrapper.47911 lib/mcafee-wrapper
--- lib/mcafee-wrapper.47911    2010-04-15 10:33:07.000000000 +0100
+++ lib/mcafee-wrapper  2010-04-10 23:23:36.000000000 +0100
@@ -33,6 +33,7 @@
 # Then tweaked for heron by JKF again
 # Then tweaked for McAfee by JKF
 # Modified (badly!) by SEP398 to work with the update script
+# Modified by MJMM to exclude uvscan v6 (different output parsing 
+required)

 PackageDir=$1
 shift
@@ -43,7 +44,14 @@
 export LD_LIBRARY_PATH

 if [ "x$1" = "x-IsItInstalled" ]; then
-  [ -x ${PackageDir}/$prog ] && exit 0
+
+  #first check if the excutable exists...
+  [ -x ${PackageDir}/$prog ] || exit 1
+
+  #second check if it is pre-v6 (using different output string)  
+ ${PackageDir}/$prog --version | grep "Virus data file v" > /dev/null  
+ [ $? = 0 ] && exit 0
+
   exit 1
 fi




########################################################################
#############
New file: lib/mcafee6-wrapper
# cat lib/mcafee6-wrapper
#!/bin/sh

#   MailScanner - SMTP E-Mail Virus Scanner
#   Copyright (C) 2001  Julian Field
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
02111-1307  USA
#
#   The author, Julian Field, can be contacted by email at
#      Jules at JulianField.net
#   or by paper mail at
#      Julian Field
#      Dept of Electronics & Computer Science
#      University of Southampton
#      Southampton
#      SO17 1BJ
#      United Kingdom
#

# JKF Wrapper Sophos programs with the correct LD_LIBRARY_PATH #
Modified for solaris by CJG # Then tweaked for heron by JKF again # Then
tweaked for McAfee by JKF # Modified (badly!) by SEP398 to work with the
update script # # MJMM Copied as mcafee6-wrapper for handle uvscan v6.0+
# MJMM Updated to detect v6 (different output parsing required)

PackageDir=$1
shift
prog=uvscan # `basename $0`
datDIR=$PackageDir

LD_LIBRARY_PATH=$PackageDir
export LD_LIBRARY_PATH

if [ "x$1" = "x-IsItInstalled" ]; then

  #first check if the excutable exists...
  [ -x ${PackageDir}/$prog ] || exit 1

  #second check if it is v6 (using different output string)
  ${PackageDir}/$prog --version | grep "Dat set version: " > /dev/null
  [ $? = 0 ] && exit 0

  exit 1
fi

if [ -f ${PackageDir}/datfiles/current/extra.dat ]; then
  exec ${PackageDir}/$prog -d $datDIR --extra
${PackageDir}/datfiles/current/extra.dat "$@"
else
  if [ -f ${PackageDir}/extra.dat ]; then
    exec ${PackageDir}/$prog -d $datDIR --extra ${PackageDir}/extra.dat
"$@"
  fi
  exec ${PackageDir}/$prog -d $datDIR "$@"
fi








Michael Miller wrote:
> Hi
>
> I was wondering if there was a date when we can expect MailScanner to 
> natively support the updated McAfee uvscan anti virus scanner? uvscan
> v5.3 is now EoL as DATs are no longer being released.
>
> I see a few patches were posted a few months back but they don't 
> appear to have been merged into MailScanner itself. Does anyone have 
> any more recent patches for uvscan 6.0.0?
>
> If there is interest in this, I can set about testing the patches and 
> consolidating the parsing and the updating patches and reposting if 
> they will be useful.
>
> Regards,
> Mike
>
>   
--
MailScanner mailing list
mailscanner at lists.mailscanner.info
http://lists.mailscanner.info/mailman/listinfo/mailscanner

Before posting, read http://wiki.mailscanner.info/posting

Support MailScanner development - buy the book off the website! 
Any opinion expressed in this e-mail or any attached files are those of the individual and not necessarily those of Herefordshire Council.
You should be aware that Herefordshire Council monitors its email service.
This e-mail and any attached files are confidential and intended solely for the use of the addressee. This communication may contain material protected by law from being passed on. If you are not the intended recipient and have received this e-mail in error, you are advised that any use, dissemination, forwarding, printing or copying of this e-mail is strictly prohibited. If you have received this e-mail in error please contact the sender immediately and destroy all copies of it.


More information about the MailScanner mailing list