====== Exim4 - Configuration File ======
http://alex.mamchenkov.net/2010/06/24/exim-dovecot-and-mysql/
http://t-machine.org/index.php/2014/06/27/webmail-on-your-debian-server-exim4-dovecot-roundcube/
http://www1.alx.pl/w/linux/exim-sql.conf
https://weijl.org/virtual-domains-with-exim4-dovecot-dspam-and-mysql/
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 =====
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 }