Ticket #17471: patch_ticket_17471_b.txt

File patch_ticket_17471_b.txt, 7.1 KB (added by Areski Belaid, 11 years ago)
Line 
1diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py
2index 53aef35..9e25009 100644
3--- a/django/conf/global_settings.py
4+++ b/django/conf/global_settings.py
5@@ -184,6 +184,7 @@ EMAIL_PORT = 25
6 EMAIL_HOST_USER = ''
7 EMAIL_HOST_PASSWORD = ''
8 EMAIL_USE_TLS = False
9+EMAIL_USE_SSL = False
10
11 # List of strings representing installed apps.
12 INSTALLED_APPS = ()
13diff --git a/django/core/mail/backends/smtp.py b/django/core/mail/backends/smtp.py
14index e456b78..fc77080 100644
15--- a/django/core/mail/backends/smtp.py
16+++ b/django/core/mail/backends/smtp.py
17@@ -15,7 +15,7 @@ class EmailBackend(BaseEmailBackend):
18 A wrapper that manages the SMTP network connection.
19 """
20 def __init__(self, host=None, port=None, username=None, password=None,
21- use_tls=None, fail_silently=False, **kwargs):
22+ use_tls=None, fail_silently=False, use_ssl=None, **kwargs):
23 super(EmailBackend, self).__init__(fail_silently=fail_silently)
24 self.host = host or settings.EMAIL_HOST
25 self.port = port or settings.EMAIL_PORT
26@@ -31,6 +31,13 @@ class EmailBackend(BaseEmailBackend):
27 self.use_tls = settings.EMAIL_USE_TLS
28 else:
29 self.use_tls = use_tls
30+ if use_ssl is None:
31+ self.use_ssl = settings.EMAIL_USE_SSL
32+ else:
33+ self.use_ssl = use_ssl
34+ if self.use_ssl and self.use_tls:
35+ raise ValueError(
36+ "EMAIL_USE_TLS/EMAIL_USE_SSL are mutually exclusive, so only set one of those settings to True.")
37 self.connection = None
38 self._lock = threading.RLock()
39
40@@ -45,12 +52,18 @@ class EmailBackend(BaseEmailBackend):
41 try:
42 # If local_hostname is not specified, socket.getfqdn() gets used.
43 # For performance, we use the cached FQDN for local_hostname.
44- self.connection = smtplib.SMTP(self.host, self.port,
45+ if self.use_ssl:
46+ self.connection = smtplib.SMTP_SSL(self.host, self.port,
47+ local_hostname=DNS_NAME.get_fqdn())
48+ else:
49+ self.connection = smtplib.SMTP(self.host, self.port,
50 local_hostname=DNS_NAME.get_fqdn())
51- if self.use_tls:
52- self.connection.ehlo()
53- self.connection.starttls()
54- self.connection.ehlo()
55+ # TLS/SSL are mutually exclusive, so only attempt TLS over
56+ # non-secure connections.
57+ if self.use_tls:
58+ self.connection.ehlo()
59+ self.connection.starttls()
60+ self.connection.ehlo()
61 if self.username and self.password:
62 self.connection.login(self.username, self.password)
63 return True
64diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt
65index eb470cd..427ac99 100644
66--- a/docs/ref/settings.txt
67+++ b/docs/ref/settings.txt
68@@ -1047,6 +1047,26 @@ EMAIL_USE_TLS
69 Default: ``False``
70
71 Whether to use a TLS (secure) connection when talking to the SMTP server.
72+This is used for explicit TLS connections, generally on port 587. If you are
73+experiencing hanging connections, see the implicit TLS setting
74+:setting:`EMAIL_USE_SSL`.
75+
76+.. setting:: EMAIL_USE_SSL
77+
78+EMAIL_USE_SSL
79+-------------
80+
81+.. versionadded:: 1.6
82+
83+Default: ``False``
84+
85+Whether to use an implicit TLS (secure) connection when talking to the SMTP
86+server. In most email documentation this type of TLS connection is referred
87+to as SSL. It is generally used on port 465. If you are experiencing problems,
88+see the explicit TLS setting :setting:`EMAIL_USE_TLS`.
89+
90+Note that :setting:`EMAIL_USE_TLS`/:setting:`EMAIL_USE_SSL` are mutually
91+exclusive, so only set one of those settings to ``True``.
92
93 .. setting:: FILE_CHARSET
94
95diff --git a/docs/topics/email.txt b/docs/topics/email.txt
96index b3d7254..8bf501c 100644
97--- a/docs/topics/email.txt
98+++ b/docs/topics/email.txt
99@@ -27,7 +27,8 @@ Mail is sent using the SMTP host and port specified in the
100 :setting:`EMAIL_HOST` and :setting:`EMAIL_PORT` settings. The
101 :setting:`EMAIL_HOST_USER` and :setting:`EMAIL_HOST_PASSWORD` settings, if
102 set, are used to authenticate to the SMTP server, and the
103-:setting:`EMAIL_USE_TLS` setting controls whether a secure connection is used.
104+:setting:`EMAIL_USE_TLS` and :setting:`EMAIL_USE_SSL` settings control whether
105+a secure connection is used.
106
107 .. note::
108
109@@ -408,8 +409,8 @@ SMTP backend
110 This is the default backend. Email will be sent through a SMTP server.
111 The server address and authentication credentials are set in the
112 :setting:`EMAIL_HOST`, :setting:`EMAIL_PORT`, :setting:`EMAIL_HOST_USER`,
113-:setting:`EMAIL_HOST_PASSWORD` and :setting:`EMAIL_USE_TLS` settings in your
114-settings file.
115+:setting:`EMAIL_HOST_PASSWORD`, :setting:`EMAIL_USE_TLS` and
116+:setting:`EMAIL_USE_SSL` settings in your settings file.
117
118 The SMTP backend is the default configuration inherited by Django. If you
119 want to specify it explicitly, put the following in your settings::
120diff --git a/tests/mail/tests.py b/tests/mail/tests.py
121index 0a843db..8079181 100644
122--- a/tests/mail/tests.py
123+++ b/tests/mail/tests.py
124@@ -9,6 +9,8 @@ import smtpd
125 import sys
126 import tempfile
127 import threading
128+from smtplib import SMTPException
129+from ssl import SSLError
130
131 from django.core import mail
132 from django.core.mail import (EmailMessage, mail_admins, mail_managers,
133@@ -738,3 +740,44 @@ class SMTPBackendTests(BaseEmailBackendTests, TestCase):
134 backend.close()
135 except Exception as e:
136 self.fail("close() unexpectedly raised an exception: %s" % e)
137+
138+ @override_settings(EMAIL_USE_TLS=True)
139+ def test_email_tls_use_settings(self):
140+ backend = smtp.EmailBackend()
141+ self.assertTrue(backend.use_tls)
142+
143+ @override_settings(EMAIL_USE_TLS=True)
144+ def test_email_tls_override_settings(self):
145+ backend = smtp.EmailBackend(use_tls=False)
146+ self.assertFalse(backend.use_tls)
147+
148+ def test_email_tls_default_disabled(self):
149+ backend = smtp.EmailBackend()
150+ self.assertFalse(backend.use_tls)
151+
152+ @override_settings(EMAIL_USE_SSL=True)
153+ def test_email_ssl_use_settings(self):
154+ backend = smtp.EmailBackend()
155+ self.assertTrue(backend.use_ssl)
156+
157+ @override_settings(EMAIL_USE_SSL=True)
158+ def test_email_ssl_override_settings(self):
159+ backend = smtp.EmailBackend(use_ssl=False)
160+ self.assertFalse(backend.use_ssl)
161+
162+ def test_email_ssl_default_disabled(self):
163+ backend = smtp.EmailBackend()
164+ self.assertFalse(backend.use_ssl)
165+
166+ @override_settings(EMAIL_USE_TLS=True)
167+ def test_email_tls_attempts_starttls(self):
168+ backend = smtp.EmailBackend()
169+ self.assertTrue(backend.use_tls)
170+ self.assertRaisesMessage(SMTPException,
171+ 'STARTTLS extension not supported by server.', backend.open)
172+
173+ @override_settings(EMAIL_USE_SSL=True)
174+ def test_email_ssl_attempts_ssl_connection(self):
175+ backend = smtp.EmailBackend()
176+ self.assertTrue(backend.use_ssl)
177+ self.assertRaises(SSLError, backend.open)
Back to Top