1 | Index: 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::
|
---|
26 | Index: 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
|
---|
53 | Index: 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
|
---|
118 | Index: 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 = ()
|
---|
130 | Index: 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
|
---|