Table of Contents

Exim4 - Configuration File

The context is a host server with a public IP (5.42.134.35, www.sharewiz.net), which is also used as local mail server:

######################################################################
#                    MAIN CONFIGURATION SETTINGS                     #
######################################################################

# If exim is used localy in batch mode (exim4 -bs) then "$host" is empty, the ": :" adds the empty string.
hostlist   own_hosts = 127.0.0.1 : : 192.168.0.2 : 192.168.0.3 : 5.42.134.35
domainlist public_domains = sharewiz.net

ACLs

Here is the ACL section of my Exim configuration file

# ACL that is used after the RCPT command
check_recipient:

# to block certain wellknown exploits, Deny for local domains if
# local parts begin with a dot or contain @ % ! / |
  deny  domains       = +local_domains
        local_parts   = ^[.] : ^.*[@%!/|]

# to restrict port 587 to authenticated users only
# see also daemon_smtp_ports above
accept  hosts = +auth_relay_hosts
        condition = ${if eq {$interface_port}{587} {yes}{no}}
        endpass
        message = relay not permitted, authentication required
        authenticated = *

# allow local users to send outgoing messages using slashes
# and vertical bars in their local parts.
# Block outgoing local parts that begin with a dot, slash, or vertical
# bar but allows them within the local part.
# The sequence \..\ is barred. The usage of @ % and ! is barred as
# before. The motivation is to prevent your users (or their virii)
# from mounting certain kinds of attacks on remote sites.
  deny  domains       = !+local_domains
        local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./

# local source whitelist
# accept if the source is local SMTP (i.e. not over TCP/IP).
# Test for this by testing for an empty sending host field.
  accept  hosts = :

# sender domains whitelist
# accept if sender domain is in whitelist
  accept  sender_domains = +whitelist_domains

# sender hosts whitelist
# accept if sender host is in whitelist
  accept  hosts = +whitelist_hosts
  accept  hosts = +whitelist_hosts_ip

# envelope senders whitelist
# accept if envelope sender is in whitelist
  accept  senders = +whitelist_senders

# accept mail to postmaster in any local domain, regardless of source
  accept  local_parts = postmaster
          domains     = +local_domains

# accept mail to abuse in any local domain, regardless of source
  accept  local_parts = abuse
          domains     = +local_domains

# accept mail to hostmaster in any local domain, regardless of source
  accept  local_parts = hostmaster
          domains     =+local_domains

# OPTIONAL MODIFICATIONS:
# If the page you're using to notify senders of blocked email of how
# to get their address unblocked will use a web form to send you email so
# you'll know to unblock those senders, then you may leave these lines
# commented out.  However, if you'll be telling your senders of blocked
# email to send an email to errors@yourdomain.com, then you should
# replace "errors" with the left side of the email address you'll be
# using, and "example.com" with the right side of the email address and
# then uncomment the second two lines, leaving the first one commented.
# Doing this will mean anyone can send email to this specific address,
# even if they're at a blocked domain, and even if your domain is using
# blocklists.

# accept mail to errors@example.com, regardless of source
#   accept  local_parts = errors
#           domains     = example.com

# deny so-called "legal" spammers"
  deny message = Email blocked by RBL - to unblock see http://www.example.com/
       # only for domains that do want to be tested against RBLs
       domains = +use_rbl_domains
       sender_domains = +blacklist_domains

# deny using hostname in bad_sender_hosts blacklist
  deny message = Email blocked by BSHL - to unblock see http://www.example.com/
       # only for domains that do want to be tested against RBLs
       domains = +use_rbl_domains
       hosts = +bad_sender_hosts

# deny using IP in bad_sender_hosts blacklist
  deny message = Email blocked by BSHL - to unblock see http://www.example.com/
       # only for domains that do want to be tested against RBLs
       domains = +use_rbl_domains
       hosts = +bad_sender_hosts_ip

# deny using email address in blacklist_senders
  deny message = Email blocked by BSAL - to unblock see http://www.example.com/
       domains = +use_rbl_domains
       senders = +blacklist_senders

# By default we do NOT require sender verification.
# Sender verification denies unless sender address can be verified:
# If you want to require sender verification, i.e., that the sending
# address is routable and mail can be delivered to it, then
# uncomment the next line. If you do not want to require sender
# verification, leave the line commented out

#require verify = sender

# deny using .spamhaus
  deny message = Email blocked by SPAMHAUS - to unblock see http://www.example.com/
       # only for domains that do want to be tested against RBLs
       domains = +use_rbl_domains
       dnslists = sbl.spamhaus.org

