bike9876@エボ猫.コム
(From https://www.exim.org/index.html) Exim is a message transfer agent (MTA) originally developed at the University of Cambridge for use on Unix systems connected to the Internet.
Install on an arch linux system with 1:
sudo pacman -S exim
Note: don’t start or enable the exim daemon (with eg
systemctl --now enable exim.service) as in my client setup,
/usr/bin/exim (or possibly its alias
/usr/bin/sendmail) will be run by any mail user agents as
needed.
This page describes one of the simplest exim configurations. All emails are locally-originated. A smarthost will be used to deliver email to non-local recipients2.
/etc/mail/aliasesSet the email alias for root (replace
USERNAME with the username of the non-root user who should
receive root’s emails):
sudo sed -i -E 's/^#?root:.*/root: USERNAME/' /etc/mail/aliases
/etc/mail/exim.confI use the configuration shown below. Definitions that must be changed
for your setup are the defintions of FROM_DOMAIN_DEFAULT
and ROUTER_SMARTHOST.
I want it to send all emails with a remote destination via a
smarthost (as defined in ROUTER_SMARTHOST). In my case that
smarthost requires authentication with a username and password, as
provided in the file defined in SYSTEM_AUTH_FILE (more
details later).
I want emails sent with an unqualified envelope sender and From:
header (eg just “root”, as would typically be sent by a system cron job)
to be qualified with @FROM_DOMAIN_DEFAULT. If I didn’t do
that, the default action of exim is to qualify with
@<hostname> (where <hostname> is
the hostname of my client system), which in my case the smarthost will
reject. Define FROM_DOMAIN_DEFAULT to be the domain to use
to qualify an unqualified sender address.
# exim.conf
# For a system with emails accepted purely on the command line, with no SMTP (so no -bs or -bS flags used).
# Eg as
# exim -bm foo < mail.txt
# (or via "mail" command or mutt).
# Except for emails delivered locally, it is expected that all will be sent off to a smarthost (see ROUTER_SMARTHOST).
# File derived from configure.default in exim source code - many of the explanatory comments have been retained.
# Sender addresses should be qualified with FROM_DOMAIN_DEFAULT, so if user bar runs "exim -bm foo < mail.txt", the
# envelope sender and From: header should be bar@FROM_DOMAIN_DEFAULT.
FROM_DOMAIN_DEFAULT = example.net
ROUTER_SMARTHOST = mail.example.net
# Where system email aliases are (https://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_redirect_router.html#SECID124)
SYSTEM_ALIASES_FILE = /etc/aliases
# Where authentication data to the smarthost is. Comment out if no authentication needed.
SYSTEM_AUTH_FILE = /etc/exim/smtp_users
domainlist local_domains = @:localhost
# Sometimes useful for debugging purposes, see below.
acl_not_smtp = acl_log_not_smtp
# I want unqualified envelope sender addresses and From: headers to be qualified with FROM_DOMAIN_DEFAULT
.ifdef FROM_DOMAIN_DEFAULT
qualify_domain = FROM_DOMAIN_DEFAULT
.endif
# I want unqualified envelope recipient addresses and recipient headers to be qualified with localhost
# so that eg "exim -bm foo < mail.txt" will try to deliver to foo on the localhost (the chances are that foo
# will have a ~/.forward set up to forward to an external host, but I should be able to deliver to localhost if that is what is wanted).
qualify_recipient = localhost
# Never run exim as any of these users.
# Local message deliveries are normally run in processes that are setuid to the recipient (so make sure that root has an alias to the sys admin).
# and remote deliveries are normally run under Exim’s own uid and gid.
# https://www.exim.org/exim-html-current/doc/html/spec_html/ch-main_configuration.html
never_users = root:daemon:bin
# Do not add a Received: header line for the locally-sent email from the user to exim.
# (I don't want the final recipient to see information about this host.)
# https://www.exim.org/exim-html-current/doc/html/spec_html/ch-main_configuration.html
received_header_text =
# Need to be in admin group to eg run exim with -d flag (for debugging output)
# Change if different group used instead of wheel (debian uses "sudo" group).
# https://www.exim.org/exim-html-current/doc/html/spec_html/ch-main_configuration.html
admin_groups=wheel
# See https://www.exim.org/exim-html-current/doc/html/spec_html/ch-the_exim_command_line.html#SECTtrustedadmin
# Sometimes I want to be able to specify the Return Path (with -f in exim).
# Change if different group used instead of wheel (debian uses "sudo" group).
trusted_groups = wheel
# To try to initialize the system resolver library with DNSSEC support. It has no effect if your library lacks
# DNSSEC support.
# https://www.exim.org/exim-html-current/doc/html/spec_html/ch-main_configuration.htm
# and see notes there re linux glibc => 2.31
dns_dnssec_ok = 1
# go crazy on logging
log_selector = +all
keep_environment =
#------------------------------------------------------------------------
begin acl
# I just use this to log stuff as needed (see example here to log the value of a macro to exim's log -
# but just using "exim -be 'SYSTEM_ALIASES_FILE'" would be easier).
# (https://www.exim.org/exim-html-current/doc/html/spec_html/ch-access_control_lists.html#SECnonSMTP)
# The ACL is run for a non-SMTP message just before the local_scan() function.
acl_log_not_smtp:
# warn log_message = ${uc:system_aliases_file}=SYSTEM_ALIASES_FILE
accept
#------------------------------------------------------------------------
begin routers
# This router can be used when you want to send all mail to a
# server which handles DNS lookups for you; an ISP will typically run such
# a server for their customers. The hostname in route_data comes from the
# macro defined at the top of the file. If not defined, then we'll use the
# dnslookup router below instead.
# Beware that the hostname is specified again in the Transport.
.ifdef ROUTER_SMARTHOST
smarthost:
driver = manualroute
domains = ! +local_domains
transport = smarthost_smtp
route_data = ROUTER_SMARTHOST
ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1
no_more
.else
# This router routes addresses that are not in local domains by doing a DNS
# lookup on the domain name. The exclamation mark that appears in "domains = !
# +local_domains" is a negating operator, that is, it can be read as "not". The
# recipient's domain must not be one of those defined by "domainlist
# local_domains" above for this router to be used.
#
# If the router is used, any domain that resolves to 0.0.0.0 or to a loopback
# interface address (127.0.0.0/8) is treated as if it had no DNS entry. Note
# that 0.0.0.0 is the same as 0.0.0.0/32, which is commonly treated as the
# local host inside the network stack. It is not 0.0.0.0/0, the default route.
# If the DNS lookup fails, no further routers are tried because of the no_more
# setting, and consequently the address is unrouteable.
dnslookup:
driver = dnslookup
domains = ! +local_domains
transport = remote_smtp
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
# if ipv6-enabled then instead use:
# ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1
no_more
# This closes the ROUTER_SMARTHOST ifdef around the choice of routing for
# off-site mail.
.endif
system_aliases:
driver = redirect
allow_fail
allow_defer
data = ${lookup{$local_part}lsearch{SYSTEM_ALIASES_FILE}}
file_transport = address_file
pipe_transport = address_pipe
userforward:
driver = redirect
check_local_user
file = $home/.forward
no_verify
no_expn
check_ancestor
file_transport = address_file
pipe_transport = address_pipe
reply_transport = address_reply
localuser:
driver = accept
check_local_user
transport = local_delivery
cannot_route_message = Unknown user
#------------------------------------------------------------------------
begin transports
# This transport is used for delivering messages over SMTP connections.
remote_smtp:
driver = smtp
.ifdef _HAVE_TLS_RESUME
tls_resumption_hosts = *
.endif
# This transport is used for delivering messages to a smarthost, if the
# smarthost router is enabled. This starts from the same basis as
# "remote_smtp" but then turns on various security options, because
# we assume that if you're told "use smarthost.example.org as the smarthost"
# then there will be TLS available, with a verifiable certificate for that
# hostname, using decent TLS.
smarthost_smtp:
driver = smtp
multi_domain
.ifdef SYSTEM_AUTH_FILE
# Try to authenticate with smarthost
hosts_try_auth = ROUTER_SMARTHOST
.endif
.ifdef _HAVE_TLS
# Comment out any of these which you have to, then file a Support
# request with your smarthost provider to get things fixed:
hosts_require_tls = *
tls_verify_hosts = *
# As long as tls_verify_hosts is enabled this will have no effect,
# but if you have to comment it out then this will at least log whether
# you succeed or not:
tls_try_verify_hosts = *
#
# The SNI name should match the name which we'll expect to verify;
# many mail systems don't use SNI and this doesn't matter, but if it does,
# we need to send a name which the remote site will recognize.
# This _should_ be the name which the smarthost operators specified as
# the hostname for sending your mail to.
tls_sni = ROUTER_SMARTHOST
#
.ifdef _HAVE_OPENSSL
tls_require_ciphers = HIGH:!aNULL:@STRENGTH
.endif
.ifdef _HAVE_GNUTLS
tls_require_ciphers = SECURE192:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1
.endif
.ifdef _HAVE_TLS_RESUME
tls_resumption_hosts = *
.endif
.endif
# This transport is used for local delivery to user mailboxes in traditional
# BSD mailbox format. By default it will be run under the uid and gid of the
# local user, and requires the sticky bit to be set on the /var/mail directory.
# Some systems use the alternative approach of running mail deliveries under a
# particular group instead of using the sticky bit. The commented options below
# show how this can be done.
local_delivery:
driver = appendfile
file = /var/mail/$local_part_data
delivery_date_add
envelope_to_add
return_path_add
# This transport is used for handling pipe deliveries generated by alias or
# .forward files. If the pipe generates any standard output, it is returned
# to the sender of the message as a delivery error. Set return_fail_output
# instead of return_output if you want this to happen only when the pipe fails
# to complete normally. You can set different transports for aliases and
# forwards if you want to - see the references to address_pipe in the routers
# section above.
address_pipe:
driver = pipe
return_output
# This transport is used for handling deliveries directly to files that are
# generated by aliasing or forwarding.
address_file:
driver = appendfile
delivery_date_add
envelope_to_add
return_path_add
# This transport is used for handling autoreplies generated by the filtering
# option of the userforward router.
address_reply:
driver = autoreply
#------------------------------------------------------------------------
begin authenticators
PLAIN:
driver = plaintext
client_send = "${extract{auth_plain}{${lookup{$host}lsearch{SYSTEM_AUTH_FILE}{$value}fail} }}"
LOGIN:
driver = plaintext
client_send = : "${extract{auth_name}{${lookup{$host}lsearch{SYSTEM_AUTH_FILE}{$value}fail} }}" : "${extract{auth_pass}{${lookup{$host}lsearch{SYSTEM_AUTH_FILE}{$value}fail} }}"
/etc/exim/smtp_users(skip if the smarthost does not require authentication)
As discussed above, my smarthost requires a client to authenticate
with a username and password. I set these in file
/etc/exim/smtp_users as eg
sudo -s # become root
mkdir -p /etc/exim
echo "$(exim -be 'ROUTER_SMARTHOST') auth_name=USERNAME auth_pass=PASSWORD auth_plain=^USERNAME^PASSWORD" > /etc/exim/smtp_users
chmod 640 /etc/exim/smtp_users
chown root:exim /etc/exim/smtp_users
exit # leave root
Change USERNAME and PASSWORD to those that
allow access to the smarthost.
Other distributions will be similar (but different) in how to install packages, and in the file locations.↩︎
Any emails with a local recipient will be saved on the
client, unless exim’s aliases file or the local recipient’s
~/.forward file has been set up to forward to an external
address (which should normally be done - see main text).↩︎