====== 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 }