# deny using ordb
#  deny message = Email blocked by ORDB - to unblock see http://www.example.com/
#       # only for domains that do want to be tested against RBLs
#       domains = +use_rbl_domains
#       dnslists = relays.ordb.org

# deny using sorbs smtp list
  deny message = Email blocked by SORBS - to unblock see http://www.example.com/
       # only for domains that do want to be tested against RBLs
       domains = +use_rbl_domains
       dnslists = dnsbl.sorbs.net=127.0.0.5

# Next deny stuff from more "fuzzy" blacklists
# but do bypass all checking for whitelisted host names
# and for authenticated users

# deny using spamcop
  deny message = Email blocked by SPAMCOP - to unblock see http://www.example.com/
       hosts = !+relay_hosts
       domains = +use_rbl_domains
       !authenticated = *
       dnslists = bl.spamcop.net

# deny using njabl
  deny message = Email blocked by NJABL - to unblock see http://www.example.com/
       hosts = !+relay_hosts
       domains = +use_rbl_domains
       !authenticated = *
       dnslists = dnsbl.njabl.org

# deny using cbl
  deny message = Email blocked by CBL - to unblock see http://www.example.com/
       hosts = !+relay_hosts
       domains = +use_rbl_domains
       !authenticated = *
       dnslists = cbl.abuseat.org

# deny using all other sorbs ip-based blocklist besides smtp list
  deny message = Email blocked by SORBS - to unblock see http://www.example.com/
       hosts = !+relay_hosts
       domains = +use_rbl_domains
       !authenticated = *
       dnslists = dnsbl.sorbs.net!=127.0.0.6

# deny using sorbs name based list
  deny message = Email blocked by SORBS - to unblock see http://www.example.com/
       domains =+use_rbl_domains
       # rhsbl list is name based
       dnslists = rhsbl.sorbs.net/$sender_address_domain

# accept if address is in a local domain as long as recipient can be verified
  accept  domains = +local_domains
          endpass
      message = "Unknown User"
          verify = recipient

# accept if address is in a domain for which we relay as long as recipient
# can be verified
  accept  domains = +relay_domains
          endpass
          verify=recipient

# accept if message comes for a host for which we are an outgoing relay
# recipient verification is omitted because many MUA clients don't cope
# well with SMTP error responses. If you are actually relaying from MTAs
# then you should probably add recipient verify here

  accept  hosts = +relay_hosts
  accept  hosts = +auth_relay_hosts
          endpass
          message = authentication required
          authenticated = *
  deny    message = relay not permitted

# default at end of acl causes a "deny", but line below will give
# an explicit error message:
  deny    message = relay not permitted

# ACL that is used after the DATA command
check_message:
  accept

Another config

######################################################################
#                    MAIN CONFIGURATION SETTINGS                     #
######################################################################

hostlist   own_hosts = 127.0.0.1 : 192.168.1.2 : 192.168.1.3 : 5.42.134.35
domainlist public_domains = sharewiz.net
 . . . 
# Mandatory to use  "verify = helo"
helo_try_verify_hosts = !+own_hosts

av_scanner = clamd:/var/run/clamd.ctl
spamd_address = 127.0.0.1 783

acl_smtp_rcpt = acl_check_rcpt
acl_smtp_mail = acl_check_sender
acl_smtp_connect = acl_check_host
acl_smtp_data = acl_check_data
acl_smtp_helo = acl_check_helo


 . . . 
######################################################################
#                          ACL CONFIGURATION                         #
######################################################################
acl_check_host:
        accept
                hosts = +own_hosts : /etc/exim4/filters/host_white.list

        deny    
                log_message = match host_reject.list
                hosts = /etc/exim4/filters/host_reject.list

        accept

acl_check_helo:
        accept  hosts = +own_hosts

	# If the HELO pretend to be this host
	deny	condition = ${if or { \
					{eq {${lc:$sender_helo_name}}{sharewiz.net}} \
					{eq {${lc:$sender_helo_name}}{5.42.134.35}} \
				    } {true}{false} }

        # by default we accept
        accept

acl_check_sender:
        deny    senders = /etc/exim4/filters/sender_reject.list
        accept

# ACL "subroutine" used by acl_check_rcpt below.
# Return ok if the HELO argument correspond to the connected HOST and 
# if the HELO argument does not contain an IP in decimal or hexa.
# I have created this ACL subroutine because we can't do a list of "or" 
# in ACL (it's a list of "and"), so I use a negation of "and": 
# no (no A and no B) = A or B.
acl_clean_helo:
        accept
                verify     = helo
                condition  = ${if match{$sender_helo_name}{\N(\d{1,3}[.-]\d{1,3}[.-]\d{1,3}[.-]\d{1,3})|([0-9a-f]{8})|([0-9A-F]{8})\N}{false}{true}}


