aboutsummaryrefslogtreecommitdiffstats
# Specify local domains, this is usually hostname -f and hostname - ie bad
# mail names the local machine might create.  They get rewritten to a cloud
# name below
domainlist local_domains =

domainlist relay_to_domains =
hostlist relay_from_hosts = localhost
# Create this file HERE
# It has single lines in the format:
#  domain.com: host=smtp.office365.com::587 helo=cms user=user@domain.com oauth=/home/XX/mail/.cms/exim/unix
# oauth= may also be replaced with password= to do basic authentication. The
# file is searched based on the Envelope From when invoking sendmail
SMARTFN = /etc/exim4/exim-smart-hosts

# We don't have IPv6, do not even try.
disable_ipv6=true

# It is also a good idea to edit /etc/default/exim4 and switch to 'queueonly' mode (Debian)
local_interfaces = <; [127.0.0.1]:25

acl_smtp_rcpt = acl_check_rcpt

tls_advertise_hosts =

# Trusted users are allowed to override the sender envelope
trusted_users = # Add your user name HERE

never_users = root

host_lookup = *

prdr_enable = true

log_selector = +smtp_protocol_error +smtp_syntax_error \
	+tls_certificate_verified

ignore_bounce_errors_after = 2d
timeout_frozen_after = 7d

keep_environment =
add_environment = <; PATH=/bin:/usr/bin

begin acl
acl_check_rcpt:

  # Standard input
  accept  hosts = :
          control = dkim_disable_verify

  deny    message       = Restricted characters in address
          domains       = +local_domains
          local_parts   = ^[.] : ^.*[@%!/|]


  deny    message       = Restricted characters in address
          domains       = !+local_domains
          local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./


  accept  local_parts   = postmaster
          domains       = +local_domains


  require verify        = sender

  accept  hosts         = +relay_from_hosts
          control       = submission
          control       = dkim_disable_verify

  accept  authenticated = *
          control       = submission
          control       = dkim_disable_verify

  require message = relay not permitted
          domains = +local_domains : +relay_to_domains

  require verify = recipient

  accept

begin routers

# The router is sensitive to the sender address and will use the correct outgoing server.
# Use something like:
#  exim -f 'user@domain.com' -bt user@otherdomain.com
# To quick test
smarthost:
  debug_print = "R: smarthost to $local_part@$domain for $sender_address"
  driver = manualroute
  domains = ! +local_domains
  transport = remote_smtp_smarthost
  address_data = ${lookup{$sender_address_domain}lsearch{SMARTFN}}
  route_data = ${extract{host}{$address_data}}

# There are several cases in exim, particularly internally generated bounces,
# that have an empty envelope from. In this case route based on the
# destination address the cloud relay will insert the account user as the
# envelope from.
empty_envelope:
  debug_print = "R: empty_envelope to $local_part@$domain for '$sender_address'"
  driver = manualroute
  domains = ! +local_domains
  transport = remote_smtp_smarthost
  condition = ${if eq{$sender_address_domain}{}{true}{}}
  address_data = ${lookup{$domain}lsearch{SMARTFN}}
  route_data = ${extract{host}{$address_data}}
  no_more

begin transports

remote_smtp_smarthost:
  debug_print = "T: remote_smtp_smarthost for $local_part@$domain"
  driver = smtp
  helo_data = ${extract{helo}{$address_data}{$value}{example.com}}
  hosts_require_auth = ${extract{user}{$address_data}{*}{}}
  hosts_require_tls = *
  tls_tempfail_tryclear = false
  tls_verify_certificates = system

begin retry

*                      *           F,2h,15m; G,16h,1h,1.5; F,4d,6h

begin rewrite

# Replace user and domain HERE
root@+local_domains user@domain.com Eh
user@+local_domains user@domain.com Eh

begin authenticators

xoauth2_smart:
  driver = plaintext
  client_condition = ${if and {{!eq{$tls_out_cipher}{}} {eq{${extract{oauth}{$address_data}{}fail}}{}}} }
  public_name = XOAUTH2
  client_ignore_invalid_base64 = true
  client_send = : ${readsocket{${extract{oauth}{$address_data}{$value}fail}}{SMTP ${extract{user}{$address_data}{$value}fail}}}

# Plain has fewer round trips, so prefer to use it
plain_smart:
  driver = plaintext
  client_condition = ${if and {{!eq{$tls_out_cipher}{}} {eq{${extract{password}{$address_data}{}fail}}{}}} }
  public_name = PLAIN
  client_send = ^${extract{user}{$address_data}{$value}fail}^${extract{password}{$address_data}}

login_smart:
  driver = plaintext
  client_condition = ${if and {{!eq{$tls_out_cipher}{}} {eq{${extract{password}{$address_data}{}fail}}{}}} }
  public_name = LOGIN
  client_send = : ${extract{user}{$address_data}{$value}fail} : ${extract{password}{$address_data}}