summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mailman/config/schema.cfg40
-rw-r--r--src/mailman/rules/dmarc.py46
2 files changed, 46 insertions, 40 deletions
diff --git a/src/mailman/config/schema.cfg b/src/mailman/config/schema.cfg
index fdf4c2b6f..33fac3716 100644
--- a/src/mailman/config/schema.cfg
+++ b/src/mailman/config/schema.cfg
@@ -20,6 +20,7 @@
# formats under the lazr.config regime to define all system configuration
# options. See <https://launchpad.net/lazr.config> for details.
+
[mailman]
# This address is the "site owner" address. Certain messages which must be
# delivered to a human, but which can't be delivered to a list owner (e.g. a
@@ -74,22 +75,6 @@ filtered_messages_are_preservable: no
# The command should print the converted text to stdout.
html_to_plain_text_command: /usr/bin/lynx -dump $filename
-# Parameters for DMARC DNS lookups. If you are seeing 'DNSException: Unable
-# to query DMARC policy ...' entries in your error log, you may need to adjust
-# these.
-#
-# The time to wait for a response from a name server before timeout.
-dmarc_resolver_timeout: 3s
-# The total time to spend trying to get an answer to the DNS question.
-dmarc_resolver_lifetime: 5s
-
-# A URL from which to retrieve the data for the algorithm that computes
-# Organizational Domains for DMARC policy lookup purposes. This can be
-# anything handled by the Python urllib.request.urlopen function. See
-# https://publicsuffix.org/list/ for info.
-dmarc_org_domain_data: https://publicsuffix.org/list/public_suffix_list.dat
-
-
[shell]
# `mailman shell` (also `withlist`) gives you an interactive prompt that you
@@ -226,6 +211,7 @@ max_restarts: 10
# ignore this.
sleep_time: 1s
+
[database]
# The class implementing the IDatabase.
class: mailman.database.sqlite.SQLiteDatabase
@@ -238,6 +224,7 @@ class: mailman.database.sqlite.SQLiteDatabase
url: sqlite:///$DATA_DIR/mailman.db
debug: no
+
[logging.template]
# This defines various log settings. The options available are:
#
@@ -334,7 +321,6 @@ success: $msgid post to $listname from $sender, $size bytes
refused: $msgid post to $listname from $sender, $size bytes, $refused failures
failure: $msgid delivery to $recip failed with code $smtpcode, $smtpmsg
-
[logging.subscribe]
[logging.vette]
@@ -863,3 +849,23 @@ rewrite_duplicate_headers:
CC X-Original-CC
Content-Transfer-Encoding X-Original-Content-Transfer-Encoding
MIME-Version X-MIME-Version
+
+
+[dmarc]
+# RFC 7489 - Domain-based Message Authentication, Reporting, and Conformance.
+# https://en.wikipedia.org/wiki/DMARC
+
+# Parameters for DMARC DNS lookups. If you are seeing 'DNSException: Unable
+# to query DMARC policy ...' entries in your error log, you may need to adjust
+# these.
+#
+# The time to wait for a response from a name server before timeout.
+resolver_timeout: 3s
+# The total time to spend trying to get an answer to the DNS question.
+resolver_lifetime: 5s
+
+# A URL from which to retrieve the data for the algorithm that computes
+# Organizational Domains for DMARC policy lookup purposes. This can be
+# anything handled by the Python urllib.request.urlopen function. See
+# https://publicsuffix.org/list/ for info.
+org_domain_data: https://publicsuffix.org/list/public_suffix_list.dat
diff --git a/src/mailman/rules/dmarc.py b/src/mailman/rules/dmarc.py
index d7e76bf0f..c8c4e56f4 100644
--- a/src/mailman/rules/dmarc.py
+++ b/src/mailman/rules/dmarc.py
@@ -83,7 +83,7 @@ def _get_org_dom(domain):
# Domain which may be the same as the input.
global s_dict
if not s_dict:
- _get_suffixes(config.mailman.dmarc_org_domain_data)
+ _get_suffixes(config.dmarc.org_domain_data)
hits = []
d = domain.lower().split('.')
d.reverse()
@@ -108,32 +108,12 @@ def _get_org_dom(domain):
return _get_dom(d, l)
-def _IsDMARCProhibited(mlist, email):
- # This takes an email address, and returns True if DMARC policy is
- # p=reject or quarantine.
- email = email.lower()
- # Scan from the right in case quoted local part has an '@'.
- local, at, from_domain = email.rpartition('@')
- if at != '@':
- return False
- x = _DMARCProhibited(mlist, email, '_dmarc.{}'.format(from_domain))
- if x is not KEEP_LOOKING:
- return x
- org_dom = _get_org_dom(from_domain)
- if org_dom != from_domain:
- x = _DMARCProhibited(
- mlist, email, '_dmarc.{}'.format(org_dom), org=True)
- if x is not KEEP_LOOKING:
- return x
- return False
-
-
def _DMARCProhibited(mlist, email, dmarc_domain, org=False):
resolver = dns.resolver.Resolver()
resolver.timeout = as_timedelta(
- config.mailman.dmarc_resolver_timeout).total_seconds()
+ config.dmarc.resolver_timeout).total_seconds()
resolver.lifetime = as_timedelta(
- config.mailman.dmarc_resolver_lifetime).total_seconds()
+ config.dmarc.resolver_lifetime).total_seconds()
try:
txt_recs = resolver.query(dmarc_domain, dns.rdatatype.TXT)
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
@@ -210,6 +190,26 @@ def _DMARCProhibited(mlist, email, dmarc_domain, org=False):
return False
+def _IsDMARCProhibited(mlist, email):
+ # This takes an email address, and returns True if DMARC policy is
+ # p=reject or quarantine.
+ email = email.lower()
+ # Scan from the right in case quoted local part has an '@'.
+ local, at, from_domain = email.rpartition('@')
+ if at != '@':
+ return False
+ x = _DMARCProhibited(mlist, email, '_dmarc.{}'.format(from_domain))
+ if x is not KEEP_LOOKING:
+ return x
+ org_dom = _get_org_dom(from_domain)
+ if org_dom != from_domain:
+ x = _DMARCProhibited(
+ mlist, email, '_dmarc.{}'.format(org_dom), org=True)
+ if x is not KEEP_LOOKING:
+ return x
+ return False
+
+
@public
@implementer(IRule)
class DMARCMitigation: