clamdscan uses the daemon of the virus scanner clamav to check emails and the like for viruses. If you use Courier-mta, you are probably using mailfilter for local delivery in many cases. The easiest way to use clamav seems to be to configure it in the .mailfiter configuration file and use it from there[1], but then

lstat() failed: Permission denied. ERROR

an error like this appears, and it does not work properly. This seems to be because clamd runs with the privileges of the clamd user and therefore cannot read the mail files.

To avoid this, you can use clamscan instead of clamdscan, but performance is far too poor because it loads the virus database every time.

In the end, it took me several hours to investigate, but the most useful reference was the article titled “HOWTO_Install_Courier_with_maildrop_and_ClamAV_and_SpamA.”

According to it, first prepare /usr/bin/clamdscan.sh as follows.

#!/bin/bash
# Created by Tom Walsh, slim at ala.net
# slightly modified by Wolfgang Ziegler, nuppla at gmx.at

# RUN=clamscan
# Enable this line, if you are using the clamav-daemon.
RUN=clamdscan


#start
MSG=$(< /proc/self/fd/0) # stdin -> $MSG
SCAN=$(echo "$MSG" | $RUN - --stdout --disable-summary)
EXIT="$?"
VIRUS=$(echo "$SCAN" | awk '{print $2}')
SUBJECT=$(echo "$MSG" | reformail -x Subject:)

if [ "$EXIT" == "1" ]; then
 SUBJECT="**VIRUS** [$VIRUS] $SUBJECT"
 MSG=$(echo "$MSG" | reformail -i"X-Virus-Status: INFECTED")
 MSG=$(echo "$MSG" | reformail -i"Subject: $(echo "$SUBJECT")")
else
 MSG=$(echo "$MSG" | reformail -i"X-Virus-Status: CLEAN")
fi

echo "$MSG"
exit 0

Make this file executable.

chmod +x /usr/bin/clamscan.sh

Then add the following to .mailfilter.

MAILDIR="$HOME/Maildir"
DEFAULT="$MAILDIR"
FOLDERS="$DEFAULT/."
SPAM="${FOLDERS}junk"
CLAMDSCAN="/usr/bin/clamdcan.sh"
`${CLAMDSCAN}`
if ( /^X-Virus-Status:.*INFECTED/ )
{
        log "Clamdscan: Virus found\n"
        to $SPAM
}

This probably works now… Clamav will inspect even the contents of ZIP files, which is a good point.

If all you want to do is drop messages with attachments such as .exe[2], there is no need to bring clamav into the picture; something like the following will do.

# attachments are in the body, so :b flag
if ( /^Content-type: (audio|application)/:b \\
     && /name=.*\\.(bat|com|exe|hta|pif|scr|shs|vb[es]|ws[fh])/:b )
{
        xfilter "${REFORMAIL} -a'$SPAMHEADER potential virus attachment'"
        log "Illegal Extention\n"
        to $SPAM
}

If you absolutely do not want to receive emails like this, you could exit instead of using to $SPAM, but sometimes you want to read just the body, after all. It may also be possible to use reformail to strip the attachment section, but I have been too lazy to try it.

Well, then.
[1] You could say it should be installed on the mail server itself, but this was easier at a personal level. I will also try doing it with perlmailfilter if I can find the time to set up a test server.

[2] It has been a topic of discussion for the past few days because of the Pension Service leak.

Related posts