Q0401: I need to have any mail for virt.dom.ain that doesn't match one of the aliases in /usr/lib/aliases.virt delivered to a particular address, for example, postmaster@virt.dom.ain.
A0401: Adding an asterisk to a search type causes Exim to look up ``*'' when the normal lookup fails. So if your aliasing router is something like this:
virtual: driver = redirect domains = virt.dom.ain data = ${lookup{$local_part}lsearch{/usr/lib/aliases.virt}} no_more
you should change lsearch to lsearch*, and put this in the alias file:
*: postmaster@virt.dom.ain
This solution has the feature that if there are several unknown addresses in the same message, only one copy gets sent to the postmaster, because of Exim's normal de-duplication rules.
NOTE: This solution works only if there is also an entry for postmaster in the alias file, ultimately resolving to an address that is not in virt.dom.ain. See also Q0434.
Q0402: How do I arrange for all incoming email for *@some.domain to go into one pop3 mail account? The customer doesn't want to add a list of specific local parts to the system.
A0402: Set up a special transport that writes to the mailbox like this:
special_transport: driver = appendfile file = /pop/mailbox envelope_to_add return_path_add delivery_date_add user = exim
The file will be written as the user exim. Then arrange to route all mail for that domain to that transport, with a router like this:
special_router: driver = accept domains = some.domain transport = special_transport
Q0403: How do I configure Exim to send messages for unknown local users to a central server?
A0403: Assuming you are using something like the default configuration, where local users are processed by the later routers, you should add the following router at the end;
unknown: driver = manualroute transport = remote_smtp route_list = * server.host.name no_verify
Q0404: How can I arrange for messages submitted by (for example) Majordomo to be handled specially?
A0404: You can use the condition option on a router, with a setting such as
condition = ${if and {{eq {$sender_host_address}{}} \ {eq {$sender_ident}{majordom}}} {yes}{no}}
This first tests for a locally-submitted message, by ensuring there is no sending host address, and then it checks the identity of the user that ran the submitting process.
Q0405: On a host that accepts mail for several domains, do I have to use fully qualified addresses in /etc/aliases or do I have to set up an alias file for each domain?
A0405: You can do it either way. The default aliasing router contains this line:
data = ${lookup{$local_part}lsearch{/etc/aliases}}
which is what does the actual lookup. To make it look up the complete address instead of just the local part, use
data = ${lookup{$local_part@$domain}lsearch{/etc/aliases}}
If you want to use a separate file for each domain, use
data = ${lookup{$local_part}lsearch{/etc/aliases/$domain}}
Q0406: Some of my users are using the .forward to pipe to a shell command which appends to the user's INBOX. How can I forbid this?
A0406: If you allow your users to run shells in pipes, you cannot control which commands they run or which files they write to. However, you should point out to them that writing to an INBOX by arbitrary commands is not interlocked with the MTA and MUAs, and is liable to mess up the contents of the file.
If a user simply wants to choose a specific file for the delivery of messages, this can be done by putting a file name in a .forward file rather than using a pipe, or by using the save command in an Exim filter file.
You can set forbid_pipe on the router, but that will prevent them from running any pipe commands at all. Alternatively, you can restrict which commands they may run in their pipes by setting the allow_commands and/or restrict_to_path options in the address_pipe transport.
Q0407: How can I arrange for a default value when using a query-style lookup such as LDAP or NIS+ to handle aliases?
A0407: Use a second query in the failure part of the original lookup, like this:
data = ${lookup ldap\ {ldap://x.y.z/l=yvr?aliasaddress?sub?(&(mail=$local_part@$domain))}\ {$value}\ {\ ${lookup ldap \ {ldap://x.y.z/l=yvr?aliasaddress?sub?(&(mail=default@$domain))}}\ }}
Of course, if the default is a fixed value you can just include it directly.
Q0408: If I don't fully qualify the addresses in a virtual domain's alias file then mail to aliases which also match the local domain get delivered to the local domain.
A0408: Set the qualify_preserve_domain option on the redirect router.
Q0409: I want mail for any local part at certain virtual domains to go to a single address for each domain.
A0409: One way to to this is
virtual: driver = redirect data = ${lookup{$domain}lsearch{/etc/virtual}}
The /etc/virtual file contains a list of domains and the addresses to which their mail should be sent. For example:
domain1: postmaster@some.where.else domain2: joe@xyz.plc
If the number of domains is large, using a DBM or cdb file would be more efficient. If the lookup fails to find the domain in the file, the value of the data option is empty, causing the router to decline.
Q0410: How can I make Exim look in the alias NIS map instead of /etc/aliases?
A0410: The default configuration does not use NIS (many hosts don't run it). You need to change this line in the system_aliases router:
data = ${lookup{$local_part}lsearch{/etc/aliases}}
Change it to
data = ${lookup{$local_part}nis{mail.aliases}}
If you want to use /etc/aliases as well as NIS, put this router (with a different name) before or after the default one, depending on which data source you want to take precedence.
Q0411: Why will Exim deliver a message locally to any username that is longer than 8 characters as long as the first 8 characters match one of the local usernames?
A0411: The problem is in your operating system. Exim just calls the getpwnam() function to test a local part for being a local login name. It does not presume to guess the maximum length of user name for the underlying operating system. Many operating systems correctly reject names that are longer than the maximum length; yours is apparently deficient in this regard. To cope with such systems, Exim has an option called max_user_name_length which you can set to the maximum allowed length.
Q0412: Why am I seeing the error bad mode (100664) for /home/test/.forward? I've looked through the documentation but can't see anything to suggest that Exim has to do anything other than read the .forward file.
A0412: For security, Exim checks for mode bits that shouldn't be set, by default 022. You can change this by setting the modemask option of the redirect router that is handling .forward files.
Q0413: When a user's .forward file is syntactially invalid, Exim defers delivery of all messages to that user, which sometimes include the user's own test messages. Can it be told to ignore the .forward file and/or inform the user of the error?
A0413: Setting skip_syntax_errors on the redirect router causes syntax errors to be skipped. When dealing with users' .forward files it is best to combine this with a setting of syntax_errors_to in order to send a message about the error to the user. However, to avoid an infinite cascade of messages, you have to be able to send to an address that bypasses .forward file processing. This can be done by including a router like this one
real_localuser: driver = accept check_local_user transport = local_delivery prefix = real-
before the redirect router that handles .forward files. This will do an ordinary local delivery without .forward processing, if the local part is prefixed by real-. You can then set something like the following options on the redirect router:
skip_syntax_errors syntax_errors_to = real-$local_part@$domain syntax_errors_text = "\ This is an automatically generated message. An error has been \ found\nin your .forward file. Details of the error are reported \ below. While\nthis error persists, messages addressed to you will \ get delivered into\nyour normal mailbox and you will receive a \ copy of this message for\neach one."
A final tidying setting to go with this is a rewriting rule that changes real-username into just username in the headers of the message:
\N^real-([^@]+)@your\.dom\.ain$\N $1@your.dom.ain h
This means that users won't ever see the real- prefix, unless they look at the Envelope-To: header.
Q0414: I have set caseful_local_part on the routers that handle my local domain because my users have upper case letters in their login names, but incoming mail now has to use the correct case. Can I relax this somehow?
A0414: If you really have to live with caseful user names but want incoming local parts to be caseless, then you have to maintain a file, indexed by the lower case forms, that gives the correct case for each login, like this:
admin: Admin steven: Steven mcdonald: McDonald lamanch: LaManche ...
and at the start of the routers that handle your local domain, put one like this:
set_case_router: driver = redirect data = ${lookup{${lc:$local_part}}lsearch{/the/file}} qualify_preserve_domain
For efficiency, you should also set the redirect_router option to cause processing of the changed address to begin at the next router. If you are otherwise using the default configuration, the setting would be
redirect_router = system_aliases
If there are lots of users, then a DBM or cdb file would be more efficient than a linear search. If you are handling several domains, you will have to extend this configuration to cope appropriately.
Q0415: Can I use my existing alias files and forward files as well as procmail and effectively drop in Exim in place of Sendmail ?
A0415: Yes, as long as your alias and forward files don't assume that pipes are going to run under a shell. If they do, you either have to change them, or configure Exim to use a shell (which it doesn't by default).
Q0416: What is quickest way to set up Exim so any message sent to a non-existing user would bounce back with a different message, based on the name of non-existing user?
A0416: Place this router last, so that it catches any local addresses that are not otherwise handled:
non_exist: driver = accept transport = non_exist_reply no_verify
Then add the following transport to the transports section:
non_exist_reply: driver = autoreply user = exim to = $sender_address subject = User does not exist text = You sent mail to $local_part. That's not a valid user here. \ The subject was: $subject.
If you want to pick up a message from a file, you can use the file option (use file_expand if you want its contents expanded).
Q0417: What do I need to do to make Exim handle /usr/ucb/vacation processing automatically, so that people could just create a .vacation.msg file in their home directory and not have to edit their .forward file?
A0417: Add a new router like this, immediately before the normal localuser router:
vacation: driver = accept check_local_user require_files = $home/.vacation.msg transport = vacation_transport unseen
and a matching new transport like this:
vacation_transport: driver = pipe command = /usr/ucb/vacation $local_part
However, some versions of /usr/ucb/vacation do not work properly unless the DBM file(s) it uses are created in advance - it won't create them itself. You also need a way of removing them when the vacation is over.
Another possibility is to use a fixed filter file which is run whenever .vacation.msg exists, for example:
vacation: driver = redirect check_local_user require_files = $home/.vacation.msg file = /some/central/filter allow_filter
The filter file should use the if personal check before sending mail, to avoid generating automatic responses to mailing lists. If sending a message is all that it does, this doesn't count as a ``significant'' delivery, so the original message goes on to be delivered as normal.
Yet another possibility is to make use of Exim's autoreply transport, and not use /usr/ucb/vacation at all.
Q0418: I want to use a default entry in my alias file to handle unknown local parts, but it picks up the local parts that the aliases generate. For example, if the alias file is
luke.skywalker: luke ls: luke *: postmaster
then messages addressed to luke.skywalker end up at postmaster.
A0418: The default mechanism works best with virtual domains, where the generated address is not in the same domain. If you just want to pick up all unknown local parts and send them to postmaster, an easier way to do it is to put this as your last router:
unknown: driver = redirect data = postmaster no_verify
Another possibility is to put the redirect router for these aliases after all the other routers, so that local parts which are user names get picked off first. You will need to have two aliasing routers if there are some local parts (e.g. root) which are login names, but which you want to handle as aliases.
Q0419: I have some obsolete domains which people have been warned not to use any more. How can I arrange to delete any mail that is sent to them?
A0419: To reject them at SMTP time, with a customized error message, place statments like this in the ACL:
deny message = The domain $domain is obsolete domains = lsearch;/etc/exim/obsolete.domains
For messages that don't arrive over SMTP, you can use a router like this to bounce them:
obsolete: driver = redirect domains = lsearch;/etc/exim/obsolete.domains allow_fail data = :fail: the domain $domain is obsolete
If you just want to throw away mail to those domains, accept them at SMTP time, and use a router like this:
obsolete: domains = lsearch;/etc/exim/obsolete.domains data = :blackhole:
Q0420: How can I arrange that mail addressed to anything@something.mydomain.com gets delivered to something@mydomain.com?
A0420: Set up a router like this:
user_from_domain: driver = redirect data = ${if match{$domain}{\N^(.+)\.mydomain\.com$\N}\ {$1@mydomain.com}}
Q0421: I can't get a regular expression to work in a local_parts option on one of my routers.
A0421: Have you remembered to protect any backslash and dollar characters in your regex from unwanted expansion? The easiest way is to use the \N facility, like this:
local_parts = \N^0740\d{6}\N
Q0422: How can I arrange for all addresses in a group of domains *.example.com to share the same alias file? I have a number of such groups.
A0422: For a single group you could just hard wire the file name into a router that had
domains = *.example.com
set, to restrict it to the relevant domains. For a number of such groups you can create a file containing the domains, like this:
*.example1.com example1.com *.example2.com example2.com ...
Then create a router like this
domain_aliases: driver = redirect domains = partial-lsearch;/that/file data = ${lookup{$local_part}lsearch*{/etc/aliases.d/$domain_data}}
The variable $domain_data contains the data that was looked up when the domains option was matched, i.e. example1.com, example2.com, etc. in this case.
Q0423: Some of our users have no home directories; the field in the password file contains /no/home/dir. This causes the error failed to stat /no/home/dir (No such file or directory) when Exim tries to look for a .forward file, and the delivery is deferred.
A0423: There are two issues involved here:
(1) With the default configuration, you are asking Exim to check for a .forward file in the user's home directory. If no file is found, Exim tries to stat() the home directory. This is so that it will notice a missing NFS home directory, and not treat it as if the .forward file did not exist. This stat() is failing when the home directory really doesn't exist. You should arrange for the userforward router not to run for these special users, by adding this line:
condition = ${if eq {$home}{/no/home/dir}{no}{yes}}
(2) If you use check_local_user on another router to route to a local transport (again, this is what is in the default configuration), you will also have to specify a current directory for the transport, because by default it makes the home directory current. This is easily done by adding
current_directory = /
to the transport or
transport_current_directory = /
to the router. Or you can add home_directory to the transport, because the current directory defaults to the home directory.
Q0424: How can I disable Exim's de-duplication features? I want it to do two deliveries if two different aliases expand to the same address.
A0424: This is not possible. Duplication has other ramifications other than just (in)convenience. Consider:
. Message is addressed to A and to B.
. Both A and B are aliased to C.
. Without de-duplication, two deliveries to C are scheduled.
. One delivery happens, Exim records that it has delivered the message to C.
. The next delivery fails (C's mailbox is over quota, say).
Next time round, Exim wants to know if it has already delivered to C or not, before scheduling a new delivery. Has it? Obviously, if duplicate deliveries are supported, it has to remember not only that it has delivered to C but also the ``history'' of how that delivery happened - in effect an ancestry list back to the original envelope address. This it does not do, and changing it to work in that way would be a lot of work and a big upheaval.
The best way to get duplicate deliveries if you want them is not to use aliases, but to route the addresses directly to a transport, e.g.
duplicates: driver = accept local_parts = lsearch;/etc/list/of/special/local/parts transport = local_delivery user = exim
Q0425: My users' mailboxes are distributed between several servers according to the first letter of the user name. All the servers receive incoming mail at random. I would like to have the same configuration file for all the servers, which does local delivery for the mailboxes it holds, and sends other addresses to the correct other server. Is this possible?
A0425: It is easiest if you arrange for all the users to have password entries on all the servers. This means that non-existent users can be detected at the first server they reach. Set up a file containing a mapping from the first letter of the user names to the servers where their mailboxes are held. For example:
a: server1 b: server1 c: server2 ...
Before the normal localuser router, place the following router:
mailbox_host: driver = manualroute check_local_user transport = remote_smtp route_list = * ${lookup{${substr_0_1:$local_part}}lsearch{/etc/mapfile}} self = pass
This router checks for a local account, then looks up the host from the first character of the local part. If the host is not the local host, the address is routed to the remote_smtp transport, and sent to the correct host. If the host is the local host, the self option causes the router to pass the address to the next router, which does a local delivery.
The router is skipped for local parts that are not the names of local users, and so these addresses fail.
Q0426: One of the things I want to set up is for anything@onedomain to forward to anything@anotherdomain. I tried adding $local_part@anotherdomain to my aliases but it did not expand - it sent it to that literal address.
A0426: If you want to do it that way, you can use the expand operator on the lookup used in the data option of the redirect router. For example:
data = ${expand:${lookup{$local_part}lsearch*{/etc/aliases}}}
Another approach is to use a router like this:
forwarddomain: driver = redirect domains = onedomain data = $local_part@anotherdomain
The value of data can, of course, be more complicated, involving lookups etc. if you have lots of different cases.
Q0427: How can I have an address looked up in two different alias files, and delivered to all the addresses that are found?
A0427: Use a router like this:
multi_aliases: driver = redirect data = ${lookup{$local_part}lsearch{/etc/aliases1}\ {$value${lookup{$local_part}lsearch{/etc/aliases2}{,$value}}}\ {${lookup{$local_part}lsearch{/etc/aliases2}{$value}fail}}}\
If the first lookup succeeds, the result is its data, followed by the data from the second lookup, if any, separated by a comma. If the first lookup fails, the result is the data from the third lookup (which also looks in the second file), but if this also fails, the entire expansion is forced to fail, thereby causing the router to decline.
Another approach is to use two routers, with the first re-generating the original local part when it succeeds. This won't get processed by the same router again. For example:
multi_aliases1: driver = redirect data = ${lookup{$local_part}lsearch{/etc/aliases1}{$value,$local_part}}
multi_aliases2: data = ${lookup{$local_part}lsearch{/etc/aliases2}}
This scales more easily to three or more alias files.
Q0428: I've converted from Sendmail, and I notice that Exim doesn't make use of the owner- entries in my alias file to change the sender address in outgoing messages to a mailing list.
A0428: If you have an alias file with entries like this:
somelist: a@b, c@d, ... owner-somelist: postmaster
Sendmail assumes that the second entry specifies a new sender address for the first. Exim does not make this assumption. However, you can make it take the same action, by adding
errors_to = owner-$local_part@whatever.domain
to the configuration for your aliasing router. This is fail-safe, because Exim verifies a new sender address before using it. Thus, the change of sender address occurs only when the owner entry exists.
Q0429: I would like to deliver mail addressed to a given domain to local mailboxes, but also to generate messages to the envelope senders.
A0429: You can do this with an ``unseen'' router and an autoreply transport, along the following lines:
# Router auto_warning_r: driver = accept check_local_user domains = <domains you want to do this for> condition = ${if eq{$sender_address}{}{no}{yes}} transport = warning_t no_verify unseen
Place this router immediately before the normal localuser router. The unseen option means that the address is still passed on to the next router. The transport is configured like this:
# Transport warning_t: driver = autoreply file = /usr/local/mail/warning.txt file_expand from = postmaster@your.domain to = $sender_address user = exim subject = Re: Your mail to $local_part@$domain
Note the use of the condition option to avoid attempting to send a message when there is no sender (that is, when the incoming message is a bounce message). You can of course extend this to include other conditions. If you want to log the sending of messages, you can add
log = /some/file
to the transport and also make use of the once option if you want to send only one message to each sender.
Q0430: Whenever Exim tries to route a local address, it gives a permission denied error for the .forward file, like this:
1998-08-10 16:55:32 0z5y2W-0000B8-00 == xxxx@yyy.zzz <xxxx@yyy.zz> D=userforward defer (-1): failed to open /home/xxxx/.forward (userforward router): Permission denied (euid=1234 egid=101)
A0430: Have you remembered to make Exim setuid root?
Q0431: How do I configure Exim to allow arbitrary extensions in local parts, of the form +extension?
A0431: Add this pre-condition to the relevant router:
local_part_suffix = +*
If you want the extensions to be optional, also add the option
local_part_suffix_optional
When the router runs, $local_part contains the local part with the extension removed, and the extension (if any) is in $local_part_suffix. If you have set check_local_user, the test is carried out after the extension is removed.
Q0432: I use NIS for my user data. How can I stop Exim rejecting mail when my NIS servers are being restarted?
A0432: Exim doesn't know that you are using NIS; it just calls the getpwnam() function, which is routed by nsswitch. Unfortunately, getpwnam() was never designed to be routed through NIS, and it returns NULL if the entry is not found or if the connection to the NIS server fails. This means that Exim cannot tell the difference between ``no such user'' and ``NIS is down''.
Crutches to help with this problem are finduser_retries in Exim, and nscd on the Unix side, but they are not perfect, and mail can still be lost. However, Nico Erfurth pointed out that you can create a router for Exim that tests for the availability of NIS, and force a defer if NIS is not running:
check_nis: driver = redirect data = ${lookup {$local_part} nis {passwd}{}}
This should be placed before any router that makes any use of NIS, typically at the start of your local routers. How does it work? If your NIS server is reachable, the lookup will take place, and whether it succeeds or fails, the result is an empty strting. This causes the router to decline, and the address is passed to the following routers. If your NIS server is down, the lookup defers, and this causes the router to defer. A verification of an incoming address gets a temporary rejection, and a delivery is deferred till later.
Q0433: How can I arrange for a single address to be processed by both redirect and accept?
A0433: Check out the unseen option.
Q0434: How can I redirect all local parts that are not in my system aliases to a single address? I tried using an asterisk in the system alias file with an lsearch* lookup, but that send all messages to the default address.
A0434: If your alias file generates addresses in the local domain, they are also processed as a potential aliases. For example, suppose this is your alias file:
caesar: jc anthony: ma *: brutus
The local part caesar is aliased to jc, but that address is then reprocessed by the routers. As the address is in the local domain, the alias file is again consulted, and this time the default matches. In fact after the second aliasing, brutus is also processed again from the start, and is aliased to itself. However, this happens only once, because the next time, Exim notices that the aliasing router has already processed brutus, so the router is skipped in order to avoid looping.
There are several ways of solving this problem; which one you use depends on your aliasing data.
(1) If the result of aliasing is always a local user name, that is, aliasing never generates another alias, you can use the redirect_router option on the router to specify that processing the generated addresses must start at the next router. For example:
redirect_router = userforward
assuming that the next router is called userforward. This ensures that there is at most one pass through the aliasing router.
(2) If you cannot rely on aliases generating non-aliases, it is often easier not to use a default alias, but instead to place a router such as the one below after all the other local routers (for the relevant domains):
catch_unknown: driver = redirect domains = ... data = brutus@$domain
Note that the default aliasing technique works more successfully for virtual domains (see Q0401) because the generated address for the default is not usually in the same virtual domain as the incoming address.
Q0435: My alias file contains fully qualified addresses as keys, and some wildcard domains in the form @foo.bar. Can Exim handle these?
A0435: You can handle fully qualified addresses with this router:
qualified_aliases: driver = redirect data = ${lookup{$local_part@$domain}lsearch{/etc/aliases}}
(Add any other options you need for the redirect router.) Place this router either before or after the default aliases router that looks up the local part only. (Or, if you have no unqualified aliases, replace the default router.)
To handle wildcards in the form @foo.bar you will need yet another router. (Wildcards of the form *@foo.bar can be handled by an lsearch*@ lookup.) Something like this:
wildcard_aliases: driver = redirect data = ${lookup{@$domain}lsearch{/etc/aliases}}
Place this after the routers that handle the more specific aliases.