Re: [exim] Setting up exim to relay through ISP's email serv…

Pàgina inicial
Delete this message
Reply to this message
Autor: Phil Pennock
Data:  
A: Eli C
CC: exim-users
Assumpte: Re: [exim] Setting up exim to relay through ISP's email server
On 2008-06-20 at 00:07 -0400, Eli C wrote:
> Do you have an example of this?


I have a rather complex setup for my laptop. It does this and more.
Details below. Used on MacOS.

> And thanks for the tip about checking for TLS if using auth PLAIN. Does
> $tls_cipher count SSL connections as well? A disturbing number of
> servers use PLAIN over unencrypted SMTP...


AFAIK, $tls_cipher counts SSL connections, but I don't think Exim
supports SSL-on-connect outbound. That is strictly for legacy client
support, Exim supports it for inbound connections only. I think.


Okay, my laptop. This does not highlight how easy Exim can be to
configure for many scenarios (once you know _how_, which is always the
sticking point); rather, it's a glimpse of the power you get from the
rather complete string expansion language. And a glimpse of how nuts I
am.

There will be various macros and hostlists which you define for
yourself. There are two special external files which are the heart of
it. "smarthosts" and "client-passwords". Example here uses Gmail
because that's what I have configured (various disclaimers apply).
Gmail's delivery folks aren't entirely enthralled with people routing
mail through Gmail and sending bounces, risking mail-loops, etc, so if
you mismanage this and damage your account's spam reputation score, on
your head be it.

smarthosts:
----------------------------8< cut here >8------------------------------
gmail.com:      host=smtp.gmail.com    submission=yes tls=yes user=nobody@???
googlemail.com: host=smtp.gmail.com    submission=yes tls=yes user=nobody@???
*:              host=mail.example.org  submission=yes tls=yes
----------------------------8< cut here >8------------------------------


For the "client-passwords" file, I don't keep that in source-code
control and I'm not on the laptop right now, so I might be making a
mistake, but I believe it goes something like:
----------------------------8< cut here >8------------------------------
nobody@???:    password=12345678
mail.example.org:    user=fred  password=sekret
----------------------------8< cut here >8------------------------------
Note how when a user is specified in smarthosts, the client-passwords
file is keyed by that, otherwise it's keyed by the smarthost (or parent
domains thereof).


Routers first; the first Router lets me declare for which domains I'll
send direct to MX, by creating a file named for the domain in a special
directory. The second Router verifies DNS so that I don't pass invalid
domains on and damage my reputation with remote systems; this does mean
that I need to be online whilst submitting email to Exim though.

----------------------------8< cut here >8------------------------------
begin routers

direct_to_mx:
driver = dnslookup
domains = partial()dsearch;DIRECT_OUT_DIR
transport = remote_smtp
ignore_target_hosts = +special_ipv4_bad
same_domain_copy_routing
no_more

remote_dns_verify:
driver = dnslookup
domains = ! +local_domains
transport = remote_smtp
ignore_target_hosts = +special_ipv4_bad
same_domain_copy_routing
verify_only
no_more

smarthost:
driver = manualroute
domains = ! +local_domains
transport = smarthost_smtp
ignore_target_hosts = +special_ipv4_bad
route_data = ${extract{host}{${lookup{$domain}partial()lsearch*{RUNCONFDIR/smarthosts}}}}
address_data = ${lookup{$domain}partial()lsearch*{RUNCONFDIR/smarthosts}}
same_domain_copy_routing
no_verify
no_more

----------------------------8< cut here >8------------------------------

The route_data extracts the 'host' field from the smarthosts file;
address_data associates the entire line from smarthosts with the
address, for later extraction.

----------------------------8< cut here >8------------------------------
begin transports

remote_smtp:
driver = smtp
.ifndef TLS_ALLOWED_OUTBOUND
hosts_avoid_tls = *
.endif
hosts_require_tls = +tls_required_to
hosts_try_auth = +authenticate_attempt_to

smarthost_smtp:
  driver = smtp
  port = ${extract{port}{$address_data}{$value}{\
          ${extract{submission}{$address_data}{587}{25}}\
          }}
  hosts_require_tls = ${extract{tls}{$address_data}{*}{+tls_required_to}}
  hosts_require_auth = ${extract{user}{$address_data}{*}{+authenticate_required_to}}
  helo_data = ${extract{helo}{$address_data}{$value}{MYHELO_TO_SMARTHOST}}
----------------------------8< cut here >8------------------------------


The TLS_ALLOWED_OUTBOUND is something I might define on the command-line
to send mail with a queue-run to someone whose TLS is currently broken.

The hostlist authenticate_attempt_to is used for stuff not going via a
smarthost.

The hostlists tls_required_to and authenticate_required_to are fallbacks
for when the fields are not present. You can easily remove those and
just have no coerced default. Note the default HELO parameter is a
macro. No, none of the lines in the example smarthosts file set helo,
so I always use that default.

For the authenticators, I'll remove the server_* fields which aren't
relevant; in theory I might start my laptop's Exim accepting remote mail
from the local network, authenticated, and send via that. I've done
that once, maybe twice, so it's just a distraction here. But if you do
want to handle authentication server-side, you just add the server_*
fields to these same authenticators.

----------------------------8< cut here >8------------------------------
begin authenticators

auth_cram:
  driver        = cram_md5
  public_name   = CRAM-MD5
# If smarthosts address_data gives us a user, use that; else do
# a domain search on client-passwords (no * default support)
  client_name = ${extract{user}{$address_data}{$value}{\
        ${extract{user}{${lookup{$host}partial()lsearch{RUNAUTHDIR/client-passwords}}}{$value}fail}}}
# The password, however, always comes from client-passwords
  client_secret = ${extract{password}{${lookup{\
        ${extract{user}{$address_data}{$value}{$host}}\
        }partial()lsearch{RUNAUTHDIR/client-passwords}}}{$value}fail}


auth_plain:
  driver        = plaintext
  public_name   = PLAIN
  client_condition      = ${if def:tls_cipher}
  client_send = ^${extract{user}{$address_data}{$value}{\
           ${extract{user}{${lookup{$host}partial()lsearch{RUNAUTHDIR/client-passwords}}}{$value}fail}}}\
        ^${extract{password}{${lookup{\
           ${extract{user}{$address_data}{$value}{$host}}\
           }partial()lsearch{RUNAUTHDIR/client-passwords}}}{$value}fail}
----------------------------8< cut here >8------------------------------


There's no GSSAPI support client-side because I only use that with
GSSAPI-enabled MUAs, not from an MTA. I could create a server principal
with no bound address, I suppose, but I don't want to.

I think I got the full details.