Access Control Lists (ACLs) are defined in a separate section of the run time configuration file, headed by begin acl. Each ACL definition starts with a name, terminated by a colon. Here is a complete ACL section which contains just one very small ACL:
begin acl small_acl: accept hosts = one.host.only
You can have as many lists as you like in the ACL section, and the order in which they appear does not matter. The lists are self-terminating.
The majority of ACLs are used to control Exim's behaviour when it receives certain SMTP commands. This applies both to incoming TCP/IP connections, and when a local process submits a message over a pipe (using the -bs option). The most common use is for controlling which recipients are accepted in incoming messages. In addition, you can also define an ACL that is used to check local non-SMTP messages. The default configuration file contains an example of a realistic ACL for checking RCPT commands. This is discussed in chapter 7.
The -bh command line option provides a way of testing your ACL configuration locally by running a fake SMTP session with which you interact. The host relay-test.mail-abuse.org provides a service for checking your relaying configuration (see section 38.27 for more details).
In order to cause an ACL to be used, you have to name it in one of the relevant options in the main part of the configuration. These options are:
| acl_not_smtp | ACL for non-SMTP messages |
| acl_smtp_auth | ACL for AUTH |
| acl_smtp_connect | ACL for start of SMTP connection |
| acl_smtp_data | ACL after DATA |
| acl_smtp_etrn | ACL for ETRN |
| acl_smtp_expn | ACL for EXPN |
| acl_smtp_helo | ACL for HELO or EHLO |
| acl_smtp_mail | ACL for MAIL |
| acl_smtp_mailauth | ACL for the AUTH parameter of MAIL |
| acl_smtp_rcpt | ACL for RCPT |
| acl_smtp_starttls | ACL for STARTTLS |
| acl_smtp_vrfy | ACL for VRFY |
For example, if you set
acl_smtp_rcpt = small_acl
the little ACL defined above is used whenever Exim receives a RCPT command in an SMTP dialogue. The majority of policy tests on incoming messages can be done when RCPT commands arrive. A rejection of RCPT should cause the sending MTA to give up on the recipient address contained in the RCPT command, whereas rejection at other times may cause the client MTA to keep on trying to deliver the message. It is therefore recommended that you do as much testing as possible at RCPT time.
However, you cannot test the contents of the message, for example, to verify addresses in the headers, at RCPT time. Such tests have to appear in the ACL that is run after the message has been received, before the final response to the DATA command is sent. This is the ACL specified by acl_smtp_data. At this time, it is no longer possible to reject individual recipients. An error response should reject the entire message. Unfortunately, it is known that some MTAs do not treat hard (5xx) errors correctly at this point they keep the message on their queues and try again later, but that is their problem, though it does waste some of your resources.
The ACL test specified by acl_smtp_connect happens after the test specified by host_reject_connection (which is now an anomaly) and any TCP Wrappers testing (if configured).
The non-SMTP ACL applies to all non-interactive incoming messages, that is, it applies to batch SMTP as well as to non-SMTP messages. (Batch SMTP is not really SMTP.) This ACL is run just before the local_scan() function. Any kind of rejection is treated as permanent, because there is no way of sending a temporary error for these kinds of message. Many of the ACL conditions (for example, host tests, and tests on the state of the SMTP connection such as encryption and authentication) are not relevant and are forbidden in this ACL.
The result of running an ACL is either accept or deny, or, if some test cannot be completed (for example, if a database is down), defer. These results cause 2xx, 5xx, and 4xx return codes, respectively, to be used in the SMTP dialogue. A fourth return, error, occurs when there is an error such as invalid syntax in the ACL. This also causes a 4xx return code.
The ACLs that are relevant to message reception may also return discard. This has the effect of accept, but causes either the entire message or an individual recipient address to be discarded. In other words, it is a blackholing facility. Use it with great care.
If the ACL for MAIL returns discard, all recipients are discarded, and no ACL is run for subsequent RCPT commands. The effect of discard in a RCPT ACL is to discard just the one address. If there are no recipients left when the message's data is received, the DATA ACL is not run. A discard return from the DATA or the non-SMTP ACL discards all the remaining recipients.
The local_scan() function is always run, even if there are no remaining recipients; it may create new recipients.
The default actions when any of the acl_smtp_xxx options are unset are not all the same.
For acl_not_smtp, acl_smtp_auth, acl_smtp_connect, acl_smtp_data, acl_smtp_helo, acl_smtp_mail, acl_smtp_mailauth, and acl_smtp_starttls, the default action is accept.
For the others (acl_smtp_etrn, acl_smtp_expn, acl_smtp_rcpt, and acl_smtp_vrfy), the default action is deny. This means that acl_smtp_rcpt must be defined in order to receive any messages over an SMTP connection. For an example, see the ACL in the default configuration file.
When an ACL for MAIL, RCPT, or DATA is being run, the variables that contain information about the host and the message's sender (for example, $sender_host_address and $sender_address) are set, and can be used in ACL statements. In the case of RCPT (but not MAIL or DATA), $domain and $local_part are set from the argument address.
When an ACL for the AUTH parameter of MAIL is being run, the variables that contain information about the host are set, but $sender_address is not yet set.
The $message_size variable is set to the value of the SIZE parameter on the MAIL command at MAIL and RCPT time, or -1 if that parameter was not given. Its value is updated to the true message size by the time the ACL after DATA is run.
The $rcpt_count variable increases by one for each RCPT command received. The $recipients_count variable increases by one each time a RCPT command is accepted, so while an ACL for RCPT is being processed, it contains the number of previously accepted recipients. At DATA time, $rcpt_count contains the total number of RCPT commands, and $recipients_count contains the total number of accepted recipients.
When an ACL for AUTH, ETRN, EXPN, STARTTLS, or VRFY is being run, the remainder of the SMTP command line is placed in $smtp_command_argument. This can be tested using a condition condition. For example, here is an ACL for use with AUTH, which insists that either the session is encrypted, or the CRAM-MD5 authentication method is used. In other words, it does not permit authentication methods that use cleartext passwords on unencrypted connections.
acl_check_auth:
accept encrypted = *
accept condition = ${if eq{${uc:$smtp_command_argument}}\
{CRAM-MD5}{yes}{no}}
deny message = TLS encryption or CRAM-MD5 required
(Another way of applying this restriction is to arrange for the authenticators that use cleartext passwords not to be advertised when the connection is not encrypted. You can use the generic server_advertise_condition authenticator option to do this.)
The value of an acl_smtp_xxx option is expanded before use, so you can use different ACLs in different circumstances, and in fact the resulting string does not have to be the name of a configured list. Having expanded the string, Exim searches for an ACL as follo
A B C D E F G H I J K L M N O P Q R S T U V W X “
This chapter contains a full description of the contents of Exim filter files.
Apart from leading white space, the first text in a filter file must be
$bheader_
$header_
$host [2]
$host_address [2]
$rheader_
$value [2] [3]
*@ with single-key lookup
+caseful
+defer_unknown
+exclude_unknown
+include_unknown [2]
-be option [2]
-bF option
-bf option
-bh option
-bi option
-bp option
-bt option
-bv option [2]
-C option
-D option
-f option
-f option:for address testing
-f option:for filter testing
-f option:overriding From line
-M option [2]
-os option
-q option
-q optioni
-R option
-t option
.ifdef
.include in configuration file
.include_if_exists in configuration file
/dev/null
/etc/aliases
/etc/mail/mailer.conf
/etc/userdbshadow.dat
8-bit characters [2] [3]
8BITMIME
@ in a domain list [2]
@ in a host list
@@ with single-key lookup
@[] in a domain list
@[] in a host list
@mx_any
@mx_primary
@mx_secondary
A
abandoning mail [2]
accept router
ACL:certificate verification
ACL:conditions, list of
ACL:conditions, processing
ACL:customized test
ACL:data for message ACL
ACL:data for non-message ACL
ACL:default configuration
ACL:description
ACL:for non-SMTP messages
ACL:format of
ACL:indirect
ACL:introduction
ACL:modifiers, list of
ACL:modifiers, processing
ACL:nested
ACL:on SMTP connection
ACL:options for specifying
ACL:relay control
ACL:return codes
ACL:setting up for SMTP commands
ACL:specifying which to use
ACL:testing a DNS list [2]
ACL:testing a local part
ACL:testing a recipient
ACL:testing a recipient domain
ACL:testing a sender
ACL:testing a sender domain
ACL:testing for authentication
ACL:testing for encryption
ACL:testing the client host
ACL:unset options
ACL:variables
ACL:verbs, definition of
ACL:verifying header syntax
ACL:verifying HELO/EHLO
ACL:verifying host reverse lookup
ACL:verifying recipient
ACL:verifying sender
ACL:verifying sender in the header
adding drivers
additional groups [2]
address list:@@ lookup type
address list:case forcing
address list:empty item
address list:in a rewriting pattern
address list:local part starting with !
address list:lookup for complete address
address list:patterns
address list:regular expression in
address list:split local part and domain
address redirection:broken files
address redirection:disabling rewriting
address redirection:domain, preserving
address redirection:errors
address redirection:included external list
address redirection:local part without domain
address redirection:non-filter list items
address redirection:one-time expansion
address redirection:redirect router
address redirection:repeated for each delivery attempt
address redirection:to black hole
address redirection:to file
address redirection:to local mailbox
address redirection:to pipe
address redirection:while verifying [2]
address:constructed
address:copying routing [2]
address:duplicate, discarding [2]
address:qualification [2]
address:qualification, suppressing
address:rewriting [2] [3]
address:sender
address:source-routed
address:testing [2]
address:verification
address:without domain
admin user [2] [3]
admin user:definition of
alias file:backslash in
alias file:broken
alias file:building [2]
alias file:exception to default
alias file:in a redirect router
alias file:one-time expansion
alias file:ownership
alias file:per-domain default
alias for host
alternate configuration file
angle brackets, excess
appendfile transport
appending to a file
asterisk:after IP address
asterisk:in address list
asterisk:in domain list
asterisk:in host list [2]
asterisk:in lookup type
asterisk:in search type
Athena
AUTH:ACL for [2]
AUTH:advertising
AUTH:advertising when encrypted
AUTH:argument
AUTH:configuration [2]
AUTH:description of
AUTH:in plaintext authenticator
AUTH:logging
AUTH:on bounce message
AUTH:on MAIL command [2] [3] [4]
AUTH:testing a server
AUTH:with PAM
authentication
authentication:ACL checking
authentication:advertising
authentication:bounce message
authentication:CRAM-MD5 mechanism
authentication:failure
authentication:generic options
authentication:id
authentication:id, specifying for local message
authentication:logging
authentication:LOGIN mechanism
authentication:Microsoft Secure Password
authentication:name, specifying for local message
authentication:NTLM
authentication:on an Exim client
authentication:on an Exim server
authentication:optional in client
authentication:PLAIN mechanism
authentication:required by client
authentication:sender
authentication:sender, authenticated
authentication:sender, specifying for local message
authentication:testing a server
authenticators:cram_md5
authenticators:plaintext
authenticators:spa
auto_thaw
autoreply transport
autoreply transport:for system filter
B
background delivery
backlog of connections
backslash in alias file
bang paths:not handled by Exim
bang paths:rewriting
banner for SMTP
base36
base62 [2] [3]
base64
batch_id
batch_max
batched local delivery
batched SMTP input [2]
batched SMTP output
batched SMTP output example
Bcc: header line [2]
Berkeley DB library
Berkeley DB library:file format
BIN_DIRECTORY
bind IP address
black hole
black list (DNS) [2] [3] [4]
body of message:definition of
body of message:expansion variable [2]
body of message:line count
body of message:size
body of message:transporting
body of message:visible size
books about Exim
boolean configuration values
bounce message:copy to other address
bounce message:customizing [2]
bounce message:definition of
bounce message:discarding
bounce message:failure to deliver
bounce message:generating
bounce message:including body
bounce message:including original
bounce message:recipient of
bounce message:Reply-to: in
bounce message:sender authentication
bounce message:size limit
bounce message:when generated
broken alias or forward files
BSD, DBM library for
bug reports
build directory
build-time options, overriding
building alias file
building DBM files
building Exim
building Exim:architecture type
building Exim:multiple OS/architectures
building Exim:operating system type
building Exim:OS-specific C header files
building Exim:overriding default settings
building Exim:pre-building configuration
building Eximon:overriding default options
C
caching:callout
caching:callout, suppressing
caching:callout, timeouts
caching:lookup data
callout:cache, suppressing
callout:caching
callout:caching timeouts
callout:defer, action on
callout:postmaster, checking
callout:timeout, specifying
callout:verification
callout:random check
carriage return [2] [3] [4]
case forcing in address lists
case forcing in strings [2]
case of local parts [2] [3] [4]
Cc: header line
cdb:acknowledgement
cdb:description of
cdb:including support for
certificate:for client, location of
certificate:for server, location of
certificate:references to discussion
certificate:self-signed
certificate:verification of client [2] [3] [4] [5]
certificate:verification of server
change log
checking access
checking disk space [2]
CIDR notation
CIDR notation
cipher, logging [2]
command line:addresses with -t
command line:options
common option syntax
configuration file:alternate
configuration file:common option syntax
configuration file:conditional skips
configuration file:editing
configuration file:errors in
configuration file:format of
configuration file:including other files
configuration file:macros
configuration file:ownership
configuration options, extracting
configuration:alternate
configuration:default file, walk through
configuration:for building Exim
configuration:main
configuration:retry
configuration:run time
CONFIGURE_FILE [2] [3]
connection backlog
constructed address
contributed material
control of incoming mail
copy of bounce message
copy of message (unseen option)
Courier
CR [2] [3] [4] [5]
CRAM-MD5 authentication mechanism
cram_md5 authenticator
creating directories
crypt()
crypt16()
current directory for local transport [2]
customizing: Received: header
customizing:ACL condition
customizing:ACL failure message
customizing:batching condition
customizing:bounce message [2]
customizing:failure message
customizing:input scan using C function
customizing:precondition
customizing:SMTP banner
customizing:warning message [2]
customizing:cannot route message
cycling logs [2]
Cygwin
Cyrus [2] [3] [4] [5] [6]
D
daemon [2]
daemon:listening IP addresses
daemon:pid file path
daemon:process id (pid) [2] [3]
daemon:starting
daemon:TCP_NODELAY on sockets
Darwin
DATA, ACL for [2]
database lookups
Date: header line
DBM:building dbm files
DBM:libraries, configuration for building [2]
DBM:libraries, discussion of
DBM:lookup
DBM:lookup type
debugging:-bh option
debugging:-d option
debugging:-N option
debugging:from embedded Perl
debugging:list of selectors
debugging:suppressing delivery
default:ACLs
default:configuration file walk through
default:in single-key lookups
default:retry rule
default:routers
default:transports
defer in system filter
deferred delivery, forcing
delay warning, specifying
delay_after_cutoff
delay_warning_condition
delayed delivery, logging
Delivery-date: header line [2] [3]
delivery:abandoning further attempts
delivery:by external agent
delivery:cancelling all
delivery:cancelling by address
delivery:deferral
delivery:delaying certain domains
delivery:discarded, logging
delivery:failure, logging
delivery:failure, long-term
delivery:fake, logging
delivery:first
delivery:forcing attempt
delivery:forcing deferral
delivery:forcing failure [2]
delivery:forcing in queue run
delivery:from given sender
delivery:in detail
delivery:in the background
delivery:in the foreground
delivery:log line format
delivery:manually started, not forced
delivery:maximum number of
delivery:parallelism for remote
delivery:permanent failure
delivery:problems with
delivery:procmail
delivery:retry in remote transports
delivery:retry mechanism
delivery:sorting remote
delivery:suppressing immediate
delivery:temporary failure
delivery:to file, forbidding
delivery:to given domain
delivery:to pipe, forbidding
delivery:to single file
delivery:unprivileged
delivery_date_remove
delivery||failure report see bounce message
design philosophy
dialup see intermittently connected hosts
directories, multiple
directory creation [2] [3] [4]
discarded messages
discarding bounce message
disk space, checking [2]
distribution:ftp site
distribution:public key
distribution:signing details
dmbnz lookup type
DNS list:in ACL [2]
DNS list:logging defer
DNS:as a lookup type [2]
DNS:IPv6 lookup for AAAA records
DNS:pre-check of name syntax
DNS:resolver options [2] [3]
DNS:reverse lookup [2] [3]
DNS:try again response, overriding
dnsdb lookup
dnslookup router
doc/ChangeLog
doc/NewStuff
doc/spec.txt
documentation
documentation:available formats
domain list:asterisk in
domain list:matching by lookup
domain list:matching literal domain name
domain list:matching local IP interfaces
domain list:matching MX pointers to local host
domain list:matching primary host name
3. Exim filter files
3.1. Format of Exim filter files
# Exim filter
This is what distinguishes it from a conventional .forward file or a Sieve filter file. If the file does not have this initial line (or the equivalent for a Sieve filter), it is treated as a conventional .forward file, both when delivering mail and when using the -bf testing mechanism. The white space in the line is optional, and any capitalization may be used. Further text on the same line is treated as a comment. For example, you could have
# Exim filter <<== do not edit or remove this line!
The remainder of the file is a sequence of filtering commands, which consist of keywords and data values. For example, in the command
deliver gulliver@lilliput.fict.example
the keyword is deliver and the data value is gulliver@lilliput.fict.example. White space or line breaks separate the components of a command, except in the case of conditions for the if command, where round brackets (parentheses) also act as separators. Complete commands are separated from each other by white space or line breaks; there are no special terminators. Thus, several commands may appear on one line, or one command may be spread over a number of lines.
If the character # follows a separator anywhere in a command, everything from # up to the next newline is ignored. This provides a way of including comments in a filter file.
There are two ways in which a data value can be input:
If the text contains no white space then it can be typed verbatim. However, if it is part of a condition, it must also be free of round brackets (parentheses), as these are used for grouping in conditions.
Otherwise, it must be enclosed in double quotation marks. In this case, the character \ (backslash) is treated as an escape character within the string, causing the following character or characters to be treated specially:
| \n | is replaced by a newline |
| \r | is replaced by a carriage return |
| \t | is replaced by a tab |
Backslash followed by up to three octal digits is replaced by the character specified by those digits, and \x followed by up to two hexadecimal digits is treated similarly. Backslash followed by any other character is replaced by the second character, so that in particular, \" becomes " and \\ becomes \. A data item enclosed in double quotes can be continued onto the next line by ending the first line with a backslash. Any leading white space at the start of the continuation line is ignored.
In addition to the escape character processing that occurs when strings are enclosed in quotes, most data values are also subject to string expansion (as described in the next section), in which case the characters $ and \ are also significant. This means that if a single backslash is actually required in such a string, and the string is also quoted, \\\\ has to be entered.
The maximum permitted length of a data string, before expansion, is 1024 characters.
Most data values are expanded before use. Expansion consists of replacing substrings beginning with $ with other text. The full expansion facilities available in Exim are extensive. If you want to know everything that Exim can do with strings, you should consult the chapter on string expansion in the Exim documentation.
In filter files, by far the most common use of string expansion is the substitution of the contents of a variable. For example, the substring
$reply_address
is replaced by the address to which replies to the message should be sent. If such a variable name is followed by a letter or digit or underscore, it must be enclosed in curly brackets (braces), for example,
${reply_address}
If a $ character is actually required in an expanded string, it must be escaped with a backslash, and because backslash is also an escape character in quoted input strings, it must be doubled in that case. The following two examples illustrate two different ways of testing for a $ character in a message:
if $message_body contains \$ then ... if $message_body contains "\\$" then ...
You can prevent part of a string from being expanded by enclosing it between two occurrences of \N. For example,
if $message_body contains \N$$$$\N then ...
tests for a run of four dollar characters.
A complete list of the available variables is given in the Exim documentation. This shortened list contains the ones that are most likely to be useful in personal filter files:
$body_linecount: The number of lines in the body of the message.
$home: In conventional configurations, this variable normally contains the user's home directory. The system administrator can, however, change this.
$local_part: The part of the email address that precedes the @ sign normally the user's login name. If support for multiple personal mailboxes is enabled (see section 3.29 below) and a prefix or suffix for the local part was recognized, it is removed from the string in this variable.
$local_part_prefix: If support for multiple personal mailboxes is enabled (see section 3.29 below), and a local part prefix was recognized, this variable contains the prefix. Otherwise it contains an empty string.
$local_part_suffix: If support for multiple personal mailboxes is enabled (see section 3.29 below), and a local part suffix was recognized, this variable contains the suffix. Otherwise it contains an empty string.
$message_body: The initial portion of the body of the message. By default, up to 500 characters are read into this variable, but the system administrator can configure this to some other value. Newlines in the body are converted into single spaces.
$message_body_end: The final portion of the body of the message, formatted and limited in the same way as $message_body.
$message_body_size: The size of the body of the message, in bytes.
$message_headers: The header lines of the message, concatenated into a single string, with newline characters between them.
$message_id: The message's local identification string, which is unique for each message handled by a single host.
$message_size: The size of the entire message, in bytes.
$original_local_part: When an address that arrived with the message is being processed, this contains the same value as the variable $local_part. However, if an address generated by an alias, forward, or filter file is being processed, this variable contains the local part of the original address.
$reply_address: The contents of the Reply-to: header, if the message has one; otherwise the contents of the From: header. It is the address to which normal replies to the message should be sent.
$return_path: The return path that is, the sender field that will be transmitted as part of the message's envelope if the message is sent to another host. This is the address to which delivery errors are sent. In many cases, this variable has the same value as $sender_address, but if, for example, an incoming message to a mailing list has been expanded, $return_path may have been changed to contain the address of the list maintainer.
$sender_address: The sender address that was received in the envelope of the message. This is not necessarily the same as the contents of the From: or Sender: header lines. For delivery error messages (bounce messages) there is no sender address, and this variable is empty.
$tod_full: A full version of the time and date, for example: Wed, 18 Oct 1995 09:51:40 +0100. The timezone is always given as a numerical offset from GMT.
$tod_log: The time and date in the format used for writing Exim's log files, without the timezone, for example: 1995-10-12 15:32:29.
$tod_zone: The local timezone offset, for example: +0100.
There is a special set of expansion variables containing the header lines of the message being processed. These variables have names beginning with $header_ followed by the name of the header line, terminated by a colon. For example,
$header_from: $header_subject:
The whole item, including the terminating colon, is replaced by the contents of the message header line. If there is more than one header line with the same name, their contents are concatenated. For header lines whose data consists of a list of addresses (for example, From: and To:), a comma and newline is inserted between each set of data. For all other header lines, just a newline is used.
Leading and trailing white space is removed from header line data, and if there are any MIME words that are encoded as defined by RFC 2047 (because they contain non-ASCII characters), they are decoded and translated, if possible, to a local character set. Translation is attempted only on operating systems that have the iconv() function. This makes the header line look the same as it would when displayed by an MUA. The default character set is ISO-8859-1, but this can be changed by means of the headers command (see below).
If you want to see the actual characters that make up a header line, you can specify $rheader_ instead of $header_. This inserts the raw header line, unmodified.
There is also an intermediate form, requested by $bheader_, which removes leading and trailing space and decodes MIME words, but does not do any character translation. If an attempt to decode what looks superficially like a MIME word fails, the raw string is returned. If decoding produces a binary zero character, it is replaced by a question mark.
The capitalization of the name following $header_ is not significant. Because any printing character except colon may appear in the name of a message's header (this is a requirement of RFC 2822, the document that describes the format of a mail message) curly brackets must not be used in this case, as they will be taken as part of the header name. Two shortcuts are allowed in naming header variables:
The initiating $header_, $rheader_, or $bheader_ can be abbreviated to $h_, $rh_, or $bh_, respectively.
The terminating colon can be omitted if the next character is white space. The white space character is retained in the expanded string. However, this is not recommended, because it makes it easy to forget the colon when it really is needed.
If the message does not contain a header of the given name, an empty string is substituted. Thus it is important to spell the names of headers correctly. Do not use $header_Reply_to when you really mean $header_Reply-to.
There are ten user variables with names $n0 $n9 that can be incremented by the add command (see section 3.10). These can be used for scoring messages in various ways. If Exim is configured to run a system filter on every message, the values left in these variables are copied into the variables $sn0 $sn9 at the end of the system filter, thus making them available to users' filter files. How these values are used is entirely up to the individual installation.
The contents of your filter file should not make any assumptions about the current directory. It is best to use absolute paths for file names; you can normally make use of the $home variable to refer to your home directory. The save command automatically inserts $home at the start of non-absolute paths.
When in the course of delivery a message is processed by a filter file, what happens next, that is, after the whole filter file has been processed, depends on whether the filter has set up any significant deliveries or not. If there is at least one significant delivery, the filter is considered to have handled the entire delivery arrangements for the current address, and no further processing of the address takes place. If, however, no significant deliveries have been set up, Exim continues processing the current address as if there were no filter file, and typically sets up a delivery of a copy of the message into a local mailbox. In particular, this happens in the special case of a filter file containing only comments.
The delivery commands deliver, save, and pipe are by default significant. However, if such a command is preceded by the word unseen, its delivery is not considered to be significant. In contrast, other commands such as mail and vacation do not count as significant deliveries unless preceded by the word seen.
The filter commands which are described in subsequent sections are listed below, with the section in which they are described in brackets:
| add | increment a user variable (section 3.10) |
| deliver | deliver to an email address (section 3.11) |
| fail | force delivery failure (sysadmin use) (section 3.18) |
| finish | end processing (section 3.16) |
| freeze | freeze message (sysadmin use) (section 3.19) |
| headers | set the header character set (section 3.20) |
| if | test condition(s) (section 3.21) |
| logfile | define log file (section 3.15) |
| logwrite | write to log file (section 3.15) |
| send a reply message (section 3.14) | |
| pipe | pipe to a command (section 3.13) |
| save | save to a file (section 3.12) |
| testprint | print while testing (section 3.17) |
| vacation | tailored form of mail (section 3.14) |
In addition, when Exim's filtering facilities are being used as a system filter, the fail, freeze, and headers commands are available. However, since they are usable only by the system administrator and not by ordinary users, they are described in the main Exim specification rather than in this document.
add <number> to <user variable>
e.g. add 2 to n3
There are 10 user variables of this type, and their values can be obtained by the normal expansion syntax (for example $n3) in other commands. At the start of filtering, these variables all contain zero. Both arguments of the add command are expanded before use, making it possible to add variables to each other. Subtraction can be obtained by adding negative numbers.
deliver <mail address>
e.g. deliver "Dr Livingstone <David@somewhere.africa.example>"
This provides a forwarding operation. The message is sent on to the given address, exactly as happens if the address had appeared in a traditional .forward file. If you want to deliver the message to a number of different addresses, you can use more than one deliver command (each one may have only one address). However, duplicate addresses are discarded.
To deliver a copy of the message to your normal mailbox, your login name can be given as the address. Once an address has been processed by the filtering mechanism, an identical generated address will not be so processed again, so doing this does not cause a loop.
However, if you have a mail alias, you should not refer to it here. For example, if the mail address L.Gulliver is aliased to lg103 then all references in Gulliver's .forward file should be to lg103. A reference to the alias will not work for messages that are addressed to that alias, since, like .forward file processing, aliasing is performed only once on an address, in order to avoid looping.
Following the new address, an optional second address, preceded by errors_to may appear. This changes the address to which delivery errors on the forwarded message will be sent. Instead of going to the message's original sender, they go to this new address. For ordinary users, the only value that is permitted for this address is the user whose filter file is being processed. For example, the user lg103 whose mailbox is in the domain lilliput.example could have a filter file that contains
deliver jon@elsewhere.example errors_to lg103@lilliput.example
Clearly, using this feature makes sense only in situations where not all messages are being forwarded. In particular, bounce messages must not be forwarded in this way, as this is likely to create a mail loop if something goes wrong.
save <file name>
e.g. save $home/mail/bookfolder
This causes a copy of the message to be appended to the given file (that is, the file is used as a mail folder). More than one save command may appear; each one causes a copy of the message to be written to its argument file, provided they are different (duplicate save commands are ignored).
If the file name does not start with a / character, the contents of the $home variable are prepended, unless it is empty. In conventional configurations, this variable is normally set in a user filter to the user's home directory, but the system administrator may set it to some other path. In some configurations, $home may be unset, in which case a non-absolute path name may be generated. Such configurations convert this to an absolute path when the delivery takes place. In a system filter, $home is never set.
The user must of course have permission to write to the file, and the writing of the file takes place in a process that is running as the user, under the user's primary group. Any secondary groups to which the user may belong are not normally taken into account, though the system administrator can configure Exim to set them up. In addition, the ability to use this command at all is controlled by the system administrator it may be forbidden on some systems.
An optional mode value may be given after the file name. The value for the mode is interpreted as an octal number, even if it does not begin with a zero. For example:
save /some/folder 640
This makes it possible for users to override the system-wide mode setting for file deliveries, which is normally 600. If an existing file does not have the correct mode, it is changed.
An alternative form of delivery may be enabled on your system, in which each message is delivered into a new file in a given directory. If this is the case, this functionality can be requested by giving the directory name terminated by a slash after the save command, for example
save separated/messages/
There are several different formats for such deliveries; check with your system administrator or local documentation to find out which (if any) are available on your system. If this functionality is not enabled, the use of a path name ending in a slash causes an error.
pipe <command>
e.g. pipe "$home/bin/countmail $sender_address"
This command sets up delivery to a specified command using a pipe. Remember, however, that no deliveries are done while the filter is being processed. All deliveries happen later on. Therefore, the result of running the pipe is not available to the filter.
When the deliveries are done, a separate process is run, and a copy of the message is passed on its standard input. The process runs as the user, under the user's primary group. Any secondary groups to which the user may belong are not normally taken into account, though the system administrator can configure Exim to set them up. More than one pipe command may appear; each one causes a copy of the message to be written to its argument pipe, provided they are different (duplicate pipe commands are ignored).
When the time comes to transport the message, the command supplied to pipe is split up by Exim into a command name and a number of arguments. These are delimited by white space except for arguments enclosed in double quotes, in which case backslash is interpreted as an escape, or in single quotes, in which case no escaping is recognized. Note that as the whole command is normally supplied in double quotes, a second level of quoting is required for internal double quotes. For example:
pipe "$home/myscript \"size is $message_size\""
String expansion is performed on the separate components after the line has been split up, and the command is then run directly by Exim; it is not run under a shell. Therefore, substitution cannot change the number of arguments, nor can quotes, backslashes or other shell metacharacters in variables cause confusion.
Documentation for some programs that are normally run via this kind of pipe often suggest that the command should start with
IFS=" "
This is a shell command, and should not be present in Exim filter files, since it does not normally run the command under a shell.
However, there is an option that the administrator can set to cause a shell to be used. In this case, the entire command is expanded as a single string and passed to the shell for interpretation. It is recommended that this be avoided if at all possible, since it can lead to problems when inserted variables contain shell metacharacters.
The default PATH set up for the command is determined by the system administrator, usually containing at least /usr/bin so that common commands are available without having to specify an absolute file name. However, it is possible for the system administrator to restrict the pipe facility so that the command name must not contain any / characters, and must be found in one of the directories in the configured PATH. It is also possible for the system administrator to lock out the use of the pipe command altogether.
When the command is run, a number of environment variables are set up. The complete list for pipe deliveries may be found in the Exim reference manual. Those that may be useful for pipe deliveries from user filter files are:
| DOMAIN | the domain of the address |
| HOME | your home directory |
| LOCAL_PART | see below |
| LOCAL_PART_PREFIX | see below |
| LOCAL_PART_SUFFIX | see below |
| LOGNAME | your login name |
| MESSAGE_ID | the message's unique id |
| PATH | the command search path |
| RECIPIENT | the complete recipient address |
| SENDER | the sender of the message |
| SHELL | /bin/sh |
| USER | see below |
LOCAL_PART, LOGNAME, and USER are all set to the same value, namely, your login id. LOCAL_PART_PREFIX and LOCAL_PART_SUFFIX may be set if Exim is configured to recognize prefixes or suffixes in the local parts of addresses. For example, a message addressed to pat-suf2@domain.example may cause user pat's filter file to be run. If this sets up a pipe delivery, LOCAL_PART_SUFFIX is -suf2 when the pipe command runs. The system administrator has to configure Exim specially for this feature to be available.
If you run a command that is a shell script, be very careful in your use of data from the incoming message in the commands in your script. RFC 2822 is very generous in the characters that are legally permitted to appear in mail addresses, and in particular, an address may begin with a vertical bar or a slash. For this reason you should always use quotes round any arguments that involve data from the message, like this:
/some/command '$SENDER'
so that inserted shell meta-characters do not cause unwanted effects.
Remember that, as was explained earlier, the pipe command is not run at the time the filter file is interpreted. The filter just defines what deliveries are required for one particular addressee of a message. The deliveries themselves happen later, once Exim has decided everything that needs to be done for the message.
A consequence of this is that you cannot inspect the return code from the pipe command from within the filter. Nevertheless, the code returned by the command is important, because Exim uses it to decide whether the delivery has succeeded or failed.
The command should return a zero completion code if all has gone well. Most non-zero codes are treated by Exim as indicating a failure of the pipe. This is treated as a delivery failure, causing the message to be returned to its sender. However, there are some completion codes which are treated as temporary errors. The message remains on Exim's spool disk, and the delivery is tried again later, though it will ultimately time out if the delivery failures go on too long. The completion codes to which this applies can be specified by the system administrator; the default values are 73 and 75.
The pipe command should not normally write anything to its standard output or standard error file descriptors. If it does, whatever is written is normally returned to the sender of the message as a delivery error, though this action can be varied by the system administrator.
There are two commands which cause the creation of a new mail message, neither of which count as a significant delivery unless the command is preceded by the word seen. This is a powerful facility, but it should be used with care, because of the danger of creating infinite sequences of messages. The system administrator can forbid the use of these commands altogether.
To help prevent runaway message sequences, these commands have no effect when the incoming message is a delivery error message, and messages sent by this means are treated as if they were reporting delivery errors. Thus they should never themselves cause a delivery error message to be returned. The basic mail-sending command is
mail [to <address-list>]
[cc <address-list>]
[bcc <address-list>]
[from <address>]
[reply_to <address>]
[subject <text>]
[extra_headers <text>]
[text <text>]
[[expand] file <filename>]
[return message]
[log <log file name>]
[once <note file name>]
[once_repeat <