acl_check_rcpt:
        # refuse if the recipient string is a hack, 
        # see exim file example C043.txt.gz
        deny    
                local_parts = ^.*[@%!/|] : ^\\.

        # Relaying with no more check for my own hosts.
        accept  
                hosts = +own_hosts

        # For the rest, the domain of the recipient address
        # must be my public domain. (no relay) 
        require
                log_message = no relay.
                domains     = +public_domains

        # Reffuse all the message if the recipient is only used by spammers.
        drop
                log_message   = match recipients_drop.list.
                recipients = /etc/exim4/filters/recipients_drop.list

        drop
                log_message = match sbl-xbl.spamhaus.org
                dnslists = sbl-xbl.spamhaus.org

        # Greylisting, if the HELO argument seems bad or 
        # a dialin name (with IP included in the name). Some hosts from big
        # providers are in a white list to avoid testing. When there is no
        # sender then it is a bounce message, so no greylist.
        defer
                message = Please try later.
                !hosts      = /etc/exim4/filters/host_white.list
                !senders    = :
                !acl        = acl_clean_helo
                log_message = greylisted.
                set acl_m9  = ${mask:$sender_host_address/24} $sender_address $local_part@$domain
                set acl_m9  = ${readsocket{/var/run/greylistd/socket}{$acl_m9}{5s}{}{}}
                condition   = ${if eq {$acl_m9}{grey}{true}{false}}

        # Default rule: accept except if recipient address is unrouteable.
        accept  
                message = unrouteable address
                verify = recipient


acl_check_data:

        accept  hosts = +own_hosts

        # if there is a windows executable as attachment then we reject
        deny    message = This message contains an attachment of a type which we do not accept (.$found_extension) 
                demime = bat:btm:cmd:com:cpl:dll:exe:lnk:msi:pif:prf:reg:scr:vbs:url

        # clamav
        deny    message = This message contains a virus or other harmful content ($malware_name)
                demime = * 
                malware = *
        
        ## spamassassin, spams are never big and spamassassin can die on big emails, so we
        ## limit its use under 500k.
        accept  condition = ${if >={$message_size}{500k}{yes}{no}}
        warn    message = X-SA-Score: $spam_score 
                spam = nobody:true 
        warn    message = X-SA-Report: $spam_report 
                spam = nobody:true
                condition = ${if >{$spam_score_int}{0}{true}{false}}
        warn    message = X-SA-Status: Yes 
                spam = nobody:true
                condition = ${if >{$spam_score_int}{50}{true}{false}}
        deny    message = This message scored $spam_score spam points. 
                spam = nobody:true 
                condition = ${if >{$spam_score_int}{70}{true}{false}}

        # accept by default
        accept

A Basic config

/etc/exim4/exim4.conf
local_scan_path = /usr/lib/exim4/local_scan/sa-exim.so
 
hide pgsql_servers = localhost::5433/authdb/poczta/poczta1
 
primary_hostname = czarny06.aklin
 
domainlist local_domains = @ : czarny06.aklin : poczta.czarny06.aklin
domainlist relay_to_domains = czarny02.aklin : czarny04.aklin
hostlist   relay_from_hosts = 127.0.0.1 : 10.0.3.67
domainlist exdomains = fiw.local 
 
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data
acl_not_smtp  = wiadomosci_z_sendmaila
 
av_scanner = clamd:/var/run/clamav/clamd.ctl
 
tls_advertise_hosts = *
 
tls_certificate = /etc/exim4/mail.crt
tls_privatekey = /etc/exim4/mail.key
 
daemon_smtp_ports = 25 : 465 : 587
tls_on_connect_ports = 465
 
never_users = root
 
host_lookup = *
 
rfc1413_hosts = !10.0.2.0/24
rfc1413_query_timeout = 5s
 
ignore_bounce_errors_after = 2d
 
timeout_frozen_after = 7d
 
begin acl
 
wiadomosci_z_sendmaila:
 
  accept  add_header    = X-SA-Nie-Uruchamiaj-Mnie: 9787be32e0cb6ae2b4e06f57c6461893
 
