+work as expected, with both local parts causing verification failure. When a
+redirection generates more than one address, the behaviour is more like a
+mailing list, where the existence of the alias itself is sufficient for
+verification to succeed.
+
+
+.section Using an ACL to control relaying
+.rset SECTrelaycontrol "~~chapter.~~section"
+.index ~~ACL||relay control
+.index relaying||control by ACL
+.index policy control||relay control
+An MTA is said to \*relay*\ a message if it receives it from some host and
+delivers it directly to another host as a result of a remote address contained
+within it. Redirecting a local address via an alias or forward file and then
+passing the message on to another host is not relaying,
+.index `percent hack'
+but a redirection as a result of the `percent hack' is.
+
+Two kinds of relaying exist, which are termed `incoming' and `outgoing'. A host
+which is acting as a gateway or an MX backup is concerned with incoming
+relaying from arbitrary hosts to a specific set of domains. On the other hand,
+a host which is acting as a smart host for a number of clients is concerned
+with outgoing relaying from those clients to the Internet at large. Often the
+same host is fulfilling both functions, as illustrated in the diagram below,
+but in principle these two kinds of relaying are entirely independent. What is
+not wanted is the transmission of mail from arbitrary remote hosts through your
+system to arbitrary domains.
+.if ~~sys.fancy
+.figure "Controlled relaying" rm
+.indent 0
+.call aspic -sgcal -nv
+centre ~~sys.linelength;
+magnify 0.8;
+boundingbox 30;
+textdepth 16;
+ boxwidth 120;
+ boxdepth 44;
+A: box "Arbitrary" "remote hosts";
+C: ibox;
+D: box "Arbitrary" "domains";
+ iline down 50 from bottom of C;
+H: box width 180 "Local host";
+ iline down 50;
+E: ibox;
+SH: box "Specific" "hosts";
+SD: box join right to E "Specific" "domains";
+ arcarrow clockwise from top of SH to bottom of D plus (-10,-4)
+ via right of H plus (-20,0);
+ arcarrow clockwise from bottom of A to top of SD plus (10,4)
+ via left of H plus (20,0);
+
+ ibox join left to right of H "$it{Outgoing}";
+ goto H;
+ ibox join right to left of H "$it{Incoming}";
+
+L: line dashed from right of A to top of H plus (-15,0);
+ arc dashed to top of H plus (15,0);
+ arrow dashed to left of D plus (-2,0);
+
+ arrow dashed back up 72 right 32 from middle of L plus (8,0);
+ text at end plus (0, 4) "$it{Not wanted}";
+.endcall
+.endfigure
+.elif !~~html
+.display asis
+ -------------- -----------
+ | Arbitrary | |Arbitrary|
+ |remote hosts| | domains |
+ -------------- -----------
+ I v ^ O
+ n v ^ u
+ c ---v----------------^--- t
+ o | v Local ^ | g
+ m | v host ^ | o
+ i ---v----------------^--- i
+ n v ^ n
+ g v ^ g
+ Specific Specific
+ domains hosts
+.endd
+.else
+[(IMG SRC="relaying.gif" alt="Controlled relaying")][(br)]
+.fi
+
+You can implement relay control by means of suitable statements in the ACL that
+runs for each \\RCPT\\ command. For convenience, it is often easiest to use
+Exim's named list facility to define the domains and hosts involved. For
+example, suppose you want to do the following:
+.numberpars $.
+Deliver a number of domains to mailboxes on the local host (or process them
+locally in some other way). Let's say these are \*my.dom1.example*\ and
+\*my.dom2.example*\.
+.nextp
+Relay mail for a number of other domains for which you are the secondary MX.
+These might be \*friend1.example*\ and \*friend2.example*\.
+.nextp
+Relay mail from the hosts on your local LAN, to whatever domains are involved.
+Suppose your LAN is 192.168.45.0/24.
+.endp
+In the main part of the configuration, you put the following definitions:
+.display asis
+domainlist local_domains = my.dom1.example : my.dom2.example
+domainlist relay_domains = friend1.example : friend2.example
+hostlist relay_hosts = 192.168.45.0/24
+.endd
+Now you can use these definitions in the ACL that is run for every \\RCPT\\
+command:
+.display asis
+acl_check_rcpt:
+ accept domains = +local_domains : +relay_domains
+ accept hosts = +relay_hosts
+.endd
+The first statement accepts any \\RCPT\\ command that contains an address in
+the local or relay domains. For any other domain, control passes to the second
+statement, which accepts the command only if it comes from one of the relay
+hosts. In practice, you will probably want to make your ACL more sophisticated
+than this, for example, by including sender and recipient verification. The
+default configuration includes a more comprehensive example, which is described
+in chapter ~~CHAPdefconfil.
+
+
+.section Checking a relay configuration
+.rset SECTcheralcon "~~chapter.~~section"
+.index relaying||checking control of
+You can check the relay characteristics of your configuration in the same way
+that you can test any ACL behaviour for an incoming SMTP connection, by using
+the \-bh-\ option to run a fake SMTP session with which you interact.
+
+For specifically testing for unwanted relaying, the host
+\*relay-test.mail-abuse.org*\ provides a useful service. If you telnet to this
+host from the host on which Exim is running, using the normal telnet port, you
+will see a normal telnet connection message and then quite a long delay. Be
+patient. The remote host is making an SMTP connection back to your host, and
+trying a number of common probes to test for open relay vulnerability. The
+results of the tests will eventually appear on your terminal.
+
+
+
+
+.
+.
+.
+.
+. ============================================================================
+.chapter Content scanning using the `exiscan' features
+.set runningfoot "content scanning"
+.rset CHAPexiscan "~~chapter"
+.index content scanning
+.em
+The content-scanning extension of Exim, also known as `exiscan', was originally
+implemented as a patch by Tom Kistner. The code was integrated into the main
+source for Exim release 4.50, and Tom continues to maintain it. Most of the
+wording of this chapter is taken from Tom's exiscan specification.
+
+If you want to include the content-scanning features when you compile Exim, you
+need to arrange for \\WITH@_CONTENT@_SCAN\\ to be defined in your
+\(Local/Makefile)\. When you do that, the Exim binary is built with:
+.numberpars $.
+An additional ACL (\acl@_smtp@_mime\) that is run for all MIME parts.
+.nextp
+Additional ACL conditions and modifiers: \decode\, \malware\, \mime@_regex\,
+\regex\, and \spam\. These can be used in the ACL that is run at the end of
+message reception (the \acl@_smtp@_data\ ACL).
+.nextp
+Additional expansion variables that are set in the new ACL and by the new
+conditions.
+.nextp
+Two new main configuration options: \av@_scanner\ and \spamd@_address\.
+.endp
+There is another content-scanning configuration option for \(Local/Makefile)\,
+called \\WITH@_OLD@_DEMIME\\. If this is set, the old, deprecated \demime\ ACL
+condition is compiled, in addition to all the other content-scanning features.
+
+Content-scanning is continually evolving, and new features are still being
+added. While such features are still unstable and liable to incompatible
+changes, they are made available in Exim by setting options whose names begin
+\\EXPERIMENTAL@_\\ in \(Local/Makefile)\. Such features are not documented in
+this manual. You can find out about them by reading the file called
+\(doc/experimental.txt)\.
+
+All the content-scanning facilites work on a MBOX copy of the message that is
+temporarily created in a file called:
+.display
+<<spool@_directory>>/scan/<<message@_id>>/<<message@_id>>.eml
+.endd
+The \(.eml)\ extension is a friendly hint to virus scanners that they can
+expect an MBOX-like structure inside that file. The file is created when the
+first exiscan facility is called. Subsequent calls to exiscan conditions open
+the same file again. The directory is recursively removed when the
+\acl@_smtp@_data\ ACL has finished running. When the MIME ACL decodes files,
+they are put into that same directory by default.
+
+
+.section Scanning for viruses
+.rset SECTscanvirus "~~chapter.~~section"
+.index virus scanning
+.index content scanning||for viruses
+.index content scanning||the \malware\ condition
+The \malware\ ACL condition lets you connect virus scanner software to Exim. It
+supports a `generic' interface to scanners called via the shell, and
+specialized interfaces for `daemon' type virus scanners, which are resident in
+memory and thus are much faster.
+
+.index \av@_scanner\
+You can set the \av@_scanner\ option in first part of the Exim configuration
+file to specify which scanner to use, together with any additional options that
+are needed. The basic syntax is as follows:
+.display
+av@_scanner = <<scanner-type>>:<<option1>>:<<option2>>:[...]
+.endd
+If you do not set \av@_scanner\, it defaults to
+.display asis
+av_scanner = sophie:/var/run/sophie
+.endd
+If the value of \av@_scanner\ starts with dollar character, it is expanded
+before use.
+
+The following scanner types are supported in this release:
+.numberpars $.
+.index virus scanners||Kaspersky
+\aveserver\: This is the scanner daemon of Kaspersky Version 5. You can get a
+trial version at \?http://www.kaspersky.com?\. This scanner type takes one
+option, which is the path to the daemon's UNIX socket. The default is shown in
+this example:
+.display asis
+av_scanner = aveserver:/var/run/aveserver
+.endd
+
+.nextp
+.index virus scanners||clamd
+\clamd\: This daemon-type scanner is GPL and free. You can get it at
+\?http://www.clamav.net/?\. Clamd does not seem to unpack MIME containers,
+so it is recommended to use the demime facility with it. It takes one option:
+either the path and name of a UNIX socket file, or a hostname or IP number, and
+a port, separated by space, as in the second of these examples:
+.display asis
+av_scanner = clamd:/opt/clamd/socket
+av_scanner = clamd:192.168.2.100 1234
+.endd
+If the option is unset, the default is \(/tmp/clamd)\.
+
+.nextp
+.index virus scanners||command line interface
+\cmdline\: This is the keyword for the generic command line scanner interface.
+It can be used to attach virus scanners that are invoked from the shell. This
+scanner type takes 3 mantadory options:
+.numberpars
+The full path and name of the scanner binary, with all command line options,
+and a placeholder (%s) for the directory to scan.
+.nextp
+A regular expression to match against the STDOUT and STDERR output of the virus
+scanner. If the expression matches, a virus was found. You must make absolutely
+sure that this expression matches on `virus found'. This is called the
+`trigger' expression.
+.nextp
+Another regular expression, containing exactly one pair of braces, to match the
+name of the virus found in the scanners output. This is called the `name'
+expression.
+.endp
+For example, Sophos Sweep reports a virus on a line like this:
+.display asis
+Virus 'W32/Magistr-B' found in file ./those.bat
+.endd
+For the trigger expression, we can just match the word `found'. For the name
+expression, we want to extract the W32/Magistr-B string, so we can match for
+the single quotes left and right of it. Altogether, this makes the
+configuration setting:
+.display asis
+av_scanner = cmdline:\
+ /path/to/sweep -all -rec -archive %s:\
+ found:'(.+)'
+.endd
+
+.nextp
+.index virus scanners||DrWeb
+\drweb\: The DrWeb daemon scanner (\?http://www.sald.com/?\) interface
+takes one argument, either a full path to a UNIX socket, or an IP address and
+port separated by whitespace, as in these examples:
+.display asis
+av_scanner = drweb:/var/run/drwebd.sock
+av_scanner = drweb:192.168.2.20 31337
+.endd
+If you omit the argument, the default path \(/usr/local/drweb/run/drwebd.sock)\
+is used. Thanks to Alex Miller for contributing the code for this scanner.
+
+.nextp
+.index virus scanners||F-Secure
+\fsecure\: The F-Secure daemon scanner (\?http://www.f-secure.com?\) takes one
+argument which is the path to a UNIX socket. For example:
+.display asis
+av_scanner = fsecure:/path/to/.fsav
+.endd
+If no argument is given, the default is \(/var/run/.fsav)\. Thanks to Johan
+Thelmen for contributing the code for this scanner.
+
+.nextp
+.index virus scanners||Kaspersky
+\kavdaemon\: This is the scanner daemon of Kaspersky Version 4. This version of
+the Kaspersky scanner is outdated. Please upgrade (see \aveserver\ above). This
+scanner type takes one option, which is the path to the daemon's UNIX socket.
+For example:
+.display asis
+av_scanner = kavdaemon:/opt/AVP/AvpCtl
+.endd
+The default path is \(/var/run/AvpCtl)\.
+
+.nextp
+.index virus scanners||mksd
+\mksd\: This is a daemon type scanner that is aimed mainly at Polish users,
+though some parts of documentation are now available in English. You can get it
+at \?http://linux.mks.com.pl/?\. The only option for this scanner type is the
+maximum number of processes used simultaneously to scan the attachments,
+provided that the demime facility is employed and also provided that mksd has
+been run with at least the same number of child processes. For example:
+.display asis
+av_scanner = mksd:2
+.endd
+You can safely omit this option (the default value is 1).
+
+.nextp
+.index virus scanners||Sophos and Sophie
+\sophie\: Sophie is a daemon that uses Sophos' \libsavi\ library to scan for
+viruses. You can get Sophie at \?http://www.vanja.com/tools/sophie/?\. The only
+option for this scanner type is the path to the UNIX socket that Sophie uses
+for client communication. For example:
+.display asis
+av_scanner = sophie:/tmp/sophie
+.endd
+The default path is \(/var/run/sophie)\, so if you are using this, you can omit
+the option.
+.endp
+
+When \av@_scanner\ is correcly set, you can use the \malware\ condition in the
+DATA ACL. The condition takes a right-hand argument that is expanded before
+use. It can then be one of
+.numberpars $.
+`true', `*', or `1', in which case the message is scanned for viruses. The
+condition succeeds if a virus was found, and fail otherwise. This is the
+recommended usage.
+.nextp
+`false' or `0', in which case no scanning is done and the condition fails
+immediately.
+.nextp
+A regular expression, in which case the message is scanned for viruses. The
+condition succeeds if a virus is found and its name matches the regular
+expression. This allows you to take special actions on certain types of virus.
+.endp
+You can append \"/defer@_ok"\ to the \malware\ condition to accept messages even
+if there is a problem with the virus scanner.
+
+.index \$malware@_name$\
+When a virus is found, the condition sets up an expansion variable called
+\$malware@_name$\ that contains the name of the virus. You can use it in a
+\message\ modifier that specifies the error returned to the sender, and/or in
+logging data.
+
+The \malware\ condition caches its results, so when you use it multiple times
+for the same message, the actual scanning process is only carried out once.
+
+If your virus scanner cannot unpack MIME and TNEF containers itself, you should
+use the \demime\ condition (see section ~~SECTdemimecond) before the \malware\
+condition.
+
+Here is a very simple scanning example:
+.display asis
+deny message = This message contains malware ($malware_name)
+ demime = *
+ malware = *
+.endd
+The next example accepts messages when there is a problem with the scanner:
+.display asis
+deny message = This message contains malware ($malware_name)
+ demime = *
+ malware = */defer_ok
+.endd
+The next example shows how to use an ACL variable to scan with both sophie and
+aveserver. It assumes you have set:
+.display asis
+av_scanner = $acl_m0
+.endd
+in the main Exim configuration.
+.display asis
+deny message = This message contains malware ($malware_name)
+ set acl_m0 = sophie
+ malware = *
+
+deny message = This message contains malware ($malware_name)
+ set acl_m0 = aveserver
+ malware = *
+.endd
+However, when \av@_scanner\ is expanded, the caching of the \malware\
+condition result does not happen, so each \malware\ condition call causes a
+new scan of the message.
+
+
+.section Scanning with SpamAssassin
+.rset SECTscanspamass "~~chapter.~~section"
+.index content scanning||for spam
+.index spam scanning
+.index SpamAssassin, scanning with
+The \spam\ ACL condition calls SpamAssassin's \spamd\ daemon to get a spam
+score and a report for the message. You can get SpamAssassin at
+\?http://www.spamassassin.org?\, or, if you have a working Perl installation,
+you can use CPAN by running:
+.display asis
+perl -MCPAN -e 'install Mail::SpamAssassin'
+.endd
+SpamAssassin has its own set of configuration files. Please review its
+documentation to see how you can tweak it. The default installation should work
+nicely, however.
+
+.index \spamd@_address\
+After having installed and configured SpamAssassin, start the \spamd\ daemon.
+By default, it listens on 127.0.0.1, TCP port 783. If you use another host or
+port for \spamd\, you must set the \spamd@_address\ option in the global part
+of the Exim configuration as follows (example):
+.display asis
+spamd_address = 192.168.99.45 387
+.endd
+You do not need to set this option if you use the default. As of version 2.60,
+\spamd\ also supports communication over UNIX sockets. If you want to use
+these, supply \spamd@_address\ with an absolute file name instead of a
+address/port pair:
+.display asis
+spamd_address = /var/run/spamd_socket
+.endd
+
+You can have multiple \spamd\ servers to improve scalability. These can reside
+on other hardware reachable over the network. To specify multiple \spamd\
+servers, put multiple address/port pairs in the \spamd@_address\ option,
+separated with colons:
+.display asis
+spamd_address = 192.168.2.10 783 : \
+ 192.168.2.11 783 : \
+ 192.168.2.12 783
+.endd
+Up to 32 \spamd\ servers are supported. The servers are
+queried in a random fashion. When a server fails to respond
+to the connection attempt, all other servers are tried
+until one succeeds. If no server responds, the \spam\
+condition defers.
+
+\**Warning**\: It is not possible to use the UNIX socket connection method with
+multiple \spamd\ servers.
+
+Here is a simple example of the use of the \spam\ condition in a DATA ACL:
+.display asis
+deny message = This message was classified as SPAM
+ spam = joe
+.endd
+The right-hand side of the \spam\ condition specifies the username that
+SpamAssassin should scan for. If you do not want to scan for a particular user,
+but rather use the SpamAssassin system-wide default profile, you can scan for
+an unknown user, or simply use `nobody'. However, you must put something on the
+right-hand side.
+
+The username allows you to use per-domain or per-user antispam profiles. The
+right-hand side is expanded before being used, so you can put lookups or
+conditions there. When the right-hand side evaluates to `0' or `false', no
+scanning is done and the condition fails immediately.
+
+The \spam\ condition returns true if the threshold specified in the user's
+SpamAssassin profile has been matched or exceeded. If you want to use the
+\spam\ condition for its side effects (see the variables below), you can make
+it always return `true' by appending \":true"\ to the username.
+
+.index spam scanning||returned variables
+When the \spam\ condition is run, it sets up the following expansion
+variables:
+
+.push
+.indent 2em
+
+.tempindent 0
+\$spam@_score$\: The spam score of the message, for example `3.4' or `30.5'.
+This is useful for inclusion in log or reject messages.
+
+.tempindent 0
+\$spam@_score@_int$\: The spam score of the message, multiplied by ten, as an
+integer value. For example `34' or `305'. This is useful for numeric
+comparisons in conditions. This variable is special; it is saved with the
+message, and written to Exim's spool file. This means that it can be used
+during the whole life of the message on your Exim system, in particualr, in
+routers or transports during the later delivery phase.
+
+.tempindent 0
+\$spam@_bar$\: A string consisting of a number of `+' or `@-' characters,
+representing the integer part of the spam score value. A spam score of 4.4
+would have a \$spam@_bar$\ value of `++++'. This is useful for inclusion in
+warning headers, since MUAs can match on such strings.
+
+.tempindent 0
+\$spam@_report$\: A multiline text table, containing the full SpamAssassin
+report for the message. Useful for inclusion in headers or reject messages.
+
+.pop
+
+The \spam\ condition caches its results. If you call it again with the same user
+name, it does not scan again, but rather returns the same values as before.
+
+The \spam\ condition returns DEFER if there is any error while running the
+message through SpamAssassin. If you want to treat DEFER as FAIL (to pass on to
+the next ACL statement block), append \"/defer@_ok"\ to the right-hand side of
+the spam condition, like this:
+.display asis
+deny message = This message was classified as SPAM
+ spam = joe/defer_ok
+.endd
+This causes messages to be accepted even if there is a
+problem with \spamd\.
+
+Here is a longer, commented example of the use of the \spam\
+condition:
+.display asis
+# put headers in all messages (no matter if spam or not)
+warn message = X-Spam-Score: $spam_score ($spam_bar)
+ spam = nobody:true
+warn message = X-Spam-Report: $spam_report
+ spam = nobody:true
+
+# add second subject line with *SPAM* marker when message
+# is over threshold
+warn message = Subject: *SPAM* $h_Subject:
+ spam = nobody
+
+# reject spam at high scores (> 12)
+deny message = This message scored $spam_score spam points.
+ spam = nobody:true
+ condition = ${if >{$spam_score_int}{120}{1}{0}}
+.endd
+
+
+
+.section Scanning MIME parts
+.rset SECTscanmimepart "~~chapter.~~section"
+.index content scanning||MIME parts
+.index MIME content scanning
+.index \acl@_smtp@_mime\
+The \acl@_smtp@_mime\ global option defines an ACL that is called once for each
+MIME part of a message, including multipart types, in the sequence of their
+position in the message.
+
+This ACL is called (possibly many times) just before the \acl@_smtp@_data\ ACL,
+but only if the message has a ::MIME-Version:: header. When a call to the MIME
+ACL does not yield `accept', ACL processing is aborted and the appropriate
+result code is sent to the remote client. The \acl@_smtp@_data\ ACL is not
+called in this circumstance.
+
+At the start of the MIME ACL, a number of variables are set from the header
+information for the relevant MIME part. These are described below. The contents
+of the MIME part are not by default decoded into a disk file except for MIME
+parts whose content-type is `message/rfc822'. If you want to decode a MIME part
+into a disk file, you can use the \decode\ modifier. The general syntax is:
+.display
+decode = [/<<path>>/]<<filename>>
+.endd
+The right hand side is expanded before use. After expansion,
+the value can be:
+.numberpars
+`0' or `false', in which case no decoding is done.
+.nextp
+The string `default'. In that case, the file is put in the temporary `default'
+directory \(<<spool@_directory>>/scan/<<message@_id>>/)\ with a sequential file
+name consisting of the message id and a sequence number. The full path and name
+is available in \$mime@_decoded@_filename$\ after decoding.
+.nextp
+A full path name starting with a slash. If the full name is an existing
+directory, it is used as a replacement for the default directory. The filename
+is then sequentially assigned. If the path does not exist, it is used as
+the full path and file name.
+.nextp
+If the string does not start with a slash, it is used as the
+filename, and the default path is then used.
+.endp
+You can easily decode a file with its original, proposed
+filename using
+.display asis
+decode = $mime_filename
+.endd
+However, you should keep in mind that \$mime@_filename$\ might contain
+anything. If you place files outside of the default path, they are not
+automatically unlinked.
+
+For RFC822 attachments (these are messages attached to messages, with a
+content-type of `message/rfc822'), the ACL is called again in the same manner
+as for the primary message, only that the \$mime@_is@_rfc822$\ expansion
+variable is set (see below). Attached messages are always decoded to disk
+before being checked, and the files are unlinked once the check is done.
+
+The MIME ACL supports the \regex\ and \mime@_regex\ conditions. These can be
+used to match regular expressions against raw and decoded MIME parts,
+respectively. They are described in section ~~SECTscanregex.
+
+.index MIME content scanning||returned variables
+The following list describes all expansion variables that are
+available in the MIME ACL:
+
+.push
+.indent 2em
+
+.tempindent 0
+\$mime@_boundary$\:
+If the current part is a multipart (see \$mime@_is@_multipart$\) below, it
+should have a boundary string, which is stored in this variable. If the current
+part has no boundary parameter in the ::Content-Type:: header, this variable
+contains the empty string.
+
+.tempindent 0
+\$mime@_charset$\:
+This variable contains the character set identifier, if one was found in the
+::Content-Type:: header. Examples for charset identifiers are:
+.display asis
+us-ascii
+gb2312 (Chinese)
+iso-8859-1
+.endd
+Please note that this value is not normalized, so you should do matches
+case-insensitively.