mirror of
https://github.com/chatmail/relay.git
synced 2026-05-12 00:54:37 +00:00
feat: DKIM-sign bounce messages (mainly "user does not exist")
This is based on Jagoda's https://github.com/chatmail/relay/pull/874 but comes with a simpler and more robust test. TODO: requires https://github.com/chatmail/filtermail/pull/149
This commit is contained in:
@@ -51,12 +51,16 @@ smtps inet n - y - 5000 smtpd
|
||||
-o smtpd_proxy_filter=127.0.0.1:{{ config.filtermail_smtp_port }}
|
||||
#628 inet n - y - - qmqpd
|
||||
pickup unix n - y 60 1 pickup
|
||||
cleanup unix n - y - 0 cleanup
|
||||
{% if not config.ipv4_relay %} -o cleanup_service_name=signlocal
|
||||
{% endif %}cleanup unix n - y - 0 cleanup
|
||||
qmgr unix n - n 300 1 qmgr
|
||||
#qmgr unix n - n 300 1 oqmgr
|
||||
tlsmgr unix - - y 1000? 1 tlsmgr
|
||||
rewrite unix - - y - - trivial-rewrite
|
||||
bounce unix - - y - 0 bounce
|
||||
{% if not config.ipv4_relay %} -o internal_mail_filter_classes=bounce
|
||||
-o cleanup_service_name=signlocal
|
||||
{% endif %}
|
||||
defer unix - - y - 0 bounce
|
||||
trace unix - - y - 0 bounce
|
||||
verify unix - - y - 1 verify
|
||||
@@ -102,6 +106,15 @@ filter unix - n n - - lmtp
|
||||
authclean unix n - - - 0 cleanup
|
||||
-o header_checks=regexp:/etc/postfix/submission_header_cleanup
|
||||
|
||||
{% if not config.ipv4_relay %}
|
||||
# DKIM-sign locally generated mail (bounces, DSNs).
|
||||
# These bypass smtpd, so they need explicit milter configuration.
|
||||
signlocal unix n - - - 0 cleanup
|
||||
-o syslog_name=postfix/signlocal
|
||||
-o milter_macro_daemon_name=ORIGINATING
|
||||
-o non_smtpd_milters=unix:opendkim/opendkim.sock
|
||||
{% endif %}
|
||||
|
||||
lmtp-filtermail unix - - y - 10000 lmtp
|
||||
-o syslog_name=postfix/lmtp-filtermail
|
||||
-o lmtp_header_checks=
|
||||
|
||||
@@ -194,6 +194,34 @@ def test_reject_missing_dkim(cmsetup, maildata, from_addr):
|
||||
s.sendmail(from_addr=from_addr, to_addrs=recipient.addr, msg=msg)
|
||||
|
||||
|
||||
def test_bounces_are_dkim_signed(cmsetup, cmsetup2, maildata, maildomain):
|
||||
# we send a message to non-existant user and expect a bounce message
|
||||
# which will only get through if the bounce message was DKIM-signed
|
||||
|
||||
if is_valid_ipv4(maildomain):
|
||||
pytest.skip("DKIM is not configured on IPv4-only relays")
|
||||
|
||||
sender = cmsetup2.gen_users(1)[0]
|
||||
nonexistent = f"nosuchuser_test42@{cmsetup.maildomain}"
|
||||
|
||||
msg = maildata(
|
||||
"encrypted.eml",
|
||||
from_addr=sender.addr,
|
||||
to_addr=nonexistent,
|
||||
).as_string()
|
||||
sender.smtp.sendmail(sender.addr, [nonexistent], msg)
|
||||
|
||||
def bounce_in_inbox():
|
||||
messages = sender.imap.fetch_all_messages()
|
||||
for m in messages:
|
||||
if "mail delivery" in m.lower() or "undelivered" in m.lower():
|
||||
return m
|
||||
raise ValueError("bounce not yet in inbox")
|
||||
|
||||
bounce = try_n_times(30, bounce_in_inbox)
|
||||
assert "nosuchuser_test42" in bounce
|
||||
|
||||
|
||||
def try_n_times(n, f):
|
||||
for _ in range(n - 1):
|
||||
try:
|
||||
|
||||
@@ -19,6 +19,7 @@ def format_mail_domain(raw_domain: str) -> str:
|
||||
DomainValidator().validate_domain_re(raw_domain)
|
||||
return raw_domain
|
||||
|
||||
|
||||
conftestdir = Path(__file__).parent
|
||||
|
||||
|
||||
@@ -466,6 +467,11 @@ def cmsetup(maildomain, gencreds, ssl_context):
|
||||
return CMSetup(maildomain, gencreds, ssl_context)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def cmsetup2(maildomain2, gencreds, ssl_context):
|
||||
return CMSetup(maildomain2, gencreds, ssl_context)
|
||||
|
||||
|
||||
class CMSetup:
|
||||
def __init__(self, maildomain, gencreds, ssl_context):
|
||||
self.maildomain = maildomain
|
||||
@@ -476,7 +482,7 @@ class CMSetup:
|
||||
print(f"Creating {num} online users")
|
||||
users = []
|
||||
for i in range(num):
|
||||
addr, password = self.gencreds()
|
||||
addr, password = self.gencreds(format_mail_domain(self.maildomain))
|
||||
user = CMUser(self.maildomain, addr, password, self.ssl_context)
|
||||
assert user.smtp
|
||||
users.append(user)
|
||||
|
||||
Reference in New Issue
Block a user