Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #12202 -- Removed hardcoded password reset subject and added a …

…subject_template_name parameter to the password_reset view. Thanks, Ramiro Morales, Claude Paroz and agabel.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16438 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 656360c24044e06c881baa648f2aad9d671c3bd8 1 parent 63f9b67
Jannis Leidel authored June 19, 2011
1  MANIFEST.in
@@ -17,6 +17,7 @@ recursive-include django/contrib/admin/templates *
17 17
 recursive-include django/contrib/admin/media *
18 18
 recursive-include django/contrib/admindocs/templates *
19 19
 recursive-include django/contrib/auth/fixtures *
  20
+recursive-include django/contrib/auth/templates *
20 21
 recursive-include django/contrib/auth/tests/templates *
21 22
 recursive-include django/contrib/comments/templates *
22 23
 recursive-include django/contrib/databrowse/templates *
2  django/contrib/auth/fixtures/authtestdata.json
@@ -31,7 +31,7 @@
31 31
             "groups": [], 
32 32
             "user_permissions": [], 
33 33
             "password": "sha1$6efc0$f93efe9fd7542f25a7be94871ea45aa95de57161", 
34  
-            "email": "testclient@example.com", 
  34
+            "email": "testclient2@example.com",
35 35
             "date_joined": "2006-12-17 07:03:31"
36 36
         }
37 37
     },
15  django/contrib/auth/forms.py
@@ -120,8 +120,11 @@ def clean_email(self):
120 120
             raise forms.ValidationError(_("That e-mail address doesn't have an associated user account. Are you sure you've registered?"))
121 121
         return email
122 122
 
123  
-    def save(self, domain_override=None, email_template_name='registration/password_reset_email.html',
124  
-             use_https=False, token_generator=default_token_generator, from_email=None, request=None):
  123
+    def save(self, domain_override=None,
  124
+             subject_template_name='registration/password_reset_subject.txt',
  125
+             email_template_name='registration/password_reset_email.html',
  126
+             use_https=False, token_generator=default_token_generator,
  127
+             from_email=None, request=None):
125 128
         """
126 129
         Generates a one-use only link for resetting password and sends to the user
127 130
         """