acl_check_rcpt:
 
 
  warn	local_parts = pracownicy
  	domains = +local_domains
  	add_header = Reply-To: pracownicy@czarny06.aklin
 
  warn  hosts = czarny02.aklin : czarny04.aklin
  	add_header    = X-SA-Nie-Uruchamiaj-Mnie: 9787be32e0cb6ae2b4e06f57c6461893
 
  accept  hosts = :
  	  add_header    = X-SA-Nie-Uruchamiaj-Mnie: 9787be32e0cb6ae2b4e06f57c6461893
 
  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
  	  add_header    = X-SA-Nie-Uruchamiaj-Mnie: 9787be32e0cb6ae2b4e06f57c6461893
          control       = submission
 
  accept  authenticated = *
	  add_header	= X-SA-Nie-Uruchamiaj-Mnie: 9787be32e0cb6ae2b4e06f57c6461893
          control       = submission
 
  require message = relay not permitted
          domains = +local_domains : +relay_to_domains : +exdomains
 
  require verify = recipient
 
  accept
 
acl_check_data:
 
  deny    malware    = *
          message    = This message contains a virus ($malware_name).
 
  accept
 
begin routers
 
dnslookup:
  driver = dnslookup
  domains = ! +local_domains : ! +exdomains
  transport = remote_smtp
  ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
  no_more
 
aliases_poczta_czarny_06_aklin:
  driver = redirect
  allow_fail
  allow_defer
  domains = poczta.czarny06.aklin
  data = ${lookup{$local_part}lsearch{/etc/aliases-poczta}}
  file_transport = address_file
  pipe_transport = address_pipe
 
system_aliases:
  driver = redirect
  allow_fail
  allow_defer
  data = ${lookup pgsql{select goto from alias where address = '${local_part}'}{$value}}
  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_spam_flag:
  driver = accept
  condition = ${lookup pgsql{select count(account_id) from account where username = '${local_part}'}{$value}}
  condition = ${if eq {$h_X-Spam-Flag}{YES} {1}{0}}
  transport = local_delivery_spam
 
localuser:
  driver = accept
  condition = ${lookup pgsql{select count(account_id) from account where username = '${local_part}'}{$value}}
  transport = local_delivery
  cannot_route_message = Unknown user
 
begin transports
 
remote_smtp:
  driver = smtp
  headers_remove = X-SA-Nie-Uruchamiaj-Mnie : X-SA-Exim-Connect-IP : X-SA-Exim-Rcpt-To : X-SA-Exim-Mail-From
 
remote_smtp_ex:
  driver = smtp
  headers_remove = X-SA-Nie-Uruchamiaj-Mnie : X-SA-Exim-Connect-IP : X-SA-Exim-Rcpt-To : X-SA-Exim-Mail-From
  hosts_avoid_tls = *
 
local_delivery:
  driver = appendfile
  maildir_format
  directory = ${lookup pgsql{SELECT maildir FROM account WHERE username = '$local_part'}{$value}}
 # file = /var/mail/$local_part
  delivery_date_add
  envelope_to_add
  return_path_add
  group = mail
  mode = 0660
  headers_remove = X-SA-Nie-Uruchamiaj-Mnie : X-SA-Exim-Connect-IP : X-SA-Exim-Rcpt-To : X-SA-Exim-Mail-From
  user = dovecot
 
local_delivery_spam:
  driver = appendfile
  maildir_format
  directory = ${lookup pgsql{SELECT maildir FROM account WHERE username = '$local_part'}{$value}}/.spam
 # file = /var/mail/$local_part
  delivery_date_add
  envelope_to_add
  return_path_add
  group = mail
  mode = 0660
  headers_remove = X-SA-Nie-Uruchamiaj-Mnie : X-SA-Exim-Connect-IP : X-SA-Exim-Rcpt-To : X-SA-Exim-Mail-From
  user = dovecot
 
address_pipe:
  driver = pipe
  return_output
 
address_file:
  driver = appendfile
  delivery_date_add
  envelope_to_add
  return_path_add
 
address_reply:
  driver = autoreply
 
begin retry
 
*                      *           F,2h,15m; G,16h,1h,1.5; F,4d,6h
 
begin rewrite
 
begin authenticators
 
PLAIN:
  driver                     = plaintext
  server_set_id              = $auth2
  server_prompts             = :
  server_condition           = ${lookup pgsql{select count(account_id) from account where username = '$2' and password = '$3'}{$value}}
  server_advertise_condition = ${if def:tls_cipher }
 
LOGIN:
  driver                     = plaintext
  server_set_id              = $auth1
  server_prompts             = <| Username: | Password:
  server_condition           = ${lookup pgsql{select count(account_id) from account where username = '$1' and password = '$2'}{$value}}
  server_advertise_condition = ${if def:tls_cipher }