######################################################################
|
# MAIN CONFIGURATION SETTINGS #
|
######################################################################
|
|
# MySQL defines
|
MYSQL_SERVER=localhost
|
MYSQL_USER=root
|
MYSQL_PASSWORD=
|
MYSQL_DB=mailserver
|
MYSQL_EMAILTABLE=mail_box
|
MYSQL_DOMAINTABLE=mail_domain
|
MYSQL_WHITETABLE=mail_whitelist
|
MYSQL_BLACKTABLE=mail_blacklist
|
|
# Server ID for Multiserver Setups
|
MAILSERVER_ID=1
|
MAILSERVER_HOSTNAME=mail.
|
MAILSERVER_IP=192.168.0.108
|
MAILSERVER_EXIM_BINARY=/usr/sbin/exim4
|
MAILSERVER_SPAMC_BINARY=/usr/bin/spamc
|
|
# Mailman vars
|
MAILMAN_HOME=/var/lib/mailman
|
MAILMAN_WRAP=MAILMAN_HOME/mail/wrapper
|
MAILMAN_UID=list
|
MAILMAN_GID=list
|
|
# MySQL queries
|
# MYSQL_Q_LDOMAIN=SELECT DISTINCT domain FROM MYSQL_DOMAINTABLE WHERE domain='${quote_mysql:$domain}' AND type = 'local'
|
# MYSQL_Q_RDOMAIN=SELECT DISTINCT domain FROM MYSQL_DOMAINTABLE WHERE domain='${quote_mysql:$domain}' AND type = 'relay'
|
|
MYSQL_Q_VSCAN=SELECT SUBSTRING_INDEX(email,'@',-1) FROM MYSQL_EMAILTABLE WHERE email=CONCAT('${quote_mysql:$local_part}','@','${quote_mysql:$domain}') AND opt_virscan='yes'
|
|
|
MM_HOME=${lookup mysql{SELECT mm_home FROM mail_mailman_domain WHERE domain='${quote_mysql:domain}'}}
|
MM_LISTCHK=MM_HOME/lists/${lc::$local_part}/config.pck
|
MM_WRAP=${lookup mysql{SELECT mm_wrap FROM mail_mailman_domain WHERE domain='${quote_mysql:domain}'}}
|
|
# MySQL connection
|
hide mysql_servers = "MYSQL_SERVER/MYSQL_DB/MYSQL_USER/MYSQL_PASSWORD"
|
|
# starting 'normal' config
|
|
primary_hostname = MAILSERVER_HOSTNAME
|
|
domainlist local_domains = mysql;SELECT DISTINCT domain FROM MYSQL_DOMAINTABLE WHERE domain='${quote_mysql:$domain}' AND type = 'local'
|
domainlist relay_to_domains = mysql;SELECT DISTINCT domain FROM MYSQL_DOMAINTABLE WHERE domain='${quote_mysql:$domain}' AND (type = 'relay' OR type = 'alias')
|
hostlist relay_from_hosts = 127.0.0.1
|
domainlist mmdomains = ${lookup mysql {SELECT domain FROM mail_mailman_domain}}
|
|
# acl_smtp_rcpt = acl_check_rcpt
|
|
qualify_domain =
|
# qualify_recipient =
|
|
# allow_domain_literals
|
|
never_users = root
|
trusted_users = mail
|
|
host_lookup = *
|
rfc1413_hosts = *
|
rfc1413_query_timeout = 15s
|
|
check_spool_space = 50M
|
check_log_space = 20M
|
return_size_limit = 20k
|
message_size_limit = 20M
|
|
# sender_unqualified_hosts =
|
# recipient_unqualified_hosts =
|
|
# percent_hack_domains =
|
|
ignore_bounce_errors_after = 2d
|
timeout_frozen_after = 7d
|
|
deliver_queue_load_max = 8
|
queue_only_load = 10
|
remote_max_parallel = 15
|
|
#tls_certificate =
|
#tls_privatekey =
|
#tls_advertise_hosts = *
|
|
# SSL/TLS cert and key
|
tls_certificate = /etc/exim4/smtpd.cert
|
tls_privatekey = /etc/exim4/smtpd.key
|
|
# Advertise TLS to anyone
|
tls_advertise_hosts = *
|
|
# Require auth over SSL only.
|
# auth_over_tls_hosts = *
|
|
helo_try_verify_hosts = !+relay_from_hosts
|
|
av_scanner = clamd:/var/run/clamav/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 #
|
# Specifies access control lists for incoming SMTP mail #
|
######################################################################
|
|
begin acl
|
|
acl_check_rcpt:
|
|
accept hosts = :
|
|
deny domains = +local_domains
|
local_parts = ^[.] : ^.*[@%!/|]
|
|
deny domains = !+local_domains
|
local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./
|
|
accept local_parts = postmaster
|
domains = +local_domains
|
|
require verify = sender
|
|
# Whitelist
|
|
|
# Blacklist
|
deny senders = ${lookup mysql {SELECT DISTINCT address FROM MYSQL_BLACKTABLE WHERE '${quote_mysql:$sender_address}' LIKE address \
|
AND (recipient = '' OR recipient = '${quote_mysql:$domain}' OR recipient = '${quote_mysql:$local_part}@${quote_mysql:$domain}') \
|
AND active = '1' AND server_id = 'MAILSERVER_ID'}{$value}}
|
log_message = Blacklisted. Sender: <$sender_address> Recipient: <$local_part@$domain>
|
|
accept domains = +local_domains
|
endpass
|
verify = recipient
|
|
accept domains = +relay_to_domains
|
endpass
|
verify = recipient
|
|
accept hosts = +relay_from_hosts
|
|
accept authenticated = *
|
|
deny message = relay not permitted
|
|
|
acl_check_host:
|
accept
|
hosts = +relay_from_hosts
|
#deny
|
# log_message = match host_reject.list
|
# hosts = /etc/exim4/filters/host_reject.list
|
|
accept
|
|
acl_check_helo:
|
accept hosts = +relay_from_hosts
|
# If the HELO pretend to be this host
|
deny condition = ${if or { \
|
{eq {${lc:$sender_helo_name}}{MAILSERVER_HOSTNAME}} \
|
{eq {${lc:$sender_helo_name}}{MAILSERVER_IP}} \
|
} {true}{false} }
|
# by default we accept
|
accept
|
|
|
acl_check_data:
|
|
accept hosts = +relay_from_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
|
|
# spamassassin
|
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}}
|
|
# clamav
|
deny message = This message contains a virus or other harmful content ($malware_name)
|
demime = *
|
malware = *
|
log_message = Virus found in Message
|
|
# accept by default
|
accept
|
|
|
|
|
######################################################################
|
# ROUTERS CONFIGURATION #
|
# Specifies how addresses are handled #
|
######################################################################
|
# THE ORDER IN WHICH THE ROUTERS ARE DEFINED IS IMPORTANT! #
|
# An address is passed to each router in turn until it is accepted. #
|
######################################################################
|
|
begin routers
|
|
fail_router:
|
driver = redirect
|
domains = ${lookup mysql {SELECT SUBSTRING_INDEX(email,'@',-1) FROM MYSQL_EMAILTABLE WHERE email=CONCAT('${quote_mysql:$local_part}','@','${quote_mysql:$domain}') AND active='0'}{$value}}
|
data = ":fail:"
|
allow_fail
|
|
domain_aliases:
|
driver=redirect
|
domains=${lookup mysql{SELECT domain FROM mail_domain WHERE domain='${domain}' AND type = 'alias'}}
|
data=$local_part@${lookup mysql{SELECT destination FROM mail_domain WHERE domain='${domain}'}}
|
|
mailman_router:
|
driver = accept
|
domains = +mmdomains
|
require_files = MM_LISTCHK
|
local_part_suffix_optional
|
local_part_suffix = -admin : \
|
-bounces : -bounces+* : \
|
-confirm : -confirm+* : \
|
-join : -leave : \
|
-owner : -request : \
|
-subscribe : -unsubscribe
|
transport = mailman_transport
|
|
dnslookup:
|
driver = dnslookup
|
domains = ! +local_domains
|
transport = remote_smtp
|
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
|
no_more
|
|
# Blacklists werden jetzt in den ACL geprüft
|
#blacklist_router:
|
# driver = manualroute
|
# senders = ${lookup mysql {SELECT DISTINCT address FROM MYSQL_BLACKTABLE WHERE '${quote_mysql:$sender_address}' LIKE address AND recipient = '${quote_mysql:$local_part}@${quote_mysql:$domain}'}{$value}}
|
# # condition = "${if !def:h_X-Spam-Flag: {1}{0}}"
|
# # headers_add = X-Spam-Flag: YES
|
# route_list = * localhost
|
# # self = pass
|
# transport = devnull_transport
|
# verify = false
|
|
#system_aliases:
|
# driver = redirect
|
# allow_fail
|
# allow_defer
|
# data = ${lookup{$local_part}lsearch{/etc/aliases}}
|
# user = exim
|
# file_transport = address_file
|
# pipe_transport = address_pipe
|
|
#mysql_systemalias:
|
# driver = redirect
|
# allow_fail
|
# allow_defer
|
# data = ${lookup mysql{SELECT dest FROM mail_systemalias WHERE local_part='${quote_mysql:$local_part}'}}
|
|
mysql_email_alias:
|
driver = redirect
|
allow_fail
|
allow_defer
|
data = ${lookup mysql{ SELECT destination FROM mail_redirect WHERE email='${quote_mysql:$local_part}@${quote_mysql:$domain}' AND type = 'alias'}}
|
|
mysql_email_forward:
|
driver = redirect
|
data = ${lookup mysql{ SELECT destination FROM mail_redirect WHERE email='${quote_mysql:$local_part}@${quote_mysql:$domain}' AND type = 'forward'}}
|
|
#spamcheck_router:
|
# driver = manualroute
|
# domains = ${lookup mysql {SELECT SUBSTRING_INDEX(email,'@',-1) FROM MYSQL_EMAILTABLE WHERE email=CONCAT('${quote_mysql:$local_part}','@','${quote_mysql:$domain}') AND spamscan='yes'}{$value}}
|
# senders = ! ${lookup mysql {SELECT DISTINCT MYSQL_WHITETABLE.address FROM MYSQL_WHITETABLE WHERE '${quote_mysql:$sender_address}' LIKE MYSQL_WHITETABLE.address}{$value}}
|
# condition = ${if and { \
|
# {!eq {$received_protocol}{spam-scanned}} \
|
# {!eq {$received_protocol}{local}} \
|
# } {1}{0}}
|
# headers_remove = X-Spam-Flag
|
# route_list = "* localhost byname"
|
# transport = spamcheck
|
# verify = false
|
|
#spamdelete_router:
|
# driver = manualroute
|
# domains = ${lookup mysql {SELECT SUBSTRING_INDEX(email,'@',-1) FROM MYSQL_EMAILTABLE WHERE email=CONCAT('${quote_mysql:$local_part}','@','${quote_mysql:$domain}') AND spamdelete = '1'}{$value}}
|
# # condition = "${if eq{$h_X-Spam-Flag:}{YES} {1}{0}}"
|
# condition = "${if match{$h_X-Spam-Flag}{YES} {1}{0}}"
|
# route_list = "* localhost byname"
|
# transport = devnull_transport
|
# verify = false
|
|
|
spamrewrite_router:
|
driver = manualroute
|
domains = ${lookup mysql {SELECT SUBSTRING_INDEX(email,'@',-1) FROM mail_spamfilter WHERE email='${quote_mysql:$local_part}@${quote_mysql:$domain}'}{$value}}
|
senders = ! ${lookup mysql {SELECT DISTINCT MYSQL_WHITETABLE.address FROM MYSQL_WHITETABLE WHERE '${quote_mysql:$sender_address}' LIKE MYSQL_WHITETABLE.address}{$value}}
|
condition = ${if and { \
|
{>{$spam_score_int}{${lookup mysql {SELECT spam_rewrite_score_int FROM mail_spamfilter WHERE email='${quote_mysql:$local_part}@${quote_mysql:$domain}'}{$value}}}}\
|
{!eq {$received_protocol}{spam-rewrite}} \
|
{!eq {$received_protocol}{local}} \
|
}{true}{false}}
|
headers_remove = Subject
|
headers_add = Subject: ${lookup mysql {SELECT spam_rewrite_subject FROM mail_spamfilter WHERE email='${quote_mysql:$local_part}@${quote_mysql:$domain}'}{$value}} $header_subject
|
route_list = "* localhost byname"
|
transport = spamrewrite_transport
|
verify = false
|
|
spamredirect_router:
|
driver = manualroute
|
domains = ${lookup mysql {SELECT SUBSTRING_INDEX(email,'@',-1) FROM mail_spamfilter WHERE email='${quote_mysql:$local_part}@${quote_mysql:$domain}'}{$value}}
|
senders = ! ${lookup mysql {SELECT DISTINCT MYSQL_WHITETABLE.address FROM MYSQL_WHITETABLE WHERE '${quote_mysql:$sender_address}' LIKE MYSQL_WHITETABLE.address}{$value}}
|
condition = ${if >{$spam_score_int}{${lookup mysql {SELECT spam_redirect_score_int FROM mail_spamfilter WHERE email='${quote_mysql:$local_part}@${quote_mysql:$domain}'}{$value}}}{true}{false}}
|
route_list = "* localhost byname"
|
transport = spamredirect_transport
|
verify = false
|
|
spamdelete_router:
|
driver = manualroute
|
domains = ${lookup mysql {SELECT SUBSTRING_INDEX(email,'@',-1) FROM mail_spamfilter WHERE email='${quote_mysql:$local_part}@${quote_mysql:$domain}'}{$value}}
|
senders = ! ${lookup mysql {SELECT DISTINCT MYSQL_WHITETABLE.address FROM MYSQL_WHITETABLE WHERE '${quote_mysql:$sender_address}' LIKE MYSQL_WHITETABLE.address}{$value}}
|
condition = ${if and { \
|
{>{$spam_score_int}{${lookup mysql {SELECT spam_delete_score_int FROM mail_spamfilter WHERE email='${quote_mysql:$local_part}@${quote_mysql:$domain}'}{$value}}}}\
|
{!eq {$received_protocol}{spam-rewrite}} \
|
{!eq {$received_protocol}{local}} \
|
}{true}{false}}
|
route_list = "* localhost byname"
|
transport = devnull_transport
|
verify = false
|
|
autoresponder_router:
|
driver = accept
|
domains = ${lookup mysql {SELECT SUBSTRING_INDEX(email,'@',-1) FROM MYSQL_EMAILTABLE WHERE email=CONCAT('${quote_mysql:$local_part}','@','${quote_mysql:$domain}') AND autoresponder='yes'}{$value}}
|
transport = autoresponder_transport
|
unseen
|
|
# cc_router:
|
# driver = redirect
|
# data = ${lookup mysql {SELECT cc FROM MYSQL_EMAILTABLE WHERE email=CONCAT('${quote_mysql:$local_part}','@','${quote_mysql:$domain}')}{$value}}
|
# unseen
|
|
# forward_router:
|
# driver = redirect
|
# data = ${lookup mysql {SELECT forward FROM MYSQL_EMAILTABLE WHERE email=CONCAT('${quote_mysql:$local_part}','@','${quote_mysql:$domain}') AND forward != ''}{$value}}
|
|
local_mailbox_router:
|
driver = accept
|
domains = ${lookup mysql {SELECT SUBSTRING_INDEX(email,'@',-1) FROM MYSQL_EMAILTABLE WHERE email=CONCAT('${quote_mysql:$local_part}','@','${quote_mysql:$domain}') AND maildir != '' AND active = '1'}{$value}}
|
transport = local_delivery
|
|
mysql_catchall_router:
|
driver=redirect
|
data=${lookup mysql{ SELECT destination FROM mail_domain_catchall WHERE domain='${domain}'}}
|
allow_fail
|
allow_defer
|
|
######################################################################
|
# TRANSPORTS CONFIGURATION #
|
######################################################################
|
# ORDER DOES NOT MATTER #
|
# Only one appropriate transport is called for each delivery. #
|
######################################################################
|
|
begin transports
|
|
########################
|
# Remote smtp transport
|
########################
|
|
remote_smtp:
|
driver = smtp
|
|
###################
|
# Mailman transport
|
###################
|
|
mailman_transport:
|
driver = pipe
|
command = /var/mailman/lists.mas-services.co.uk/mail/mailman \
|
'${if def:local_part_suffix \
|
{${sg{$local_part_suffix}{-(\\w+)(\\+.*)?}{\$1}}} \
|
{post}}' \
|
$local_part
|
current_directory = ${lookup mysql{SELECT mm_home FROM mail_mailman_domain WHERE domain='${domain}'}}
|
home_directory = ${lookup mysql{SELECT mm_home FROM mail_mailman_domain WHERE domain='${domain}'}}
|
user = ${lookup mysql{SELECT mm_user FROM mail_mailman_domain WHERE domain='${domain}'}}
|
group = ${lookup mysql{SELECT mm_group FROM mail_mailman_domain WHERE domain='${domain}'}}
|
|
|
#################################################################################
|
# This transport is only for rewriting the header of the message with ***SPAM***
|
#################################################################################
|
|
spamrewrite_transport:
|
driver = pipe
|
command = MAILSERVER_EXIM_BINARY -oMr spam-rewrite -bS
|
use_bsmtp = true
|
home_directory = "/tmp"
|
current_directory = "/tmp"
|
user = mail
|
group = mail
|
log_output = true
|
return_fail_output = true
|
return_path_add = false
|
message_prefix =
|
message_suffix =
|
|
######################################################
|
# This transport is only for redirecting SPAM messages
|
######################################################
|
|
spamredirect_transport:
|
driver = appendfile
|
directory = ${lookup mysql {SELECT concat(spam_redirect_maildir,'/Maildir') FROM mail_spamfilter WHERE email='${quote_mysql:$local_part}@${quote_mysql:$domain}'}{$value}}
|
maildir_format
|
user = mail
|
group = mail
|
mode = 0660
|
directory_mode = 0770
|
|
##########################
|
# Local delivery transport
|
##########################
|
|
local_delivery:
|
driver = appendfile
|
directory = ${lookup mysql {SELECT concat(maildir,'/Maildir') FROM MYSQL_EMAILTABLE WHERE email=CONCAT('${quote_mysql:$local_part}','@','${quote_mysql:$domain}')}{$value}}
|
maildir_format
|
user = mail
|
group = mail
|
quota = ${lookup mysql{select quota from MYSQL_EMAILTABLE where email=CONCAT('${quote_mysql:$local_part}','@','${quote_mysql:$domain}')}{${value}M}}
|
quota_is_inclusive = false
|
maildir_tag = ,S=$message_size
|
quota_size_regex = ,S=(\d+):
|
quota_warn_threshold = 75%
|
maildir_use_size_file = false
|
quota_warn_message = "To: $local_part@$domain\n\
|
Subject: Mailbox quota warning\n\n\
|
This message was automatically generated by the mail delivery software.\n\n\
|
You are now using over 75% of your allocated mail storage quota.\n\n\
|
If your mailbox fills completely, further incoming messages will be automatically\n\
|
returned to their senders.\n\n\
|
Please take note of this and remove unwanted mail from your mailbox.\n"
|
mode = 0660
|
directory_mode = 0770
|
|
##########################
|
# autoresponder transport
|
##########################
|
|
autoresponder_transport:
|
driver = autoreply
|
to = ${sender_address}
|
from = "vacation@${domain}"
|
subject = "Autoresponder: ${local_part}@${domain}"
|
text = ${lookup mysql {SELECT autoresponder_text FROM MYSQL_EMAILTABLE WHERE email=CONCAT('${quote_mysql:$local_part}','@','${quote_mysql:$domain}')}{$value}}
|
|
##########################
|
# devnull transport
|
##########################
|
|
devnull_transport:
|
driver = appendfile
|
file = /dev/null
|
user = mail
|
|
|
######################################################################
|
# RETRY CONFIGURATION #
|
######################################################################
|
|
begin retry
|
|
# This single retry rule applies to all domains and all errors. It specifies
|
# retries every 15 minutes for 2 hours, then increasing retry intervals,
|
# starting at 1 hour and increasing each time by a factor of 1.5, up to 16
|
# hours, then retries every 6 hours until 4 days have passed since the first
|
# failed delivery.
|
|
# Domain Error Retries
|
# ------ ----- -------
|
|
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h
|
|
|
|
######################################################################
|
# REWRITE CONFIGURATION #
|
######################################################################
|
|
# There are no rewriting specifications in this default configuration file.
|
begin rewrite
|
|
|
|
######################################################################
|
# AUTHENTICATION CONFIGURATION #
|
######################################################################
|
|
# There are no authenticator specifications in this default configuration file.
|
|
begin authenticators
|
|
fixed_plain:
|
driver = plaintext
|
public_name = PLAIN
|
server_condition = ${lookup mysql{SELECT email FROM MYSQL_EMAILTABLE WHERE email='${quote_mysql:$2}' AND cryptpwd=encrypt('${quote_mysql:$3}', cryptpwd) AND active = '1'}{1}fail}
|
server_set_id = $2
|
|
fixed_login:
|
driver = plaintext
|
public_name = LOGIN
|
server_prompts = "Username:: : Password::"
|
server_condition = ${lookup mysql{SELECT email FROM MYSQL_EMAILTABLE WHERE email='${quote_mysql:$1}' AND cryptpwd=encrypt('${quote_mysql:$2}', cryptpwd) AND active = '1'}{1}fail}
|
server_set_id = $1
|
|
cram:
|
driver = cram_md5
|
public_name = CRAM-MD5
|
server_secret = "${lookup mysql {SELECT clearpwd FROM mail_box WHERE email = '${sg {$1}{'}{}}' AND active = '1'} {$value} fail}"
|
server_set_id = $1
|
|
|
######################################################################
|
# CONFIGURATION FOR local_scan() #
|
######################################################################
|
|
# If you have built Exim to include a local_scan() function that contains
|
# tables for private options, you can define those options here. Remember to
|
# uncomment the "begin" line. It is commented by default because it provokes
|
# an error with Exim binaries that are not built with LOCAL_SCAN_HAS_OPTIONS
|
# set in the Local/Makefile.
|
|
# begin local_scan
|
|
|
# End of Exim configuration file
|