summaryrefslogtreecommitdiff
path: root/tests/mail
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2016-08-29 14:37:03 +0200
committerClaude Paroz <claude@2xlibre.net>2016-08-31 09:00:41 +0200
commitfe252c0a5a2ceb5c97aafc16a42dbe5ad03ef1e9 (patch)
treeaee82f2003ac0b6889303595a2cce47054704dc6 /tests/mail
parent190d2ff4a7a392adfe0b12552bd71871791d87aa (diff)
Fixed #27131 -- Passed proper string type to SMTP connection login
Passing an Unicode string on Python 2 was crashing the connection. Thanks slavugan@gmail.com for the report, and Tim Graham for the review.
Diffstat (limited to 'tests/mail')
-rw-r--r--tests/mail/tests.py49
1 files changed, 47 insertions, 2 deletions
diff --git a/tests/mail/tests.py b/tests/mail/tests.py
index 3d1a74518f..93e2127d63 100644
--- a/tests/mail/tests.py
+++ b/tests/mail/tests.py
@@ -2,6 +2,7 @@
from __future__ import unicode_literals
import asyncore
+import base64
import mimetypes
import os
import shutil
@@ -11,7 +12,7 @@ import tempfile
import threading
from email.header import Header
from email.mime.text import MIMEText
-from smtplib import SMTP, SMTPException
+from smtplib import SMTP, SMTPAuthenticationError, SMTPException
from ssl import SSLError
from django.core import mail
@@ -1115,12 +1116,21 @@ class FakeSMTPChannel(smtpd.SMTPChannel):
def collect_incoming_data(self, data):
try:
- super(FakeSMTPChannel, self).collect_incoming_data(data)
+ smtpd.SMTPChannel.collect_incoming_data(self, data)
except UnicodeDecodeError:
# ignore decode error in SSL/TLS connection tests as we only care
# whether the connection attempt was made
pass
+ def smtp_AUTH(self, arg):
+ if arg == 'CRAM-MD5':
+ # This is only the first part of the login process. But it's enough
+ # for our tests.
+ challenge = base64.b64encode(b'somerandomstring13579')
+ self.push(str('334 %s' % challenge.decode()))
+ else:
+ self.push(str('502 Error: login "%s" not implemented' % arg))
+
class FakeSMTPServer(smtpd.SMTPServer, threading.Thread):
"""
@@ -1140,6 +1150,15 @@ class FakeSMTPServer(smtpd.SMTPServer, threading.Thread):
self.active_lock = threading.Lock()
self.sink_lock = threading.Lock()
+ if not PY3:
+ def handle_accept(self):
+ # copy of Python 2.7 smtpd.SMTPServer.handle_accept with hardcoded
+ # SMTPChannel replaced by self.channel_class
+ pair = self.accept()
+ if pair is not None:
+ conn, addr = pair
+ self.channel_class(self, conn, addr)
+
def process_message(self, peer, mailfrom, rcpttos, data):
if PY3:
data = data.encode('utf-8')
@@ -1187,6 +1206,20 @@ class FakeSMTPServer(smtpd.SMTPServer, threading.Thread):
self.join()
+class FakeAUTHSMTPConnection(SMTP):
+ """
+ A SMTP connection pretending support for the AUTH command. It does not, but
+ at least this can allow testing the first part of the AUTH process.
+ """
+
+ def ehlo(self, name=''):
+ response = SMTP.ehlo(self, name=name)
+ self.esmtp_features.update({
+ 'auth': 'CRAM-MD5 PLAIN LOGIN',
+ })
+ return response
+
+
class SMTPBackendTestsBase(SimpleTestCase):
@classmethod
@@ -1270,6 +1303,18 @@ class SMTPBackendTests(BaseEmailBackendTests, SMTPBackendTestsBase):
backend.close()
self.assertTrue(opened)
+ def test_server_login(self):
+ """
+ Even if the Python SMTP server doesn't support authentication, the
+ login process starts and the appropriate exception is raised.
+ """
+ class CustomEmailBackend(smtp.EmailBackend):
+ connection_class = FakeAUTHSMTPConnection
+
+ backend = CustomEmailBackend(username='username', password='password')
+ with self.assertRaises(SMTPAuthenticationError):
+ backend.open()
+
@override_settings(EMAIL_USE_TLS=True)
def test_email_tls_use_settings(self):
backend = smtp.EmailBackend()