This sign is used in the text to mark an action that you need to take if you
want to do the things that are suggested in this practical.
In particular, running email tests as root is a bad idea, because root has privileges. You want to test that Exim is working when an ordinary, unprivileged user calls it.
As with most software under FreeBSD, you have three choices on how to install it:
Here we are going to install Exim from ports. It's a straightforward process, easier than compiling it yourself. If you bring your ports collection up to date using cvsup then you will be building the latest version of Exim (whereas the binary package on the CD-ROM may be an older version).
Proceed as follows:
# cd /usr/ports/mail/exim # make ... a lot of stuff is displayed ... # make install ... some more stuff is displayed ... # rehash (Needed if you are using the C shell)
You should end up with the Exim program in /usr/local/sbin/exim and a default configuration file in /usr/local/etc/exim/configure.
(ASIDE: There are optional extra features you can build into exim when
compiling it. For example, "make WITH_MYSQL=yes" would build exim with
MySQL support, so that mailboxes could be looked up in a MySQL database.
However, the defaults in the ports collection are fine for what we need. Look
at the comments in
/usr/ports/mail/exim/Makefile to see the options available).
If a sendmail daemon is running, kill it off. Use ps with
grep to find it. (Modern versions of sendmail may have two
or more processes running)
# ps auxw | grep sendmail # /etc/rc.d/sendmail stop # vi /etc/rc.conf ... set this value: sendmail_enable="NONE"
Note that the FreeBSD port builds exim to run using user "mailnull" and group "mail". You should now arrange for your personal (non-root) account to be in the mail group so that you can be an administrator for Exim.
# pw usermod username -G mail # grep mail /etc/group (To check)
$ less /usr/local/share/doc/exim/spec.txt
(There is also a separate port available, mail/exim-doc-html,
which installs the Exim documentation in HTML format for reading with a web
browser. Or it's available on-line at http://www.exim.org/)
Test that Exim has been installed by running:
$ exim -bVwhich should tell you Exim's version number and some other information about which features are included.
FreeBSD lets us choose a new MTA by setting values in
the /etc/mail/mailer.conf file. We redirect the programs
'sendmail', 'send-mail' and 'mailq' to point to exim.
# cd /etc/mail # vi mailer.conf ... change these three lines: sendmail /usr/local/sbin/exim send-mail /usr/local/sbin/exim mailq /usr/local/sbin/exim ... you can leave newaliases, hoststat and purgestat unchanged
Now try that basic test again, but this time using the standard path name:
$ /usr/sbin/sendmail -bVYou should get the same output as before, which shows that Exim is now being used instead of Sendmail.
First, check what Exim will do with a local address:
$ exim -bt localuserThis tests the delivery routing for a local account. See what output you get.
Try with a non-existent local user and see what happens:
$ exim -bt junkjunkjunk
Try something that is in /etc/aliases:
$ exim -bt postmasterExim will not normally deliver mail to a root mailbox (for security reasons) so what people usually do is to make root an alias for the sysadmin. In FreeBSD, all the default aliases point to root. Therefore, you should add a new alias to /etc/aliases. Find this commented-out line:
# root: me@mydomainand change it (remembering to remove the initial '#') to:
root: localuserNow try this again:
$ exim -bt postmaster
Now we are going to try a real local delivery. You can pass a message directly
to Exim without using an MUA:
$ exim -v -odf localuser This is a test message. .Note: the message is terminated by a line that just contains a dot. Be sure to type it! (Alternatively, you can send ``end of file'' by pressing CTRL-D.)
The -v option turns on user verification output, which shows you copies of Exim's log lines.
The -odf option requests `foreground' delivery, which means that the exim command won't return until the delivery is complete. (This avoids your shell prompt getting mixed up with Exim's output.)
Check what is in Exim's logs:
$ cat /var/log/exim/mainlog $ cat /var/log/exim/paniclogThe panic log should normally be empty, and if nothing has ever been written to it, it will not even exist. Tip: On a live system it is helpful to set up a cron job that mails you a warning if it ever finds a non-empty panic log.
If you get a permission error, make sure that your username is in the 'mail' group, then logout and login again to become a member of that group.
If the delivery succeeded, you should see two lines in the main log, one containing <= for the message arriving, and one containing => for the delivery.
Now go check the local user's mailbox:
$ ls -l /var/mail/localuser $ cat /var/mail/localuserIf the delivery didn't succeed, you need to find out why. If the information in the log doesn't help, you can try the delivery again, with debugging turned on:
$ exim -d -odf localuser <there will be output from Exim here> This is another test message. .The -d option turns on debugging, which gives a lot more information than -v. You need to be an Exim administrator to use -d. If you get a `Permission denied' error, check that you are a member of the "mail" group.
If you are logged on as localuser, you can use the mail command to
read the mail in the usual way. You could also try sending a message from the
mail command.
The next thing is to test whether Exim can send to a remote host. The speed of this may vary, depending on the state of the network connection. In what follows, replace user@remote.host with your home email address.
First, check that Exim can route to the address:
$ exim -bt user@remote.host
Now send a message to the remote address:
$ exim -v -odf user@remote.host This is a test message. .This time, the -v option causes Exim to display the SMTP dialogue as well as the log lines. If you can, check that the message arrived safely. If there are problems, see if you can figure out what went wrong and why.
You won't be able to receive messages from a remote host until you start the
Exim daemon:
# exim -bd -q30mThe -bd option causes the daemon to listen for incoming SMTP calls, and the -q30m option causes it to start a queue runner process every 30 minutes. On a live system, starting the daemon should happen automatically on a reboot, by putting the following entry in /etc/rc.conf :
exim_enable="YES"Once you've done this, you can use /usr/local/etc/rc.d/exim.sh {start|stop|status} as usual.
Use telnet to check that the daemon is accepting SMTP calls:
$ telnet localhost 25You should see an Exim greeting message. Use QUIT to exit.
Now check that a remote host can send a message to your host, and see how
Exim logs what happens. If that succeeds, you have a working basic installation
correctly installed.
Try sending to an invalid address from a remote host, and see what error
message you get, and how Exim logs this case. Look in both mainlog and
rejectlog.
To put a message on the queue without its being delivered, run
$ exim -odq address1 address2 ... Test message. .The message stays on the queue until a queue runner process notices it.
List the messages on the queue:
$ exim -bp
Do a manual queue run, with minimal verification output:
$ exim -v -q(Without -v you won't see any output at all on the terminal, but there will be entries in the log.)
To demonstrate that Exim will relay by default via the loopback interface, try
the following sequence of SMTP commands. Wait for Exim to respond to each
command before typing the next one. Substitute the number of your pc for
nn:
$ telnet 127.0.0.1 25 ehlo localhost mail from:<localuser@pcnn.presanog.org.bt> rcpt to:<localuser@pcnn.presanog.org.bt> rcpt to:<user@some.remote.domain>You should get an OK response to all the SMTP commands. Type `quit' to end the SMTP session without actually sending a message.
Now try the same thing, but use your host's IP address instead of 127.0.0.1.
$ telnet xx.xx.xx.nn 25 ehlo localhost mail from:<localuser@pcnn.presanog.org.bt> rcpt to:<localuser@pcnn.presanog.org.bt> rcpt to:<user@some.remote.domain>In this case, you should get the error message
550 relay not permittedfor the second RCPT command, which is the one that is trying to relay. The first RCPT command should be accepted, because it specifies a local delivery. You could also try telnetting from an external host and running the same check.
Run exigrep to extract all information about a certain message, or a
certain user's messages, or messages for a certain domain. For example:
$ exigrep localuser /var/log/exim/mainlogThat extracts all the log information for all messages that have any log line containing `localuser'. It's a Perl pattern match, so you can use Perl regular expressions.
To extract simple statistics from a log, run
$ eximstats /var/log/exim/mainlog | moreThere are options for selecting which bits you don't want. Details are in the manual. If you have time, experiment with the options for outputting the statistics as HTML.
# cat /var/run/exim.pid # kill -HUP nnnnwhere nnnn is the pid from the previous line. Alternatively, you can use the startup script installed by the port to do this for you:
# /usr/local/etc/rc.d/exim.sh reloadYou can confirm that the daemon has restarted by checking the main log.
The following sections contain some suggestions for configuration modifications that you can try, just to get a feel for how the configuration file works. You do not have to stick rigidly to these examples; use different domain names or user names if you want to.
Edit the configuration, and change the local_domains setting so that it
looks like this:
domainlist local_domains = @ : testnn.presanog.org.btwhere nn is the number of your host. Remember to HUP the daemon afterwards. Now you have a new local domain. Try sending it some mail:
$ mail yourname@testnn.presanog.org.btCheck that it arrives in your mailbox.
Note: The domains that we are adding now can only be used from your own host, because there are no DNS records for them. When you are adding domains to a production host, you must of course also add MX records for them.
If you want to add a lot of domains, or if you want to keep changing them, it is easier to keep the list of domains in a file instead of in the Exim configuration. (You can also keep them in several different kinds of database, such as LDAP or MySQL, but we don't cover that in this workshop.) We are now going to add some domains like this, and then make them into virtual domains.
Use vi to create a file called /usr/local/etc/exim/vdomains that contains a
list of domains (as many as you like):
vdom1.presanog.org.bt vdom2.presanog.org.bt ...
Edit /usr/local/etc/exim/configure to change the local domains setting:
domainlist local_domains = @ : testnn.presanog.org.bt : \
lsearch;/usr/local/etc/exim/vdomains
Note: There is no space following the semicolon. This change makes all the
new domains into local domains.
Now we add a new router to handle these domains as virtual domains. Put this
router first, before all the other routers, immediately after the line
``begin routers'':
virtual_domains:
driver = redirect
domains = lsearch;/usr/local/etc/exim/vdomains
data = ${lookup{$local_part}lsearch{/usr/local/etc/exim/aliases-$domain}}
no_more
There must be no space after the semicolon in the ``domains'' line. (Remember
to HUP the daemon.)
Create an alias file for the first virtual domain -- use vi to make the
file /usr/local/etc/exim/aliases-vdom1.presanog.org.bt containing these lines:
brian: b.candler@pobox.com yourname: your email addressThe local parts brian and yourname should now be valid for the first virtual domain.
Test that Exim recognizes the virtual addresses:
$ exim -bt brian@vdom1.presanog.org.btPlease don't actually send test mail to that address -- I get too much junk already!
Now create a different alias file for the second virtual domain, with
brian aliased to somebody else, and check (with -bt) that Exim
treats that address differently.
Note: It is always important to test that incorrect addresses are handled the way you want. So you need to run this test too:
$ exim -bt unknown@vdom1.presanog.org.bt
Add a redirect router that sends all undeliverable mail in your domain to
the postmaster. Where in the list of routers should this go? See if you can
work out how to do this on your own without looking at the answer below. Do you
think that having a router like this is a good idea on a busy host?
Here is a sample router that does this job:
unknown_to_postmaster: driver = redirect data = postmaster
It should be placed last, after all the other routers. Test it by sending mail to an unknown user.
We are now going to remove this block by changing a line in the configuration
to let all the classroom hosts relay through your host. Change this line:
hostlist relay_from_hosts = 127.0.0.1to
hostlist relay_from_hosts = 127.0.0.1 : xx.xx.xx.xx/mmwhere xx.xx.xx.xx/mm is the classroom network. (Don't forget to HUP the daemon.) Then try the telnet test from section 2 again. This time it should accept the request to relay. Ask one of the other students to try relaying through your host -- it should work. If you can, telnet from a host outside the classroom network, and confirm that relaying is still blocked.
domainlist relay_to_domains =This defines domains to which your host will relay, wherever the message comes from. As you can see, the default list is empty, so no domains match.
Add some domains to this line. For example, add the domain of your home email.
In my case, this would be:
domainlist relay_to_domains = pobox.com
Now we need to test that Exim will indeed relay to those domains (but not to others) from a host that does not match relay_from_hosts. Exim has a testing facility that lets you simulate an SMTP call from a remote host. Run it like this:
$ exim -bh 192.168.1.1You will see some debugging output, and then an SMTP greeting line. Now type SMTP commands, waiting for a response between each one:
ehlo testhost mail from:<localuser@pcnn.presanog.org.bt> rcpt to:<user@your.home.domain> rcpt to:<user@some.other.domain>You will see the tests that Exim is making as it runs the ACL after each RCPT command. Check that it allows relaying to the right domains, and not to any others. End the SMTP session with QUIT.
Edit the configuration, and change the remote_smtp transport to be
like this:
remote_smtp: driver = smtp port = 3456(Remember to HUP the daemon.) This makes Exim try port 3456 instead of the SMTP port (25) when delivering, causing the remote host to refuse the connection (assuming you've chosen an unused port!)
Send a message to a remote address and see what happens.
Start a queue run
$ exim -qand see what happens and what gets logged. Have a look at the message's own msglog file, which you can do from the monitor or by using the -Mvl option. For example:
$ exim -Mvl 19EdUm-00016A-IA(That is an example message ID; you must use the real one for the message that is on your queue.)
Use exinext to see when Exim is next scheduled to deliver to the host that
failed:
$ exinext remote.domain
Remember to remove the setting of port when you have finished
playing with retries (and HUP the daemon).
Use vi to create a test system filter file in
/usr/local/etc/exim/system.filter, containing these lines:
# Exim filter if $h_subject: is "spam" then save /dev/null endif
Arrange for Exim to use the system filter by adding these lines to the
configuration (somewhere near the beginning, before the first ``begin'' line):
system_filter = /usr/local/etc/exim/system.filter system_filter_file_transport = address_file
Now send yourself a message with the subject `spam' and see what happens.
Find the rewriting section of the configuration (the part that starts with
``begin rewrite''). Then add this line:
othernameotherdomain.com postmasteryour.domain
Now send a message to othername@otherdomain.com and see what happens.
You can test rewriting rules with the -brw command line option:
$ exim -brw othername@otherdomain.com