The Exim FAQ Section 5

# The Exim FAQ

Contents Previous Next

## 5. FILTERING

Q0501: My filter isn't working. How can I test it?

A0501: Use the -bf option (-bF for a system filter) to test the basic operation of your filter. You can request debugging information for filtering only by adding `-d-all+filter` to the command.

Q0502: What I really need is the ability to obtain the result of a pipe command so that I can filter externally and redirect internally. Is this possible?

A0502: The result of a pipe command is not available to a filter, because Exim does not run any actual deliveries while filtering. It just sets up deliveries at this time. They all actually happen later. If you want to run pipes and examine their results, you need to set up a single delivery to a delivery agent such as procmail which provides this kind of facility.

An possible alternative is to use the `${run` expansion item to run an external command while filtering. In this case, you can make use of some of the results of the command.

Q0503: I received a message with a Subject: line that contained a non-printing character (a carriage return). This messed up my filter file. Is there a way to get round it?

A0503: Instead of `$h_subject:` use `${escape:$h_subject:}`

Q0504: I want to search for `$` in the subject line, but I can't seem to get the syntax.

A0504: Try one of these:

       if $h_subject: contains \$ then ...
       if $h_subject: contains "\\$" then ...

Q0505: My problem is that Exim replaces $local_part with an empty string in the system filtering. What's wrong or what did I miss?

A0505: A message may have many recipients. The system filter is run just once at the start of a delivery attempt. Consequently, it does not make sense to set $local_part. Which recipient should it be set to? However, you can access all the recipients from a system filter via the variable called $recipients.

Q0506: Using $recipients in a system filter gives me another problem: how can I do a string lookup if $recipients is a list of addresses?

A0506: Check out the section of the filter specification called Testing a list of addresses. If that doesn't help, you may have to resort to calling an embedded Perl interpreter - but that is expensive.

Q0507: What are the main differences between using an Exim filter and using procmail?

A0507: Exim filters and procmail provide different facilities. Exim filters run at routing time, before any deliveries are done. A filter is like a “.forward file with conditions”. One of the benefits is de-duplication. Another is that if you forward, you are forwarding the original message.

However, this does mean that pipes etc. are not run at filtering time, nor can you change the headers, because the message may have other recipients and Exim keeps only a single set of headers.

procmail runs at delivery time. This is for one recipient only, and so it can change headers, run pipes and check the results, etc. However, if it wants to forward, it has to create a new message containing a copy of the original message.

It's your choice as to which of these you use. You can of course use both.

Q0508: How can I allow the use of relative paths in users' filter files when the directories concerned are not available from the password data?

A0508: You need to be running Exim 4.11 or later. You can then specify a value for $home by setting the router_home_directory option on the redirect router.

For earlier releases, there is no way to specify the value of $home for a redirect router; it either comes from the password data as a result of `check_local_user`, or is unset.

Q0509: How can I set up a filter file to detect and block virus attachments?

A0509: Exim's filter facilities aren't powerful enough to do much more than very crude testing. Most people that want virus checking are nowadays using one of the separate scanning programs such as exiscan (see http://duncanthrax.net/exiscan/). There is some further information about scanning with Exim via http://www.timj.co.uk/linux/exim.php.

Q0510: Is it possible to write code for scanning messages in Python?

A0510: elspy is a layer of glue code that enables you to write Python code to scan email messages at SMTP time. elspy also includes a small Python library with common mail-scanning tools, including an interface to SpamAssassin and a simple but effective virus detector. You can optain elspy from http://elspy.sourceforge.net/.

Q0511: Whenever my system filter uses a `mail` command to send a message, I get the error User 0 set for address_reply transport is on the never_users list. What does this mean?

A0511: The system filter runs as root in Exim 4, unless you set `system_filter_user` to specify otherwise. When you set up a delivery direct from a system filter (an autoreply is a special kind of “delivery”) the transport runs as the same user, unless it has a `user` setting of its own. Normally, deliveries are not allowed to run as root as a security precaution; this is implemented by the `never_users` option.

The easiest solution is to add this to your configuration:

       system_filter_user = exim

The system filter then runs as exim instead of root. Alternatively, you can arrange for autoreplies from the system filter to use a special transport of their own, and set the `user` option on that transport.

Q0512: I'm trying to reference the Envelope-To: header in my filter, but $h_envelope-to: is always empty.

A0512: Envelope-To: is added at delivery time, by the transport. Therefore, the header doesn't exist at filter time. In a user filter, the values you probably want are in $original_local_part and $original_domain. In a system filter, the complete list of all envelope recipients is in $recipients.

Q0513: I want my system filter to freeze all mails greater than 500K in size, but to exclude those to a specific domain. However, I don't seem to be able to use $domain in a system filter.

A0513: You cannot do this in a system filter, because a single message may have multiple recipients, some in the special domain, and some not. That is also the reason why $domain is not set in a system filter.

If you want to take actions on a per-recipient basis, you have to do it in a router. However, freezing is not appropriate, because freezing stops all deliveries. You could, however, delay delivery to all but the special domains by using something like this:

       delay_if_too_big:
         driver = redirect
         domains = !the.special.domain
         condition = ${if >{$message_size}{500K}{yes}{no}}
         allow_defer
         data = :defer: message too big.

However, there isn't an easy way of “releasing” such messages at present.

Q0514: When I try to send to two addresses I get an error in the filter file malformed address: , e@fgh.com may not follow a@bcd.com. What is going on?

A0514: Have you got

       deliver "a@bcd.com, e@fgh.com"

in your filter? If so, that is your problem. You should have

       deliver a@bcd.com
       deliver e@fgh.com

Each `deliver` command expects just one address.

Contents Previous Next