@@ -133,7 +136,6 @@ def save(self, domain_override=None, email_template_name='registration/password_
133 136
                 domain = current_site.domain
134 137
             else:
135 138
                 site_name = domain = domain_override
136  
-            t = loader.get_template(email_template_name)
137 139
             c = {
138 140
                 'email': user.email,
139 141
                 'domain': domain,
@@ -143,8 +145,11 @@ def save(self, domain_override=None, email_template_name='registration/password_
143 145
                 'token': token_generator.make_token(user),
144 146
                 'protocol': use_https and 'https' or 'http',
145 147
             }
146  
-            send_mail(_("Password reset on %s") % site_name,
147  
-                t.render(Context(c)), from_email, [user.email])
  148
+            subject = loader.render_to_string(subject_template_name, c)
  149
+            # Email subject *must not* contain newlines
  150
+            subject = ''.join(subject.splitlines())
  151
+            email = loader.render_to_string(email_template_name, c)
  152
+            send_mail(subject, email, from_email, [user.email])
148 153
 
149 154
 class SetPasswordForm(forms.Form):
150 155
     """
98  django/contrib/auth/locale/en/LC_MESSAGES/django.po
@@ -4,7 +4,7 @@ msgid ""
4 4
 msgstr ""
5 5
 "Project-Id-Version: Django\n"
6 6
 "Report-Msgid-Bugs-To: \n"
7  
-"POT-Creation-Date: 2011-03-15 13:14-0400\n"
  7
+"POT-Creation-Date: 2011-06-19 13:08+0200\n"
8 8
 "PO-Revision-Date: 2010-05-13 15:35+0200\n"
9 9
 "Last-Translator: Django team\n"
10 10
 "Language-Team: English <en@li.org>\n"
@@ -12,27 +12,27 @@ msgstr ""
12 12
 "Content-Type: text/plain; charset=UTF-8\n"
13 13
 "Content-Transfer-Encoding: 8bit\n"
14 14
 
15  
-#: admin.py:28
  15
+#: admin.py:29
16 16
 msgid "Personal info"
17 17
 msgstr ""
18 18
 
19  
-#: admin.py:29
  19
+#: admin.py:30
20 20
 msgid "Permissions"
21 21
 msgstr ""
22 22
 
23  
-#: admin.py:30
  23
+#: admin.py:31
24 24
 msgid "Important dates"
25 25
 msgstr ""
26 26
 
27  
-#: admin.py:31
  27
+#: admin.py:32
28 28
 msgid "Groups"
29 29
 msgstr ""
30 30
 
31  
-#: admin.py:113
  31
+#: admin.py:116
32 32
 msgid "Password changed successfully."
33 33
 msgstr ""
34 34
 
35  
-#: admin.py:123
  35
+#: admin.py:126
36 36
 #, python-format
37 37
 msgid "Change password: %s"
38 38
 msgstr ""
@@ -49,7 +49,7 @@ msgstr ""
49 49
 msgid "This value may contain only letters, numbers and @/./+/-/_ characters."
50 50
 msgstr ""
51 51
 
52  
-#: forms.py:17 forms.py:67 forms.py:193
  52
+#: forms.py:17 forms.py:67 forms.py:201
53 53
 msgid "Password"
54 54
 msgstr ""
55 55
 
@@ -65,7 +65,7 @@ msgstr ""
65 65
 msgid "A user with that username already exists."
66 66
 msgstr ""
67 67
 
68  
-#: forms.py:37 forms.py:163 forms.py:205
  68
+#: forms.py:37 forms.py:171 forms.py:213
69 69
 msgid "The two password fields didn't match."
70 70
 msgstr ""
71 71
 
@@ -89,154 +89,150 @@ msgstr ""
89 89
 msgid "E-mail"
90 90
 msgstr ""
91 91
 
92  
-#: forms.py:117
  92
+#: forms.py:120
93 93
 msgid ""
94 94
 "That e-mail address doesn't have an associated user account. Are you sure "
95 95
 "you've registered?"
96 96
 msgstr ""
97 97
 
98  
-#: forms.py:143
99  
-#, python-format
100  
-msgid "Password reset on %s"
101  
-msgstr ""
102  
-
103  
-#: forms.py:151
  98
+#: forms.py:159
104 99
 msgid "New password"
105 100
 msgstr ""
106 101
 
107  
-#: forms.py:152
  102
+#: forms.py:160
108 103
 msgid "New password confirmation"
109 104
 msgstr ""
110 105
 
111  
-#: forms.py:177
  106
+#: forms.py:185
112 107
 msgid "Old password"
113 108
 msgstr ""
114 109
 
115  
-#: forms.py:185
  110
+#: forms.py:193
116 111
 msgid "Your old password was entered incorrectly. Please enter it again."
117 112
 msgstr ""
118 113
 
119  
-#: forms.py:194
  114
+#: forms.py:202
120 115
 msgid "Password (again)"
121 116
 msgstr ""
122 117
 
123  
-#: models.py:76 models.py:104
  118
+#: models.py:77 models.py:105
124 119
 msgid "name"
125 120
 msgstr ""
126 121
 
127  
-#: models.py:78
  122
+#: models.py:79
128 123
 msgid "codename"
129 124
 msgstr ""
130 125
 
131  
-#: models.py:82
  126
+#: models.py:83
132 127
 msgid "permission"
133 128
 msgstr ""
134 129
 
135  
-#: models.py:83 models.py:105
  130
+#: models.py:84 models.py:106
136 131
 msgid "permissions"
137 132
 msgstr ""
138 133
 
139  
-#: models.py:108
  134
+#: models.py:109
140 135
 msgid "group"
141 136
 msgstr ""
142 137
 
143  
-#: models.py:109 models.py:216
  138
+#: models.py:110 models.py:217
144 139
 msgid "groups"
145 140
 msgstr ""
146 141
 
147  
-#: models.py:206
  142
+#: models.py:207
148 143
 msgid "username"
149 144
 msgstr ""
150 145
 
151  
-#: models.py:206
  146
+#: models.py:207
152 147
 msgid ""
153 148
 "Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"
154 149
 msgstr ""
155 150
 
156  
-#: models.py:207
  151
+#: models.py:208
157 152
 msgid "first name"
158 153
 msgstr ""
159 154
 
160  
-#: models.py:208
  155
+#: models.py:209
161 156
 msgid "last name"
162 157
 msgstr ""
163 158
 
164  
-#: models.py:209
  159
+#: models.py:210
165 160
 msgid "e-mail address"
166 161
 msgstr ""
167 162
 
168  
-#: models.py:210
  163
+#: models.py:211
169 164
 msgid "password"
170 165
 msgstr ""
171 166
 
172  
-#: models.py:210
  167
+#: models.py:211
173 168
 msgid ""
174 169
 "Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change "
175 170
 "password form</a>."
176 171
 msgstr ""
177 172
 
178  
-#: models.py:211
  173
+#: models.py:212
179 174
 msgid "staff status"
180 175
 msgstr ""
181 176
 
182  
-#: models.py:211
  177
+#: models.py:212
183 178
 msgid "Designates whether the user can log into this admin site."
184 179
 msgstr ""
185 180
 
186  
-#: models.py:212
  181
+#: models.py:213
187 182
 msgid "active"
188 183
 msgstr ""
189 184
 
190  
-#: models.py:212
  185
+#: models.py:213
191 186
 msgid ""
192 187
 "Designates whether this user should be treated as active. Unselect this "
193 188
 "instead of deleting accounts."
194 189
 msgstr ""
195 190
 
196  
-#: models.py:213
  191
+#: models.py:214
197 192
 msgid "superuser status"
198 193
 msgstr ""
199 194
 
200  
-#: models.py:213
  195
+#: models.py:214
201 196
 msgid ""
202 197
 "Designates that this user has all permissions without explicitly assigning "
203 198
 "them."
204 199
 msgstr ""
205 200
 
206  
-#: models.py:214
  201
+#: models.py:215
207 202
 msgid "last login"
208 203
 msgstr ""
209 204
 
210  
-#: models.py:215
  205
+#: models.py:216
211 206
 msgid "date joined"
212 207
 msgstr ""
213 208
 
214  
-#: models.py:217
  209
+#: models.py:218
215 210
 msgid ""
216 211
 "In addition to the permissions manually assigned, this user will also get "
217 212
 "all permissions granted to each group he/she is in."
218 213
 msgstr ""
219 214
 
220  
-#: models.py:218
  215
+#: models.py:219
221 216
 msgid "user permissions"
222 217
 msgstr ""
223 218
 
224  
-#: models.py:222
  219
+#: models.py:223
225 220
 msgid "user"
226 221
 msgstr ""
227 222
 
228  
-#: models.py:223
  223
+#: models.py:224
229 224
 msgid "users"
230 225
 msgstr ""
231 226
 
232  
-#: models.py:406
233  
-msgid "message"
234  
-msgstr ""
235  
-
236  
-#: views.py:91
  227
+#: views.py:93
237 228
 msgid "Logged out"
238 229
 msgstr ""
239 230
 
240  
-#: management/commands/createsuperuser.py:23
  231
+#: management/commands/createsuperuser.py:24
241 232
 msgid "Enter a valid e-mail address."
242 233
 msgstr ""
  234
+
  235
+#: templates/registration/password_reset_subject.txt:2
  236
+#, python-format
  237
+msgid "Password reset on %(site_name)s"
  238
+msgstr ""
3  django/contrib/auth/templates/registration/password_reset_subject.txt
... ...
@@ -0,0 +1,3 @@
  1
+{% load i18n %}{% autoescape off %}
  2
+{% blocktrans %}Password reset on {{ site_name }}{% endblocktrans %}
  3
+{% endautoescape %}
13  django/contrib/auth/tests/forms.py
... ...
@@ -1,3 +1,7 @@
  1
+from __future__ import with_statement
  2
+import os
  3
+from django.conf import settings
  4
+from django.core import mail
1 5
 from django.contrib.auth.models import User
2 6
 from django.contrib.auth.forms import UserCreationForm, AuthenticationForm,  PasswordChangeForm, SetPasswordForm, UserChangeForm, PasswordResetForm
3 7
 from django.test import TestCase
@@ -251,6 +255,15 @@ def test_cleaned_data(self):
251 255
         self.assertTrue(form.is_valid())
252 256
         self.assertEqual(form.cleaned_data['email'], email)
253 257
 
  258
+    def test_custom_email_subject(self):
  259
+        template_path = os.path.join(os.path.dirname(__file__), 'templates')
  260
+        with self.settings(TEMPLATE_DIRS=(template_path,)):
  261
+            data = {'email': 'testclient@example.com'}
  262
+            form = PasswordResetForm(data)
  263
+            self.assertTrue(form.is_valid())
  264
+            form.save()
  265
+            self.assertEqual(len(mail.outbox), 1)
  266
+            self.assertEqual(mail.outbox[0].subject, u'Custom password reset on example.com')
254 267
 
255 268
     def test_bug_5605(self):
256 269
         # bug #5605, preserve the case of the user name (before the @ in the
1  django/contrib/auth/tests/templates/registration/password_reset_subject.txt
... ...
@@ -0,0 +1 @@
  1
+{% autoescape off %}Custom password reset on {{ site_name }}{% endautoescape %}
2  django/contrib/auth/views.py
@@ -135,6 +135,7 @@ def redirect_to_login(next, login_url=None,
135 135
 def password_reset(request, is_admin_site=False,
136 136
                    template_name='registration/password_reset_form.html',
137 137
                    email_template_name='registration/password_reset_email.html',
  138
+                   subject_template_name='registration/password_reset_subject.txt',
138 139
                    password_reset_form=PasswordResetForm,
139 140
                    token_generator=default_token_generator,
140 141
                    post_reset_redirect=None,
@@ -151,6 +152,7 @@ def password_reset(request, is_admin_site=False,
151 152
                 'token_generator': token_generator,
152 153
                 'from_email': from_email,
153 154
                 'email_template_name': email_template_name,
  155
+                'subject_template_name': subject_template_name,
154 156
                 'request': request,
155 157
             }
156 158
             if is_admin_site:
6  docs/topics/auth.txt
@@ -964,6 +964,12 @@ includes a few other useful built-in views located in
964 964
           generating the email with the new password. This will default to
965 965
           :file:`registration/password_reset_email.html` if not supplied.
966 966
 
  967
+        * ``subject_template_name``: The full name of a template to use for
  968
+          the subject of the email with the new password. This will default
  969
+          to :file:`registration/password_reset_subject.txt` if not supplied.
  970
+
  971
+          .. versionadded:: 1.4
  972
+
967 973
         * ``password_reset_form``: Form that will be used to set the password.
968 974
           Defaults to :class:`~django.contrib.auth.forms.PasswordResetForm`.
969 975
 

0 notes on commit 656360c

Please sign in to comment.
Something went wrong with that request. Please try again.