summaryrefslogtreecommitdiff
path: root/src/mailman/runners
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/runners')
-rw-r--r--src/mailman/runners/docs/lmtp.rst2
-rw-r--r--src/mailman/runners/lmtp.py17
2 files changed, 14 insertions, 5 deletions
diff --git a/src/mailman/runners/docs/lmtp.rst b/src/mailman/runners/docs/lmtp.rst
index 6a21295b9..8243b62de 100644
--- a/src/mailman/runners/docs/lmtp.rst
+++ b/src/mailman/runners/docs/lmtp.rst
@@ -20,7 +20,7 @@ Let's start a testable LMTP runner.
It also helps to have a nice LMTP client.
>>> lmtp = helpers.get_lmtp_client()
- (220, b'... Python LMTP runner 1.0')
+ (220, b'... GNU Mailman LMTP runner 1.1')
>>> lmtp.lhlo('remote.example.org')
(250, ...)
diff --git a/src/mailman/runners/lmtp.py b/src/mailman/runners/lmtp.py
index 39f92f228..8a490d906 100644
--- a/src/mailman/runners/lmtp.py
+++ b/src/mailman/runners/lmtp.py
@@ -39,8 +39,8 @@ __all__ = [
]
+import sys
import email
-import smtpd
import logging
import asyncore
@@ -54,6 +54,14 @@ from mailman.utilities.datetime import now
from mailman.utilities.email import add_message_hash
from zope.component import getUtility
+# Python 3.4's smtpd module can't handle non-UTF-8 byte input. Unfortunately
+# we do get such emails in the wild. Python 3.5's version of the module does
+# handle it correctly. We vendor a version to use in the Python 3.4 case.
+if sys.version_info < (3, 5):
+ from mailman.compat import smtpd
+else:
+ import smtpd
+
elog = logging.getLogger('mailman.error')
qlog = logging.getLogger('mailman.runner')
@@ -95,7 +103,7 @@ ERR_550 = '550 Requested action not taken: mailbox unavailable'
ERR_550_MID = '550 No Message-ID header provided'
# XXX Blech
-smtpd.__version__ = 'Python LMTP runner 1.0'
+smtpd.__version__ = 'GNU Mailman LMTP runner 1.1'
@@ -131,13 +139,13 @@ class Channel(smtpd.SMTPChannel):
"""An LMTP channel."""
def __init__(self, server, conn, addr):
- smtpd.SMTPChannel.__init__(self, server, conn, addr)
+ super().__init__(server, conn, addr)
# Stash this here since the subclass uses private attributes. :(
self._server = server
def smtp_LHLO(self, arg):
"""The LMTP greeting, used instead of HELO/EHLO."""
- smtpd.SMTPChannel.smtp_HELO(self, arg)
+ super().smtp_HELO(arg)
def smtp_HELO(self, arg):
"""HELO is not a valid LMTP command."""
@@ -148,6 +156,7 @@ class Channel(smtpd.SMTPChannel):
## return super().push(arg)
+
class LMTPRunner(Runner, smtpd.SMTPServer):
# Only __init__ is called on startup. Asyncore is responsible for later