diff options
| author | Claude Paroz <claude@2xlibre.net> | 2016-08-29 14:37:03 +0200 |
|---|---|---|
| committer | Claude Paroz <claude@2xlibre.net> | 2016-08-31 09:00:41 +0200 |
| commit | fe252c0a5a2ceb5c97aafc16a42dbe5ad03ef1e9 (patch) | |
| tree | aee82f2003ac0b6889303595a2cce47054704dc6 /tests/mail | |
| parent | 190d2ff4a7a392adfe0b12552bd71871791d87aa (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.py | 49 |
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() |
