Send all outgoing mail to a smart host.
The default configuration contains this router, which sends outgoing mail
directly to its destination, using a DNS lookup:
lookuphost:
driver = lookuphost
transport = remote_smtp
If you're an end user, you may want instead to send everything to your
ISP's mail server, to let it handle the routing and queueing. It's easy.
Suppose your ISP's mail server is called mail.myisp.com. All you
have to do is replace the default router with this one:
smarthost:
driver = domainlist
transport = remote_smtp
route_list = * mail.myisp.com byname
In that route_list setting, the asterisk means "for all remote
domains", and the byname means "look up the server's IP address
using the system's name-resolution function (gethostbyname)".
(If you want to avoid any kind of lookup, you can put the smart host's IP
address instead of the name, but you still need the byname.)
If your ISP has several mail servers, you can list them all:
route_list = * \
"mail1.myisp.com : \
mail2.myisp.com" \
byname
We are using backslashes here to continue the configuration lines, and we
have to put the colon-separated list of hosts in quotes, because it's got
spaces in it. One final trick in this case is to add
hosts_randomize
to the router. This tells Exim to sort the host list into a random order
each time it is used.
Save outgoing mail until a dial-up connection is made.
If you are running a dial-up host, you need to configure Exim so that it
does not try to deliver outgoing mail until you have connected to the Net.
(You probably also want to arrange for such mail to be delivered to a
smart host, as described above.) To stop Exim trying to do immediate
deliveries for remote domains, you must add the line
queue_remote_domains = *
to the first section of the configuration file. (In this context,
* means "all".) When Exim receives a message addressed to a
remote domain, it now just leaves it on the queue, and does not attempt to
deliver it. The other thing you must do is to stop Exim starting queue
runner processes automatically because you want to process the queue only
when dialed up. Somewhere in the boot scripts for your host there will be
a line of the form /usr/sbin/sendmail -bd -q30m, which starts up
the MTA daemon when you reboot. (The path name is historic; on an Exim
system, it will normally be a symbolic link to the Exim binary. On some
systems /usr/lib/sendmail is used.) The -q30m option
specifies that queue runners are started every 30 minutes; you should
remove this option from the command. Unless you are going to reboot, you
must now kill any existing Exim daemon and restart it. This normally can be
done by obeying (as root):
kill `cat /var/spool/exim/exim-daemon.pid`
Restart the daemon without the -q30m option:
/usr/sbin/sendmail -bd
So far, so good. You now have a system where all outgoing mail just sits on
the queue until some explicit action is taken. How do you get it delivered
when you dial up? The command that must be run is exim -qqff.
This is usually placed in a script that is automatically obeyed once the
connection has been made, but you can run it by hand if you want to.
However, you must either do this as root, or you must add your login
to the exim group in order to give yourself Exim administration
privileges.
Route all mail for a domain to a single mailbox.
How you do this depends on whether the single mailbox is remote or local,
and whether it is itself in the domain or not. Let's first take the simple
case where the host is handling only one local domain, and you want all
mail to be delivered into the mailbox /var/mail/incoming. All you
need to do is configure a single director like this:
all:
driver = smartuser
transport = incoming_delivery
Then create a corresponding transport:
incoming_delivery:
driver = appendfile
file = /var/mail/incoming
user = mail
You must supply a user setting to tell Exim which uid to run as
when writing to the file. Note that the two configuration snippets above
must be placed in the correct sections of the configuration file: the first
in the "directors" section, and the second in the "transports" section.
If you are handling several domains, and the relevant mailbox is not itself
in the special domain, it is more straightforward to handle this as a kind
of aliasing operation. Suppose the domain is onebox.domain.com and
its mail must be sent to postmaster@other.domain.com. Firstly, you
need to ensure that onebox.domain.com is a treated as a local
domain, so you must set (in the first section of the configuration)
local_domains = onebox.domain.com : ...
where the ... includes all your other local domains. The following director
than handles the requirement:
onebox_director:
driver = smartuser
domains = onebox.domain.com
new_address = postmaster@other.domain.com
This simply forwards everything for the domain to the given address. What
if the address is itself in the special domain? You can handle that by
listing an exception:
onebox_director:
driver = smartuser
domains = onebox.domain.com
local_parts = !postmaster
new_address = postmaster@onebox.domain.com
That setting of local_parts means "not postmaster". The address
postmaster@onebox.domain.com bypasses this director. Of course, you
must then have a subsequent director that deals with it.
Give each virtual domain its own alias file.
The term "virtual domain" usually means a domain in which every valid
address is just an alias for some other address, which may be local or
remote to the host that handles the virtual domain. A virtual domain is
essentially just a redirection service. A common way of managing a number
of virtual domains is to give each one its own alias file; this means you
can allow each file to be maintained by its own manager. Suppose you are
handling the virtual domains a.virt.com, b.virt.com,
c.virt.com, etc. You have to make them local domains
local_domains = *.virt.com : ...
(where the ... indicates your other local domains). Then you can handle
them all with a single director:
virtual:
driver = aliasfile
domains = *.virt.com
file = /etc/aliases.$domain
search_type = lsearch
no_more
You would probably put this director first, before all the others. It runs
only for addresses whose domains match *.virt.com, and after it has
run, no more directors are run because of the no_more setting. When
it runs, it expands the file name by inserting the domain, so, for example,
if the incoming address is user@a.virt.com, the file it inspects is
/etc/aliases.a.virt.com. This file could contain lines like this:
user1: some.one@some.domain
user2: some.one.else@other.domain
If the local part is not found in the file, delivery fails because no
further directors are run (but see the next item).
Add defaults to virtual domains.
You can add a default address to a virtual domain alias file very easily.
First, you must tell Exim to look for a default if it cannot match the
local part it is looking for. You do this by specifying
search_type = lsearch*
instead of just specifying lsearch (as in the previous item), so
the complete director might be:
virtual:
driver = aliasfile
domains = *.virt.com
file = /etc/aliases.$domain
search_type = lsearch*
no_more
The added asterisk tells Exim to look for an alias for the string
* when its initial search fails, so if you have an alias file like
this:
*: postmaster@whatever.domain
user1: some.one@some.domain
user2: some.one.else@other.domain
any local part other than user1 and user2 gets forwarded to
postmaster@whatever.domain. Note that the order of the items in the
file does not matter. Exim first searches for the local part of the
incoming address, and only if that is not found does it search for
*.
Convert sendmail alias files.
If you are converting from sendmail to Exim, you will have to make some
changes to alias files if you are using any kind of domain default. There
are four different kinds of line that appear in sendmail alias files, of
the following forms:
user1: newuser1@new.domain1
user2@domain2: newuser2@new.domain2
@domain3: newuser3@new.domain3
%1@domain4: @new.domain4
The first line is an example of an alias for a local part in a local
domain. Exim handles these by default. You can put such a line straight
into /etc/aliases, and use Exim's default configuration. It matches
the given local part in any local domain.
The second line specifies a complete email address instead of just a local
part. Exim normally looks up just the local part when expanding aliases; if
you want it to use the full address, you must set the
include_domain option, but then it always uses the full
address. How can we cope with a mixture of lines of the first two types?
The answer is to define two directors in the configuration, like this:
full_aliases:
driver = aliasfile
file = /etc/aliases
search_type = lsearch
include_domain
short_aliases:
driver = aliasfile
file = /etc/aliases
search_type = lsearch
With this configuration, Exim first searches /etc/aliases using the
full address. If it doesn't find anything, it searches again, but this
time using only the local part.
The third sendmail alias line is specifying a default for a specific
domain. You can do this in Exim in several ways. After the aliasing
directors, you could put this director:
domain_default:
driver = smartuser
domains = domain3
new_address = newuser3@new.domain3
However, you can also handle defaults as part of aliasing. The alias line
must be changed to:
*@domain3: newuser3@new.domain3
and the full_aliases director changed to:
full_aliases:
driver = aliasfile
file = /etc/aliases
search_type = lsearch*@
include_domain
The *@ in the search type tells Exim to look for *@domain
if it fails to find the original address in the file. (If it can't find
*@domain, it will then go on to look for *.)
The fourth sendmail alias line routes a message to the same local part, but
at a different domain. Again, there are several ways to achieve this effect
in Exim. We could use a smartuser director:
rename_domain:
driver = smartuser
domains = domain4
new_address = ${quote:$local_part}@new.domain4
Note the use of the quote string expansion operator, to ensure
that the local part is correctly quoted if necessary. To do this
transformation as part of aliasing, we need to use the defaulting facility
again, and also to set expand option so that the string that is
looked up is passed through the string expansion mechanism, in order to
substitute $local_part. In the alias file we'd put:
*@domain4: ${quote:$local_part}@new.domain4
and the director to use the file would be:
full_aliases:
driver = aliasfile
file = /etc/aliases
search_type = lsearch*@
include_domain
expand
Handle mailing lists with external software.
For all but trivial mailing lists, you should normally make use of proper
mailing list software such as Majordomo or SmartList. Exim has to do two
things:
It has to recognize messages addressed to mailing lists, and send them
off to be handled by the mailing list software.
It has to recognize messages coming back from the mailing list software
so that the original sender address can be preserved. (Normally, the
sender of a message sent by a local process is forced to the login of the
user running the process, which in this case is likely to be a user
reserved for the mailing list software.)
Majordomo configurations usually make use of a number of aliases that are
kept in a separate file, and other mailing list software can be configured
in the same way. It is easy to get Exim to handle this. Just set up an
additional director:
majordomo_aliases:
driver = aliasfile
file = /usr/local/majordomo/lists/majordomo.aliases
search_type = lsearch
pipe_transport = address_pipe
user = majordom
group = majordom
The lines in the alias file are of the form
majordomo: |/usr/mail/majordomo ...
that is, an alias name followed by a command that starts with a vertical
bar (pipe symbol). (For actual details of the format of the commands,
you'll have to check the documentation for your mailing list software.) The
pipe symbol tells Exim that this is an alias for a command; in order to run
it, the director needs three additional options:
pipe_transport = address_pipe
specifies which transport should be run for the pipe delivery. The default
configuration contains:
address_pipe:
driver = pipe
return_output
which runs a pipe transport with default configuration, except that any
output generated by the pipe is returned to the sender.
user = majordom
group = majordom
specify the user and group under which the pipe is to be run. OK, so we've
now arranged for incoming messages that are addressed to any of the mailing
list aliases to be piped to the mailing list manager software. What about
getting back messages for delivery to the subscribers? The mailing list
software can just call /usr/lib/sendmail to send messages, in the
same way that any running process can, but there is one small twist. The
command that is used is normally something like
/usr/lib/sendmail -f <sender address> <recipients>
where the -f option defines the original sender address. Exim
doesn't honor this option unless the sender is trusted. When an
ordinary user process sends a message, the sender is always taken from the
login ID. To ensure that the correct sender addresses are used, you must
set
trusted_users = majordom
in Exim's configuration (in the first section).
Verify message senders.
In the main part of Exim's configuration, if you set the option
sender_verify = true
Exim will attempt to verify the sender addresses of incoming messages
from other hosts, before accepting the message. If verification fails, the
message is rejected. This can keep out a certain amount of junk mail,
though, of course, it imposes a certain overhead.
Verify message recipients.
By default, Exim accepts messages from other hosts without checking the
validity of recipients, although it does check for unwanted relay attempts
(see the next two items). If you set, in the main part of Exim's
configuration, the option
receiver_verify = true
Exim will verify each recipient as it is received. Those that fail
verification are refused as part of the SMTP dialogue. If all recipients
are rejected, the message does not get into your host at all.
Configure incoming relaying.
Incoming relaying refers to the case where your host is acting as an
incoming gateway server for domains that are handled by other hosts inside
your organization, or is acting as a secondary backup MX server for any
domains. In these cases, there is a given set of domains that you want to
be able to relay. Configuring Exim to do this is simple. Just set
relay_domains = list of domains
For example,
relay_domains = *.mycompany.plc.uk : \
myfriend.org
Once you've done this, your host will accept mail from outside that is
addressed to those domains, and will relay it according to your delivery
configuration.
Configure outgoing relaying.
Outgoing relaying refers to the case where your host is acting as an
outgoing gateway server for hosts inside your organization. Usually this
means hosts on your local LAN. In this case, you want your host to accept
any outgoing mail from these hosts, but no others. Again, the configuration
is simple. Just set
host_accept_relay = list of hosts
The most common form this takes is to specify the hosts by a set of IP
addresses, for example:
host_accept_relay = 192.168.4.0/24
Once you've done this, your host will accept all mail from the given
hosts, whatever the domains of recipients.
Note the difference between relay_domains and
host_accept_relay: the former accepts relay mail for given
domains, whereas the latter accepts relay mail from the given hosts.
Of course, there is no reason why you should not set both options if you
want to. (This is common.)