Ticket #17471: ssl_setting_patch.txt

File ssl_setting_patch.txt, 6.8 KB (added by dje, 12 years ago)

ssl_setting_patch.txt

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
Back to Top