Code

Ticket #17471: ssl_setting_patch.diff

File ssl_setting_patch.diff, 6.8 KB (added by anonymous, 2 years ago)

same as the same-named attachment with .txt extension, only with .diff as extension to allow for easy trac viewing

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