From 7ec3c9cbbb0bb8fa4b966a52c51a9c916b8e690e Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Sun, 6 Mar 2016 12:25:06 -0800 Subject: Better logging of DMARC lookup DNS exceptions. --- Mailman/Utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Mailman') diff --git a/Mailman/Utils.py b/Mailman/Utils.py index f821f13a..37336e0d 100644 --- a/Mailman/Utils.py +++ b/Mailman/Utils.py @@ -1267,7 +1267,7 @@ def _DMARCProhibited(mlist, email, dmarc_domain): except DNSException, e: syslog('error', 'DNSException: Unable to query DMARC policy for %s (%s). %s', - email, dmarc_domain, e.__class__) + email, dmarc_domain, e.__doc__) return 'continue' else: # people are already being dumb, don't trust them to provide honest DNS -- cgit v1.2.3 From bf7b73081b17eda9589e5cd6ee0242912633d306 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Sun, 6 Mar 2016 22:27:49 -0800 Subject: Fixed CommandRunner shunting a message with a null byte in the body. --- Mailman/Queue/CommandRunner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Mailman') diff --git a/Mailman/Queue/CommandRunner.py b/Mailman/Queue/CommandRunner.py index c5cc3d94..a9f6f000 100644 --- a/Mailman/Queue/CommandRunner.py +++ b/Mailman/Queue/CommandRunner.py @@ -134,7 +134,8 @@ class Results: handler = sys.modules[modname] # ValueError can be raised if cmd has dots in it. # and KeyError if cmd is otherwise good but ends with a dot. - except (ImportError, ValueError, KeyError): + # and TypeError if cmd has a null byte. + except (ImportError, ValueError, KeyError, TypeError): # If we're on line zero, it was the Subject: header that didn't # contain a command. It's possible there's a Re: prefix (or # localized version thereof) on the Subject: line that's messing -- cgit v1.2.3 From 41a9b83a0d0a1253aeb5d7aa108852128de504ee Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Thu, 10 Mar 2016 17:53:32 -0800 Subject: Fixed _set_date() in pipermail.py do do a better job. --- Mailman/Archiver/pipermail.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'Mailman') diff --git a/Mailman/Archiver/pipermail.py b/Mailman/Archiver/pipermail.py index 9c54bbd9..15decd40 100644 --- a/Mailman/Archiver/pipermail.py +++ b/Mailman/Archiver/pipermail.py @@ -16,6 +16,7 @@ __version__ = '0.09 (Mailman edition)' VERSION = __version__ CACHESIZE = 100 # Number of slots in the cache +from Mailman import mm_cfg from Mailman import Errors from Mailman.Mailbox import ArchiverMailbox from Mailman.Logging.Syslog import syslog @@ -230,21 +231,30 @@ class Article: self.body = s.readlines() def _set_date(self, message): - def floatdate(header): - missing = [] - datestr = message.get(header, missing) - if datestr is missing: + def floatdate(datestr): + if not datestr: return None date = parsedate_tz(datestr) try: - return mktime_tz(date) + date = mktime_tz(date) + if (date < 0 or + date - time.time() > + mm_cfg.ARCHIVER_ALLOWABLE_SANE_DATE_SKEW + ): + return None + return date except (TypeError, ValueError, OverflowError): return None - date = floatdate('date') + date = floatdate(message.get('date')) + if date is None: + date = floatdate(message.get('x-list-received-date')) + if date is None: + date = floatdate(re.sub(r'^.*;\s*', '', + message.get('received'), flags=re.S)) if date is None: - date = floatdate('x-list-received-date') + date = floatdate(re.sub(r'From \s*\S+\s+', '', + message.get_unixfrom())) if date is None: - # What's left to try? date = self._last_article_time + 1 self._last_article_time = date self.date = '%011i' % date -- cgit v1.2.3 From c34680adb21d669521ca80c086b4913ba370fb79 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Fri, 11 Mar 2016 09:32:21 -0800 Subject: Fixed bug in last commit if no Received: header. --- Mailman/Archiver/pipermail.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Mailman') diff --git a/Mailman/Archiver/pipermail.py b/Mailman/Archiver/pipermail.py index 15decd40..c03d43b3 100644 --- a/Mailman/Archiver/pipermail.py +++ b/Mailman/Archiver/pipermail.py @@ -250,10 +250,10 @@ class Article: date = floatdate(message.get('x-list-received-date')) if date is None: date = floatdate(re.sub(r'^.*;\s*', '', - message.get('received'), flags=re.S)) + message.get('received', ''), flags=re.S)) if date is None: date = floatdate(re.sub(r'From \s*\S+\s+', '', - message.get_unixfrom())) + message.get_unixfrom() or '' )) if date is None: date = self._last_article_time + 1 self._last_article_time = date -- cgit v1.2.3 From 52c355755a5b33c975ec9b3a7535236685bf0c18 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Sat, 2 Apr 2016 23:18:40 -0700 Subject: Attempt to improve threading of posts gated to Usenet. --- Mailman/Queue/NewsRunner.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'Mailman') diff --git a/Mailman/Queue/NewsRunner.py b/Mailman/Queue/NewsRunner.py index 449532fb..d62cb8dd 100644 --- a/Mailman/Queue/NewsRunner.py +++ b/Mailman/Queue/NewsRunner.py @@ -1,4 +1,4 @@ -# Copyright (C) 2000-2015 by the Free Software Foundation, Inc. +# Copyright (C) 2000-2016 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 @@ -12,7 +12,8 @@ # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. """NNTP queue runner.""" @@ -109,7 +110,11 @@ def prepare_message(mlist, msg, msgdata): or msgdata.get('origsubj') if not mlist.news_prefix_subject_too and stripped_subject is not None: del msg['subject'] - msg['subject'] = stripped_subject + msg['Subject'] = stripped_subject + # Make sure we have a non-blank subject. + if not msg.get('subject', '').strip(): + del msg['subject'] + msg['Subject'] = '(no subject)' # Add the appropriate Newsgroups: header if msg['newsgroups'] is not None: # This message is gated from our list to it's associated usnet group. @@ -125,6 +130,9 @@ def prepare_message(mlist, msg, msgdata): # isn't ours with one of ours, so we need to parse it to be sure we're not # looping. # + # We also add the original Message-ID: to References: to try to help with + # threading issues and create another header for documentation. + # # Our Message-ID format is msgid = msg['message-id'] hackmsgid = True @@ -137,6 +145,18 @@ def prepare_message(mlist, msg, msgdata): if hackmsgid: del msg['message-id'] msg['Message-ID'] = Utils.unique_message_id(mlist) + if msgid: + msg['X-Mailman-Original-Message-ID'] = msgid + refs = msg['references'] + del msg['references'] + if not refs: + refs = msg.get('in-reply-to', '') + else: + msg['X-Mailman-Original-References'] = refs + if refs: + msg['References'] = '\n '.join([refs, msgid]) + else: + msg['References'] = msgid # Lines: is useful if msg['Lines'] is None: # BAW: is there a better way? -- cgit v1.2.3 From 93f11f1a9b9e6f2f1251b1efb75131e0c9839029 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Wed, 6 Apr 2016 07:37:27 -0700 Subject: Fixed a bug in ensuring gated news articles have a Subject:. --- Mailman/Queue/NewsRunner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Mailman') diff --git a/Mailman/Queue/NewsRunner.py b/Mailman/Queue/NewsRunner.py index d62cb8dd..fe693f28 100644 --- a/Mailman/Queue/NewsRunner.py +++ b/Mailman/Queue/NewsRunner.py @@ -112,7 +112,7 @@ def prepare_message(mlist, msg, msgdata): del msg['subject'] msg['Subject'] = stripped_subject # Make sure we have a non-blank subject. - if not msg.get('subject', '').strip(): + if not msg.get('subject', ''): del msg['subject'] msg['Subject'] = '(no subject)' # Add the appropriate Newsgroups: header -- cgit v1.2.3 From 325a8d245275d421094f71eb026801a0bc1b8a5f Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Sat, 9 Apr 2016 15:43:47 -0700 Subject: Honor an organizational domain's DMARC sp= policy for sub-domains. --- Mailman/Utils.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'Mailman') diff --git a/Mailman/Utils.py b/Mailman/Utils.py index 37336e0d..f6cf607e 100644 --- a/Mailman/Utils.py +++ b/Mailman/Utils.py @@ -1250,12 +1250,12 @@ def IsDMARCProhibited(mlist, email): return x o_dom = get_org_dom(f_dom) if o_dom != f_dom: - x = _DMARCProhibited(mlist, email, '_dmarc.' + o_dom) + x = _DMARCProhibited(mlist, email, '_dmarc.' + o_dom, org=True) if x != 'continue': return x return False -def _DMARCProhibited(mlist, email, dmarc_domain): +def _DMARCProhibited(mlist, email, dmarc_domain, org=False): try: resolver = dns.resolver.Resolver() @@ -1315,14 +1315,23 @@ def _DMARCProhibited(mlist, email, dmarc_domain): testing them all""", dmarc_domain, len(dmarc)) for entry in dmarcs: - if re.search(r'\bp=reject\b', entry, re.IGNORECASE): + mo = re.search(r'\bsp=(\w*)\b', entry, re.IGNORECASE) + if org and mo: + policy = mo.group(1).lower() + else: + mo = re.search(r'\bp=(\w*)\b', entry, re.IGNORECASE) + if mo: + policy = mo.group(1).lower() + else: + continue + if policy == 'reject': syslog('vette', '%s: DMARC lookup for %s (%s) found p=reject in %s = %s', mlist.real_name, email, dmarc_domain, name, entry) return True if (mlist.dmarc_quarantine_moderation_action and - re.search(r'\bp=quarantine\b', entry, re.IGNORECASE)): + policy == 'quarantine'): syslog('vette', '%s: DMARC lookup for %s (%s) found p=quarantine in %s = %s', mlist.real_name, email, dmarc_domain, name, entry) @@ -1331,7 +1340,7 @@ def _DMARCProhibited(mlist, email, dmarc_domain): if (mlist.dmarc_none_moderation_action and mlist.dmarc_quarantine_moderation_action and mlist.dmarc_moderation_action in (1, 2) and - re.search(r'\bp=none\b', entry, re.IGNORECASE)): + policy == 'none'): syslog('vette', '%s: DMARC lookup for %s (%s) found p=none in %s = %s', mlist.real_name, email, dmarc_domain, name, entry) -- cgit v1.2.3 From 35720b98bdaff9ad565fc2775f2b5aba918c52c9 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Sat, 9 Apr 2016 21:53:04 -0700 Subject: Use rfind rather than find to find '@' for domain splitting. --- Mailman/Utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Mailman') diff --git a/Mailman/Utils.py b/Mailman/Utils.py index f6cf607e..892bb5c8 100644 --- a/Mailman/Utils.py +++ b/Mailman/Utils.py @@ -1241,7 +1241,8 @@ def IsDMARCProhibited(mlist, email): return False email = email.lower() - at_sign = email.find('@') + # Scan from the right in case quoted local part has an '@'. + at_sign = email.rfind('@') if at_sign < 1: return False f_dom = email[at_sign+1:] -- cgit v1.2.3 From 5019dc01d25398b37596e86a7fa9c036576c4235 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Thu, 14 Apr 2016 16:25:57 -0700 Subject: Fixed missing VIRTUAL_MAILMAN_LOCAL_DOMAIN and duplicates in virtual-mailman. --- Mailman/MTA/Postfix.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'Mailman') diff --git a/Mailman/MTA/Postfix.py b/Mailman/MTA/Postfix.py index 8860459e..d18d850b 100644 --- a/Mailman/MTA/Postfix.py +++ b/Mailman/MTA/Postfix.py @@ -28,6 +28,7 @@ from Mailman import mm_cfg from Mailman import Utils from Mailman import LockFile from Mailman.i18n import C_ +from Mailman.MailList import MailList from Mailman.MTA.Utils import makealiases from Mailman.Logging.Syslog import syslog @@ -132,6 +133,11 @@ def _addvirtual(mlist, fp): sitedest = Utils.ParseEmail(siteaddr)[0] if mm_cfg.VIRTUAL_MAILMAN_LOCAL_DOMAIN: loopdest += '@' + mm_cfg.VIRTUAL_MAILMAN_LOCAL_DOMAIN + sitedest += '@' + mm_cfg.VIRTUAL_MAILMAN_LOCAL_DOMAIN + # If the site list's host_name is a virtual domain, adding it to the + # SITE ADDRESSES will duplicate the list posting entry, so comment it. + if _isvirtual(MailList(mm_cfg.MAILMAN_SITE_LIST, lock=False)): + siteaddr = '#' + siteaddr # Seek to the end of the text file, but if it's empty write the standard # disclaimer, and the loop catch address and site address. fp.seek(0, 2) @@ -179,6 +185,9 @@ def _check_for_virtual_loopaddr(mlist, filename): loopdest = Utils.ParseEmail(loopaddr)[0] siteaddr = Utils.get_site_email(mlist.host_name) sitedest = Utils.ParseEmail(siteaddr)[0] + if mm_cfg.VIRTUAL_MAILMAN_LOCAL_DOMAIN: + loopdest += '@' + mm_cfg.VIRTUAL_MAILMAN_LOCAL_DOMAIN + sitedest += '@' + mm_cfg.VIRTUAL_MAILMAN_LOCAL_DOMAIN infp = open(filename) omask = os.umask(007) try: @@ -230,7 +239,7 @@ def _check_for_virtual_loopaddr(mlist, filename): print >> outfp, '%s\t%s' % (siteaddr, sitedest) outfp.write(line) break - elif line.startswith(siteaddr): + elif line.startswith(siteaddr) or line.startswith('#' + siteaddr): # We just found it outfp.write(line) break -- cgit v1.2.3 From d90dcb330021a6bac598e7a032da77e4b1559034 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Sun, 17 Apr 2016 11:50:44 -0700 Subject: Bumped branch version to: 2.1.22 --- Mailman/Version.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Mailman') diff --git a/Mailman/Version.py b/Mailman/Version.py index 132648a8..413ac531 100644 --- a/Mailman/Version.py +++ b/Mailman/Version.py @@ -16,7 +16,7 @@ # USA. # Mailman version -VERSION = '2.1.21' +VERSION = '2.1.22' # And as a hex number in the manner of PY_VERSION_HEX ALPHA = 0xa @@ -28,7 +28,7 @@ FINAL = 0xf MAJOR_REV = 2 MINOR_REV = 1 -MICRO_REV = 21 +MICRO_REV = 22 REL_LEVEL = FINAL # at most 15 beta releases! REL_SERIAL = 0 -- cgit v1.2.3 From a70edc26ac027f6278a38bbe10c921b962adbf7a Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Tue, 19 Apr 2016 15:53:54 -0700 Subject: Use nonmember_rejection_notice as the default reject reason for a held nonmember post. --- Mailman/Handlers/Hold.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'Mailman') diff --git a/Mailman/Handlers/Hold.py b/Mailman/Handlers/Hold.py index 5452d06a..dcc7f963 100644 --- a/Mailman/Handlers/Hold.py +++ b/Mailman/Handlers/Hold.py @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2011 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2016 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 @@ -28,6 +28,7 @@ Finally an exception is raised to let the pipeline machinery know that further message handling should stop. """ +import re import email from email.MIMEText import MIMEText from email.MIMEMessage import MIMEMessage @@ -220,7 +221,14 @@ def hold_for_approval(mlist, msg, msgdata, exc): # We need to send both the reason and the rejection notice through the # translator again, because of the games we play above reason = Utils.wrap(exc.reason_notice()) - msgdata['rejection_notice'] = Utils.wrap(exc.rejection_notice(mlist)) + if isinstance(exc, NonMemberPost) and mlist.nonmember_rejection_notice: + msgdata['rejection_notice'] = Utils.wrap(re.sub( + '%(listowner)s', + mlist.GetOwnerEmail(), + mlist.nonmember_rejection_notice, + )) + else: + msgdata['rejection_notice'] = Utils.wrap(exc.rejection_notice(mlist)) id = mlist.HoldMessage(msg, reason, msgdata) # Now we need to craft and send a message to the list admin so they can # deal with the held message. -- cgit v1.2.3 From 97557e37b4436ea4bf09ef618e6105951266b838 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Wed, 20 Apr 2016 20:14:20 -0700 Subject: Remove (incorrect) re.sub in favor of str.replace. --- Mailman/Handlers/Hold.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'Mailman') diff --git a/Mailman/Handlers/Hold.py b/Mailman/Handlers/Hold.py index dcc7f963..2faebae1 100644 --- a/Mailman/Handlers/Hold.py +++ b/Mailman/Handlers/Hold.py @@ -28,7 +28,6 @@ Finally an exception is raised to let the pipeline machinery know that further message handling should stop. """ -import re import email from email.MIMEText import MIMEText from email.MIMEMessage import MIMEMessage @@ -222,11 +221,9 @@ def hold_for_approval(mlist, msg, msgdata, exc): # translator again, because of the games we play above reason = Utils.wrap(exc.reason_notice()) if isinstance(exc, NonMemberPost) and mlist.nonmember_rejection_notice: - msgdata['rejection_notice'] = Utils.wrap(re.sub( - '%(listowner)s', - mlist.GetOwnerEmail(), - mlist.nonmember_rejection_notice, - )) + msgdata['rejection_notice'] = Utils.wrap( + mlist.nonmember_rejection_notice.replace( + '%(listowner)s', owneraddr)) else: msgdata['rejection_notice'] = Utils.wrap(exc.rejection_notice(mlist)) id = mlist.HoldMessage(msg, reason, msgdata) -- cgit v1.2.3 From 7ed5fe5c0668f2014a7f7a08376b4e6a2e3e921c Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Thu, 21 Apr 2016 08:01:01 -0700 Subject: Implimented mm_cfg.SMTPLIB_DEBUG_LEVEL setting. --- Mailman/Defaults.py.in | 6 ++++++ Mailman/Handlers/SMTPDirect.py | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'Mailman') diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in index 04d7db8a..a71875ac 100755 --- a/Mailman/Defaults.py.in +++ b/Mailman/Defaults.py.in @@ -469,6 +469,12 @@ PUBLIC_MBOX = No #DELIVERY_MODULE = 'Sendmail' DELIVERY_MODULE = 'SMTPDirect' +# Sometimes there are 'low level' smtplib failures that are difficult to +# debug. To enable very verbose debugging info from smtplib to Mailman's +# error log, set the following to 1. This will only work if +# DELIVERY_MODULE = 'SMTPDirect' and Python is >= 2.4. +SMTPLIB_DEBUG_LEVEL = 0 + # MTA should name a module in Mailman/MTA which provides the MTA specific # functionality for creating and removing lists. Some MTAs like Exim can be # configured to automatically recognize new lists, in which case the MTA diff --git a/Mailman/Handlers/SMTPDirect.py b/Mailman/Handlers/SMTPDirect.py index 1d11d19a..32b03423 100644 --- a/Mailman/Handlers/SMTPDirect.py +++ b/Mailman/Handlers/SMTPDirect.py @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2011 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2016 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 @@ -61,6 +61,7 @@ class Connection: def __connect(self): self.__conn = smtplib.SMTP() + self.__conn.set_debuglevel(mm_cfg.SMTPLIB_DEBUG_LEVEL) self.__conn.connect(mm_cfg.SMTPHOST, mm_cfg.SMTPPORT) self.__numsessions = mm_cfg.SMTP_MAX_SESSIONS_PER_CONNECTION -- cgit v1.2.3 From 1adb205d2cf4e6c53ade88ff4dc9c3e42ee08d35 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Fri, 22 Apr 2016 10:13:16 -0700 Subject: White space left of Logout link is no longer part of the link. --- Mailman/Cgi/admindb.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Mailman') diff --git a/Mailman/Cgi/admindb.py b/Mailman/Cgi/admindb.py index af3f46d1..2cc348e6 100644 --- a/Mailman/Cgi/admindb.py +++ b/Mailman/Cgi/admindb.py @@ -1,4 +1,4 @@ -# Copyright (C) 1998-2014 by the Free Software Foundation, Inc. +# Copyright (C) 1998-2016 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 @@ -213,9 +213,10 @@ def main(): doc.AddItem(Link(admindburl, _('Click here to reload this page.'))) # Put 'Logout' link before the footer + doc.AddItem('\n
') doc.AddItem(Link('%s/logout' % admindburl, - '
%s
' % - _('Logout'))) + '%s' % _('Logout'))) + doc.AddItem('
\n') doc.AddItem(mlist.GetMailmanFooter()) print doc.Format() mlist.Save() -- cgit v1.2.3 From 6a615a1e6c6b3b03c3d8e334e6b097f29c9c975a Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Wed, 4 May 2016 18:27:19 -0700 Subject: Allow DMARC_ORGANIZATIONAL_DOMAIN_DATA_URL to be None or the null string. --- Mailman/Utils.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Mailman') diff --git a/Mailman/Utils.py b/Mailman/Utils.py index 892bb5c8..2dbaef0b 100644 --- a/Mailman/Utils.py +++ b/Mailman/Utils.py @@ -1170,6 +1170,8 @@ def get_suffixes(url): global s_dict if s_dict: return + if not url: + return try: d = urllib2.urlopen(url) except urllib2.URLError, e: -- cgit v1.2.3 From d2145608089777cd27175763cf9f71ca2a3159f5 Mon Sep 17 00:00:00 2001 From: Mark Sapiro Date: Fri, 6 May 2016 14:44:28 -0700 Subject: Implement SASL and STARTTLS in SMTPDirect.py. --- Mailman/Defaults.py.in | 16 ++++++++++++++++ Mailman/Handlers/SMTPDirect.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) (limited to 'Mailman') diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in index a71875ac..3569cc07 100755 --- a/Mailman/Defaults.py.in +++ b/Mailman/Defaults.py.in @@ -562,6 +562,22 @@ SMTPPORT = 0 # default from smtplib # when DELIVERY_MODULE is 'Sendmail'. SENDMAIL_CMD = '/usr/lib/sendmail' +# SMTP authentication for DELIVERY_MODULE = 'SMTPDirect'. To enable SASL +# authentication for SMTPDirect, set SMTP_AUTH = Yes and provide appropriate +# settings for SMTP_USER and SMTP_PASSWD. +SMTP_AUTH = No +SMTP_USER = '' +SMTP_PASSWD = '' + +# If using SASL authentication (SMTP_AUTH = Yes), set the following to Yes +# to also use TLS. This has no effect if SMTP_AUTH = No. +SMTP_USE_TLS = No + +# When using TLS the following should be set to the hostname that should be +# used in order to identify Mailman to the SMTP server. By default, it +# uses DEFAULT_URL_HOST. Normally, you should not change this. +SMTP_HELO_HOST = DEFAULT_URL_HOST + # Set these variables if you need to authenticate to your NNTP server for # Usenet posting or reading. If no authentication is necessary, specify None # for both variables. diff --git a/Mailman/Handlers/SMTPDirect.py b/Mailman/Handlers/SMTPDirect.py index 32b03423..3b489c2f 100644 --- a/Mailman/Handlers/SMTPDirect.py +++ b/Mailman/Handlers/SMTPDirect.py @@ -63,6 +63,36 @@ class Connection: self.__conn = smtplib.SMTP() self.__conn.set_debuglevel(mm_cfg.SMTPLIB_DEBUG_LEVEL) self.__conn.connect(mm_cfg.SMTPHOST, mm_cfg.SMTPPORT) + if mm_cfg.SMTP_AUTH: + if mm_cfg.SMTP_USE_TLS: + try: + self.__conn.starttls() + except SMTPException, e: + syslog('smtp-failure', 'SMTP TLS error: %s', e) + self.quit() + raise + try: + self.__conn.ehlo(mm_cfg.SMTP_HELO_HOST) + except SMTPException, e: + syslog('smtp-failure', 'SMTP EHLO error: %s', e) + self.quit() + raise + try: + self.__conn.login(mm_cfg.SMTP_USER, mm_cfg.SMTP_PASSWD) + except smtplib.SMTPHeloError, e: + syslog('smtp-failure', 'SMTP HELO error: %s', e) + self.quit() + raise + except smtplib.SMTPAuthenticationError, e: + syslog('smtp-failure', 'SMTP AUTH error: %s', e) + self.quit() + raise + except smtplib.SMTPException, e: + syslog('smtp-failure', + 'SMTP - no suitable authentication method found: %s', e) + self.quit() + raise + self.__numsessions = mm_cfg.SMTP_MAX_SESSIONS_PER_CONNECTION def sendmail(self, envsender, recips, msgtext): -- cgit v1.2.3