aboutsummaryrefslogtreecommitdiffstats
path: root/Mailman/Utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman/Utils.py')
-rw-r--r--Mailman/Utils.py45
1 files changed, 29 insertions, 16 deletions
diff --git a/Mailman/Utils.py b/Mailman/Utils.py
index 37ae940b..89b7975e 100644
--- a/Mailman/Utils.py
+++ b/Mailman/Utils.py
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2011 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2014 by the Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -231,7 +231,7 @@ def ValidateEmail(s):
# Pretty minimal, cheesy check. We could do better...
if not s or s.count(' ') > 0:
raise Errors.MMBadEmailError
- if _badchars.search(s) or s[0] == '-':
+ if _badchars.search(s):
raise Errors.MMHostileAddress, s
user, domain_parts = ParseEmail(s)
# This means local, unqualified addresses, are not allowed
@@ -240,8 +240,9 @@ def ValidateEmail(s):
if len(domain_parts) < 2:
raise Errors.MMBadEmailError, s
# domain parts may only contain ascii letters, digits and hyphen
+ # and must not begin with hyphen.
for p in domain_parts:
- if len(_valid_domain.sub('', p)) > 0:
+ if len(p) == 0 or p[0] == '-' or len(_valid_domain.sub('', p)) > 0:
raise Errors.MMHostileAddress, s
@@ -1067,7 +1068,8 @@ def suspiciousHTML(html):
# This takes an email address, and returns True if DMARC policy is p=reject
-def IsDmarcProhibited(email):
+# or possibly quarantine.
+def IsDMARCProhibited(email):
if not dns_resolver:
return False
@@ -1085,7 +1087,8 @@ def IsDmarcProhibited(email):
except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
return False
except DNSException, e:
- syslog('error', 'DNSException: Unable to query DMARC policy for %s (%s). %s',
+ syslog('error',
+ 'DNSException: Unable to query DMARC policy for %s (%s). %s',
email, dmarc_domain, e.__class__)
return False
else:
@@ -1098,10 +1101,12 @@ def IsDmarcProhibited(email):
want_names = set([dmarc_domain + '.'])
for txt_rec in txt_recs.response.answer:
if txt_rec.rdtype == dns.rdatatype.CNAME:
- cnames[txt_rec.name.to_text()] = txt_rec.items[0].target.to_text()
+ cnames[txt_rec.name.to_text()] = (
+ txt_rec.items[0].target.to_text())
if txt_rec.rdtype != dns.rdatatype.TXT:
continue
- results_by_name[txt_rec.name.to_text()].append("".join(txt_rec.items[0].strings))
+ results_by_name[txt_rec.name.to_text()].append(
+ "".join(txt_rec.items[0].strings))
expands = list(want_names)
seen = set(expands)
while expands:
@@ -1115,26 +1120,34 @@ def IsDmarcProhibited(email):
want_names.discard(item)
if len(want_names) != 1:
- syslog('error', 'multiple DMARC entries in results for %s, processing each to be strict',
- dmarc_domain)
+ syslog('error',
+ """multiple DMARC entries in results for %s,
+ processing each to be strict""",
+ dmarc_domain)
for name in want_names:
if name not in results_by_name:
continue
- dmarcs = filter(lambda n: n.startswith('v=DMARC1;'), results_by_name[name])
+ dmarcs = filter(lambda n: n.startswith('v=DMARC1;'),
+ results_by_name[name])
if len(dmarcs) == 0:
return False
if len(dmarcs) > 1:
- syslog('error', 'RRset of TXT records for %s has %d v=DMARC1 entries; testing them all',
+ syslog('error',
+ """RRset of TXT records for %s has %d v=DMARC1 entries;
+ testing them all""",
dmarc_domain, len(dmarc))
for entry in dmarcs:
if re.search(r'\bp=reject\b', entry, re.IGNORECASE):
- syslog('info', 'DMARC lookup for %s (%s) found p=reject in %s = %s',
- email, dmarc_domain, name, entry)
+# syslog('info',
+# 'DMARC lookup for %s (%s) found p=reject in %s = %s',
+# email, dmarc_domain, name, entry)
return True
- if re.search(r'\bp=quarantine\b', entry, re.IGNORECASE):
- syslog('info', 'DMARC lookup for %s (%s) found p=quarantine in %s = %s',
- email, dmarc_domain, name, entry)
+ if (mm_cfg.DMARC_QUARANTINE_MODERATION_ACTION and
+ re.search(r'\bp=quarantine\b', entry, re.IGNORECASE)):
+# syslog('info',
+# 'DMARC lookup for %s (%s) found p=quarantine in %s = %s',
+# email, dmarc_domain, name, entry)
return True
return False