fix for forwarding save option, added SRS
This commit is contained in:
parent
9186bc4a01
commit
6d1dd40484
12
etc/exim4/bounce_message_text
Normal file
12
etc/exim4/bounce_message_text
Normal file
|
@ -0,0 +1,12 @@
|
|||
****
|
||||
|
||||
This message was created automatically by the mail delivery software on $primary_hostname:
|
||||
|
||||
A message ${if eq{$sender_address}{$bounce_recipient}{that you sent}{sent by\n}}
|
||||
${if ! eq{$sender_address}{$bounce_recipient} {${if match {$sender_address} {\N(?i)^SRS[01][=+-]\N} {${sg {${sg {$sender_address} {\N(?i)^SRS[01][=+-][^ @]+?[=+-][a-zA-Z0-9]{2}[=+-]([^ @]+?)[=+-]([^ @]++)@.*$\N} {\N $2@$1\N}} } {\N^ prvs=[^=]+?=(.*)$\N} {\N $1\N} }\n} {${if match {$sender_address} {\N(?i)^prvs=\N} {${sg {$sender_address} {\N(?i)^prvs=[^ @]+?=(.*@.*)$\N} {\N $1\n\N}}} { $sender_address\n}}} }}}
|
||||
could not be delivered to one or more of its recipients. The following
|
||||
address(es) failed:
|
||||
****
|
||||
****
|
||||
****
|
||||
****
|
|
@ -7,6 +7,7 @@ disable_ipv6 = true
|
|||
keep_environment =
|
||||
add_environment = PATH=/usr/sbin:/usr/bin:/sbin:/bin
|
||||
smtp_enforce_sync = false
|
||||
bounce_message_file = /etc/exim4/bounce_message_text
|
||||
|
||||
smtp_accept_max = 50
|
||||
smtp_accept_max_per_host = 10
|
||||
|
@ -202,7 +203,7 @@ rfc1413_query_timeout = 0s
|
|||
|
||||
ignore_bounce_errors_after = 0s
|
||||
|
||||
# This option cancels (removes) frozen messages that are older than a week.
|
||||
# This option cancels (removes) frozen messages that are older than a day.
|
||||
|
||||
timeout_frozen_after = 1d
|
||||
|
||||
|
@ -433,6 +434,32 @@ acl_rcpt_to:
|
|||
# Recipent Address Checks
|
||||
######################################################################
|
||||
|
||||
# Ensure only valid SRS prefixed bounce message get accepted
|
||||
deny
|
||||
senders = :
|
||||
domains = +local_domains
|
||||
local_parts = ${if match {$local_part} {(?i)\N^SRS[01][=+-]\N} {$local_part}}
|
||||
control = caseful_local_part
|
||||
condition = ${if match{${readsocket{/run/srsd/srsd.sock}{REVERSE $local_part@$domain}{5s}{\n}}}{^ERROR: .* Invalid hash at .*}}
|
||||
message = Invalid reverse path (SRS check failed on $local_part@$domain).
|
||||
|
||||
warn
|
||||
senders = :
|
||||
domains = +local_domains
|
||||
local_parts = ${if match {$local_part} {\N^srs[01][=+-]\N} {$local_part}}
|
||||
control = caseful_local_part
|
||||
condition = ${if match{${readsocket{/run/srsd/srsd.sock}{REVERSE $local_part@$domain}{5s}{ }}}{^SRS: Case insensitive hash match detected. Someone smashed case in the local-part. .*}}
|
||||
log_message = SRS hash smashed on the way for $local_part@$domain by case insensitive MTA.
|
||||
|
||||
# this is for debugging only. can be safely removed any time
|
||||
warn
|
||||
senders = :
|
||||
domains = +local_domains
|
||||
local_parts = ${if match {$local_part} {(?i)\N^SRS[01][=+-]\N} {$local_part}}
|
||||
control = caseful_local_part
|
||||
condition = ${if !match{${readsocket{/run/srsd/srsd.sock}{REVERSE $local_part@$domain}{5s}{\n}}}{^ERROR: .* Invalid hash at .*}}
|
||||
log_message = Incoming SRS bounce to $local_part@$domain
|
||||
|
||||
# Deny if the local part contains @ or % or / or | or !. These are
|
||||
# rarely found in genuine local parts, but are often tried by people
|
||||
# looking to circumvent relaying restrictions.
|
||||
|
@ -697,6 +724,33 @@ autowhitelist_filter:
|
|||
unseen
|
||||
allow_filter = true
|
||||
|
||||
srs_bounce:
|
||||
senders = :
|
||||
driver = redirect
|
||||
domains = +local_domains
|
||||
allow_fail
|
||||
allow_defer
|
||||
local_part_prefix = srs0+ : srs0- : srs0= : srs1+ : srs1- : srs1=
|
||||
caseful_local_part
|
||||
address_data = ${readsocket{/run/srsd/srsd.sock}{REVERSE $local_part_prefix$local_part@$domain}{5s}{ }{:defer: SRS daemon failure}}
|
||||
data = ${sg {$address_data} {^SRS: Case insensitive hash match detected. Someone smashed case in the local-part\. .* ([^ ]+)@([^ ]+)\$} {\N$1@$2\N} }
|
||||
headers_add = X-SRS: Decoded valid SRS return address to ${quote_local_part:${local_part:$address_data}}@${domain:$address_data} by $primary_hostname
|
||||
|
||||
srs_forward:
|
||||
driver = redirect
|
||||
senders = ! : ! *@+local_domains
|
||||
domains = ! +local_domains : ! +relay_to_domains
|
||||
condition = ${lookup mysql{SELECT vm_domains.id FROM vm_domains WHERE vm_domains.domain='${original_domain}' AND vm_domains.status = '1'}}
|
||||
address_data = ${readsocket{/run/srsd/srsd.sock}\
|
||||
{FORWARD $sender_address_local_part@$sender_address_domain $original_domain\n}\
|
||||
{5s}{\n}{:defer: SRS daemon failure}}
|
||||
errors_to = ${quote_local_part:${local_part:$address_data}}@${domain:$address_data}
|
||||
data = ${quote_local_part:$local_part}@$domain
|
||||
headers_add = X-SRS-Forward: from $sender_address to $original_local_part@$original_domain forwarded to $local_part@$domain by $primary_hostname
|
||||
repeat_use = false
|
||||
allow_defer
|
||||
no_verify
|
||||
|
||||
# This router routes addresses that are not in local domains by doing a DNS
|
||||
# lookup on the domain name. Any domain that resolves to 0.0.0.0 or to a
|
||||
# loopback interface address (127.0.0.0/8) is treated as if it had no DNS
|
||||
|
@ -735,24 +789,6 @@ junk_filter:
|
|||
condition = ${lookup mysql{SELECT vm_mboxes.id FROM vm_domains, vm_mboxes WHERE vm_domains.domain='${domain}' AND vm_mboxes.mbox='${local_part}' AND vm_domains.id = vm_mboxes.domain_id AND vm_domains.status = '1' AND vm_mboxes.status = '1' AND vm_mboxes.filter > '0'}}
|
||||
transport = junk_delivery
|
||||
|
||||
spamcheck_router:
|
||||
driver = accept
|
||||
domains = +local_domains
|
||||
local_part_suffix = +*
|
||||
local_part_suffix_optional = true
|
||||
condition = ${if and { \
|
||||
{ !eq {$received_protocol}{spam-scanned}} \
|
||||
{ !eq {$sender_address_domain}{$domain}} \
|
||||
{ < {$message_size}{512k}} \
|
||||
{ !eq {$header_X-Junk-Flag:}{YES}} \
|
||||
{ !eq {$header_X-Whitelist-Flag:}{YES}} \
|
||||
{ eq {${lookup mysql{SELECT vm_mboxes.status FROM vm_domains, vm_mboxes WHERE vm_domains.domain='${domain}' AND vm_mboxes.mbox='${local_part}' AND vm_domains.id = vm_mboxes.domain_id AND vm_domains.status = '1'}{$value}fail}}{1} } \
|
||||
} {yes} {no}}
|
||||
# check domain & mbox 'status'?
|
||||
# Check for other headers too? Blacklist, SPF, DKIM failers go directly to Spam folder without spam scan??? - actually they should go to spam folder before this router is hit?
|
||||
headers_remove = X-Spam-Checker-Version:X-Spam-Flag:X-Spam-Level:X-Spam-Status:X-Spam-Score:X-Spam-Report
|
||||
transport = spamcheck
|
||||
|
||||
spam_filter:
|
||||
driver = accept
|
||||
domains = +local_domains
|
||||
|
@ -772,6 +808,7 @@ virtual_vacation:
|
|||
# do not reply to errors or lists or spam-scanned messages, require vacation message in db
|
||||
condition = ${if and { \
|
||||
{ !match {$h_precedence:} {(?i)junk|bulk|list}} \
|
||||
{ !eq {$received_protocol}{spam-scanned}} \
|
||||
{ !eq {$sender_address} {}} \
|
||||
{ eq {${lookup mysql{SELECT vm_autoresponders.mode FROM vm_domains, vm_mboxes, vm_autoresponders WHERE vm_domains.domain='${domain}' AND vm_mboxes.mbox='${local_part}' AND vm_domains.id = vm_mboxes.domain_id AND vm_autoresponders.mbox_id = vm_mboxes.id AND vm_domains.status = '1' AND vm_mboxes.status = '1' AND vm_autoresponders.status = '1'}{$value}fail}}{Vacation}} \
|
||||
} {yes} {no}}
|
||||
|
@ -797,6 +834,7 @@ virtual_autoresponder:
|
|||
# do not reply to errors or lists or spam-scanned messages, require autoresponder message in db
|
||||
condition = ${if and { \
|
||||
{ !match {$h_precedence:} {(?i)junk|bulk|list}} \
|
||||
{ !eq {$received_protocol}{spam-scanned}} \
|
||||
{ !eq {$sender_address} {}} \
|
||||
{ eq {${lookup mysql{SELECT vm_autoresponders.mode FROM vm_domains, vm_mboxes, vm_autoresponders WHERE vm_domains.domain='${domain}' AND vm_mboxes.mbox='${local_part}' AND vm_domains.id = vm_mboxes.domain_id AND vm_autoresponders.mbox_id = vm_mboxes.id AND vm_domains.status = '1' AND vm_mboxes.status = '1' AND vm_autoresponders.status = '1'}{$value}fail}}{Autoresponder} } \
|
||||
} {yes} {no}}
|
||||
|
@ -813,13 +851,38 @@ virtual_autoresponder:
|
|||
unseen
|
||||
no_verify
|
||||
|
||||
virtual_forward:
|
||||
virtual_forward_and_drop:
|
||||
driver = redirect
|
||||
domains = +local_domains
|
||||
condition = ${if !eq {$received_protocol}{spam-scanned}}
|
||||
local_part_suffix = +*
|
||||
local_part_suffix_optional = true
|
||||
data = ${lookup mysql{SELECT vm_forwards.forward_to FROM vm_domains, vm_mboxes, vm_forwards WHERE vm_domains.domain='${domain}' AND vm_domains.id = vm_mboxes.domain_id AND vm_mboxes.mbox='${local_part}' AND vm_mboxes.id=vm_forwards.mbox_id AND vm_domains.status = '1' AND vm_mboxes.status = '1' AND vm_forwards.save_local='0'}}
|
||||
|
||||
virtual_forward_and_keep:
|
||||
driver = redirect
|
||||
domains = +local_domains
|
||||
condition = ${if !eq {$received_protocol}{spam-scanned}}
|
||||
local_part_suffix = +*
|
||||
local_part_suffix_optional = true
|
||||
data = ${lookup mysql{SELECT CONCAT('${local_part}@${domain}\n', vm_forwards.forward_to) FROM vm_domains, vm_mboxes, vm_forwards WHERE vm_domains.domain='${domain}' AND vm_domains.id = vm_mboxes.domain_id AND vm_mboxes.mbox='${local_part}' AND vm_mboxes.id=vm_forwards.mbox_id AND vm_domains.status = '1' AND vm_mboxes.status = '1' AND vm_forwards.save_local='1'}}
|
||||
|
||||
spamcheck_router:
|
||||
driver = accept
|
||||
domains = +local_domains
|
||||
local_part_suffix = +*
|
||||
local_part_suffix_optional = true
|
||||
data = ${lookup mysql{SELECT vm_forwards.forward_to FROM vm_domains, vm_mboxes, vm_forwards WHERE vm_domains.domain='${domain}' AND vm_domains.id = vm_mboxes.domain_id AND vm_mboxes.mbox='${local_part}' AND vm_mboxes.id=vm_forwards.mbox_id AND vm_domains.status = '1' AND vm_mboxes.status = '1' }}
|
||||
unseen = ${lookup mysql{SELECT vm_forwards.id FROM vm_domains, vm_mboxes, vm_forwards WHERE vm_domains.domain='${domain}' AND vm_domains.id = vm_mboxes.domain_id AND vm_mboxes.mbox='${local_part}' AND vm_mboxes.id=vm_forwards.mbox_id AND vm_domains.status = '1' AND vm_mboxes.status = '1' AND vm_forwards.save_local='1'}{true}{false}}
|
||||
condition = ${if and { \
|
||||
{ !eq {$received_protocol}{spam-scanned}} \
|
||||
{ !eq {$sender_address_domain}{$domain}} \
|
||||
{ < {$message_size}{512k}} \
|
||||
{ !eq {$header_X-Junk-Flag:}{YES}} \
|
||||
{ !eq {$header_X-Whitelist-Flag:}{YES}} \
|
||||
{ eq {${lookup mysql{SELECT vm_mboxes.status FROM vm_domains, vm_mboxes WHERE vm_domains.domain='${domain}' AND vm_mboxes.mbox='${local_part}' AND vm_domains.id = vm_mboxes.domain_id AND vm_domains.status = '1' AND vm_mboxes.status = '1'}{$value}fail}}{1} } \
|
||||
} {yes} {no}}
|
||||
# Check for other headers too? Blacklist, SPF, DKIM failers go directly to Spam folder without spam scan??? - actually they should go to spam folder before this router is hit?
|
||||
headers_remove = X-Spam-Checker-Version:X-Spam-Flag:X-Spam-Level:X-Spam-Status:X-Spam-Score:X-Spam-Report
|
||||
transport = spamcheck
|
||||
|
||||
user_filter:
|
||||
driver = redirect
|
||||
|
@ -1094,10 +1157,8 @@ address_reply:
|
|||
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.
|
||||
# retries every 15 minutes for 2 hours, then every 2 hours until 1 full day
|
||||
# has passed since the first delivery failed.
|
||||
|
||||
# Domain Error Retries
|
||||
# ------ ----- -------
|
||||
|
@ -1114,7 +1175,6 @@ begin retry
|
|||
begin rewrite
|
||||
|
||||
|
||||
|
||||
######################################################################
|
||||
# AUTHENTICATION CONFIGURATION #
|
||||
######################################################################
|
||||
|
|
16
install.sh
16
install.sh
|
@ -59,7 +59,7 @@ mysql -e "GRANT ALL PRIVILEGES ON vmail.* TO 'vmail'@'localhost';"
|
|||
mysqladmin flush-privileges
|
||||
|
||||
# install mail server software
|
||||
apt -y install exim4-daemon-heavy spf-tools-perl spamassassin libclass-dbi-mysql-perl dovecot-core dovecot-imapd dovecot-mysql dovecot-pop3d dovecot-lmtpd
|
||||
apt -y install exim4-daemon-heavy spf-tools-perl spamassassin srs libclass-dbi-mysql-perl dovecot-core dovecot-imapd dovecot-mysql dovecot-pop3d dovecot-lmtpd
|
||||
|
||||
# configure system users
|
||||
apt -y install ssl-cert
|
||||
|
@ -97,6 +97,16 @@ chmod 644 /etc/spamassassin/local.cf
|
|||
chown debian-spamd:mail /etc/spamassassin/sql.cf
|
||||
chmod 640 /etc/spamassassin/sql.cf
|
||||
|
||||
# srsd
|
||||
# bug fixes for libmail-srs-perl. still needed as of v0.31-6 on Ubuntu 20.04
|
||||
sed -i 's|/tmp/srsd|/run/srsd/srsd.sock|' /usr/share/perl5/Mail/SRS/Daemon.pm
|
||||
sed -i '/Until we decide that forward/,+3d' /usr/share/perl5/Mail/SRS/Daemon.pm
|
||||
cp systemd/srsd.service /lib/systemd/system/srsd.service
|
||||
chmod 644 /lib/systemd/system/srsd.service
|
||||
systemctl daemon-reload
|
||||
systemctl enable srsd
|
||||
systemctl start srsd
|
||||
|
||||
# exim config
|
||||
maildomain=`hostname -d`
|
||||
sed -i 's/size 10M/daily/g' /etc/logrotate.d/exim4-paniclog
|
||||
|
@ -112,6 +122,10 @@ chmod 640 /etc/exim4/skip_greylisting_hosts
|
|||
sed -i "s|example.com|$maildomain|g" /etc/exim4/skip_greylisting_hosts
|
||||
sed -i "s|password|$VMAILPASS|g" /etc/exim4/exim_local.conf
|
||||
sed -i "s|example.com|$maildomain|g" /etc/exim4/exim_local.conf
|
||||
touch /etc/exim4/srsd.secret
|
||||
chmod 640 /etc/exim4/srsd.secret
|
||||
chown Debian-exim:Debian-exim /etc/exim4/srsd.secret
|
||||
pwgen -N 1 -cny 64 > /etc/exim4/srsd.secret
|
||||
|
||||
# dovecot config
|
||||
mkdir /etc/dovecot/sites.d
|
||||
|
|
15
systemd/srsd.service
Normal file
15
systemd/srsd.service
Normal file
|
@ -0,0 +1,15 @@
|
|||
[Unit]
|
||||
Description=Sender Rewriting Scheme Daemon
|
||||
|
||||
[Service]
|
||||
Type=exec
|
||||
User=Debian-exim
|
||||
Group=Debian-exim
|
||||
ExecStart=/usr/bin/srsd --secretfile /etc/exim4/srsd.secret --hashlength 24
|
||||
PIDFile=/run/srsd/srsd.pid
|
||||
Restart=on-failure
|
||||
RuntimeDirectory=srsd
|
||||
RuntimeDirectoryMode=0750
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
Loading…
Reference in New Issue
Block a user