| 2 | | |
| 3 | | r""" |
| 4 | | # Tests for the django.core.mail. |
| 5 | | |
| 6 | | >>> import os |
| 7 | | >>> import shutil |
| 8 | | >>> import tempfile |
| 9 | | >>> from StringIO import StringIO |
| 10 | | >>> from django.conf import settings |
| 11 | | >>> from django.core import mail |
| 12 | | >>> from django.core.mail import EmailMessage, mail_admins, mail_managers, EmailMultiAlternatives |
| 13 | | >>> from django.core.mail import send_mail, send_mass_mail |
| 14 | | >>> from django.core.mail.backends.base import BaseEmailBackend |
| 15 | | >>> from django.core.mail.backends import console, dummy, locmem, filebased, smtp |
| 16 | | >>> from django.utils.translation import ugettext_lazy |
| 17 | | |
| 18 | | # Test normal ascii character case: |
| 19 | | |
| 20 | | >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com']) |
| 21 | | >>> message = email.message() |
| 22 | | >>> message['Subject'].encode() |
| 23 | | 'Subject' |
| 24 | | >>> message.get_payload() |
| 25 | | 'Content' |
| 26 | | >>> message['From'] |
| 27 | | 'from@example.com' |
| 28 | | >>> message['To'] |
| 29 | | 'to@example.com' |
| 30 | | |
| 31 | | # Test multiple-recipient case |
| 32 | | |
| 33 | | >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com','other@example.com']) |
| 34 | | >>> message = email.message() |
| 35 | | >>> message['Subject'].encode() |
| 36 | | 'Subject' |
| 37 | | >>> message.get_payload() |
| 38 | | 'Content' |
| 39 | | >>> message['From'] |
| 40 | | 'from@example.com' |
| 41 | | >>> message['To'] |
| 42 | | 'to@example.com, other@example.com' |
| 43 | | |
| 44 | | # Test for header injection |
| 45 | | |
| 46 | | >>> email = EmailMessage('Subject\nInjection Test', 'Content', 'from@example.com', ['to@example.com']) |
| 47 | | >>> message = email.message() |
| 48 | | Traceback (most recent call last): |
| 49 | | ... |
| 50 | | BadHeaderError: Header values can't contain newlines (got u'Subject\nInjection Test' for header 'Subject') |
| 51 | | |
| 52 | | >>> email = EmailMessage(ugettext_lazy('Subject\nInjection Test'), 'Content', 'from@example.com', ['to@example.com']) |
| 53 | | >>> message = email.message() |
| 54 | | Traceback (most recent call last): |
| 55 | | ... |
| 56 | | BadHeaderError: Header values can't contain newlines (got u'Subject\nInjection Test' for header 'Subject') |
| 57 | | |
| 58 | | # Test for space continuation character in long (ascii) subject headers (#7747) |
| 59 | | |
| 60 | | >>> email = EmailMessage('Long subject lines that get wrapped should use a space continuation character to get expected behaviour in Outlook and Thunderbird', 'Content', 'from@example.com', ['to@example.com']) |
| 61 | | >>> message = email.message() |
| 62 | | >>> message.as_string() |
| 63 | | 'Content-Type: text/plain; charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\nSubject: Long subject lines that get wrapped should use a space continuation\n character to get expected behaviour in Outlook and Thunderbird\nFrom: from@example.com\nTo: to@example.com\nDate: ...\nMessage-ID: <...>\n\nContent' |
| 64 | | |
| 65 | | # Specifying dates or message-ids in the extra headers overrides the defaul |
| 66 | | # values (#9233). |
| 67 | | |
| 68 | | >>> headers = {"date": "Fri, 09 Nov 2001 01:08:47 -0000", "Message-ID": "foo"} |
| 69 | | >>> email = EmailMessage('subject', 'content', 'from@example.com', ['to@example.com'], headers=headers) |
| 70 | | >>> email.message().as_string() |
| 71 | | 'Content-Type: text/plain; charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\nSubject: subject\nFrom: from@example.com\nTo: to@example.com\ndate: Fri, 09 Nov 2001 01:08:47 -0000\nMessage-ID: foo\n\ncontent' |
| 72 | | |
| 73 | | # Test that mail_admins/mail_managers doesn't connect to the mail server if there are no recipients (#9383) |
| 74 | | |
| 75 | | >>> old_admins = settings.ADMINS |
| 76 | | >>> old_managers = settings.MANAGERS |
| 77 | | >>> settings.ADMINS = [] |
| 78 | | >>> settings.MANAGERS = [] |
| 79 | | >>> mail.outbox = [] |
| 80 | | >>> mail_admins('hi','there') |
| 81 | | >>> len(mail.outbox) |
| 82 | | 0 |
| 83 | | >>> mail.outbox = [] |
| 84 | | >>> mail_managers('hi','there') |
| 85 | | >>> len(mail.outbox) |
| 86 | | 0 |
| 87 | | >>> settings.ADMINS = settings.MANAGERS = [('nobody','nobody@example.com')] |
| 88 | | >>> mail.outbox = [] |
| 89 | | >>> mail_admins('hi','there') |
| 90 | | >>> len(mail.outbox) |
| 91 | | 1 |
| 92 | | >>> mail.outbox = [] |
| 93 | | >>> mail_managers('hi','there') |
| 94 | | >>> len(mail.outbox) |
| 95 | | 1 |
| 96 | | |
| 97 | | # Make sure we can manually set the From header (#9214) |
| 98 | | |
| 99 | | >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) |
| 100 | | >>> message = email.message() |
| 101 | | >>> message['From'] |
| 102 | | 'from@example.com' |
| 103 | | |
| 104 | | # Regression for #13259 - Make sure that headers are not changed |
| 105 | | # when calling EmailMessage.message() |
| 106 | | >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) |
| 107 | | >>> message = email.message() |
| 108 | | >>> message['From'] |
| 109 | | 'from@example.com' |
| 110 | | >>> message = email.message() |
| 111 | | >>> message['From'] |
| 112 | | 'from@example.com' |
| 113 | | |
| 114 | | # Regression for #11144 - When a to/from/cc header contains unicode, |
| 115 | | # make sure the email addresses are parsed correctly (especially |
| 116 | | # with regards to commas) |
| 117 | | >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['"Firstname Sürname" <to@example.com>','other@example.com']) |
| 118 | | >>> email.message()['To'] |
| 119 | | '=?utf-8?q?Firstname_S=C3=BCrname?= <to@example.com>, other@example.com' |
| 120 | | |
| 121 | | >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['"Sürname, Firstname" <to@example.com>','other@example.com']) |
| 122 | | >>> email.message()['To'] |
| 123 | | '=?utf-8?q?S=C3=BCrname=2C_Firstname?= <to@example.com>, other@example.com' |
| 124 | | |
| 125 | | # Regression for #6918 - When a header contains unicode, |
| 126 | | # make sure headers can be set with a different encoding than utf-8 |
| 127 | | >>> email = EmailMessage('Message from Firstname Sürname', 'Content', 'from@example.com', ['"Sürname, Firstname" <to@example.com>','other@example.com']) |
| 128 | | >>> email.encoding = 'iso-8859-1' |
| 129 | | >>> email.message()['To'] |
| 130 | | '=?iso-8859-1?q?S=FCrname=2C_Firstname?= <to@example.com>, other@example.com' |
| 131 | | >>> email.message()['Subject'].encode() |
| 132 | | u'=?iso-8859-1?q?Message_from_Firstname_S=FCrname?=' |
| 133 | | |
| 134 | | # Make sure headers can be set with a different encoding than utf-8 in SafeMIMEMultipart as well |
| 135 | | >>> headers = {"Date": "Fri, 09 Nov 2001 01:08:47 -0000", "Message-ID": "foo"} |
| 136 | | >>> subject, from_email, to = 'hello', 'from@example.com', '"Sürname, Firstname" <to@example.com>' |
| 137 | | >>> text_content = 'This is an important message.' |
| 138 | | >>> html_content = '<p>This is an <strong>important</strong> message.</p>' |
| 139 | | >>> msg = EmailMultiAlternatives('Message from Firstname Sürname', text_content, from_email, [to], headers=headers) |
| 140 | | >>> msg.attach_alternative(html_content, "text/html") |
| 141 | | >>> msg.encoding = 'iso-8859-1' |
| 142 | | >>> msg.message()['To'] |
| 143 | | '=?iso-8859-1?q?S=FCrname=2C_Firstname?= <to@example.com>' |
| 144 | | >>> msg.message()['Subject'].encode() |
| 145 | | u'=?iso-8859-1?q?Message_from_Firstname_S=FCrname?=' |
| 146 | | |
| 147 | | # Regression for #12791 - Encode body correctly with other encodings than utf-8 |
| 148 | | >>> email = EmailMessage('Subject', 'Firstname Sürname is a great guy.', 'from@example.com', ['other@example.com']) |
| 149 | | >>> email.encoding = 'iso-8859-1' |
| 150 | | >>> message = email.message() |
| 151 | | >>> message.as_string() |
| 152 | | 'Content-Type: text/plain; charset="iso-8859-1"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\nSubject: Subject\nFrom: from@example.com\nTo: other@example.com\nDate: ...\nMessage-ID: <...>\n\nFirstname S=FCrname is a great guy.' |
| 153 | | |
| 154 | | # Make sure MIME attachments also works correctly with other encodings than utf-8 |
| 155 | | >>> text_content = 'Firstname Sürname is a great guy.' |
| 156 | | >>> html_content = '<p>Firstname Sürname is a <strong>great</strong> guy.</p>' |
| 157 | | >>> msg = EmailMultiAlternatives('Subject', text_content, 'from@example.com', ['to@example.com']) |
| 158 | | >>> msg.encoding = 'iso-8859-1' |
| 159 | | >>> msg.attach_alternative(html_content, "text/html") |
| 160 | | >>> msg.message().get_payload(0).as_string() |
| 161 | | 'Content-Type: text/plain; charset="iso-8859-1"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\n\nFirstname S=FCrname is a great guy.' |
| 162 | | >>> msg.message().get_payload(1).as_string() |
| 163 | | 'Content-Type: text/html; charset="iso-8859-1"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\n\n<p>Firstname S=FCrname is a <strong>great</strong> guy.</p>' |
| 164 | | |
| 165 | | # Handle attachments within an multipart/alternative mail correctly (#9367) |
| 166 | | # (test is not as precise/clear as it could be w.r.t. email tree structure, |
| 167 | | # but it's good enough.) |
| 168 | | >>> headers = {"Date": "Fri, 09 Nov 2001 01:08:47 -0000", "Message-ID": "foo"} |
| 169 | | >>> subject, from_email, to = 'hello', 'from@example.com', 'to@example.com' |
| 170 | | >>> text_content = 'This is an important message.' |
| 171 | | >>> html_content = '<p>This is an <strong>important</strong> message.</p>' |
| 172 | | >>> msg = EmailMultiAlternatives(subject, text_content, from_email, [to], headers=headers) |
| 173 | | >>> msg.attach_alternative(html_content, "text/html") |
| 174 | | >>> msg.attach("an attachment.pdf", "%PDF-1.4.%...", mimetype="application/pdf") |
| 175 | | >>> print msg.message().as_string() |
| 176 | | Content-Type: multipart/mixed; boundary="..." |
| 177 | | MIME-Version: 1.0 |
| 178 | | Subject: hello |
| 179 | | From: from@example.com |
| 180 | | To: to@example.com |
| 181 | | Date: Fri, 09 Nov 2001 01:08:47 -0000 |
| 182 | | Message-ID: foo |
| 183 | | ... |
| 184 | | Content-Type: multipart/alternative;... |
| 185 | | ... |
| 186 | | Content-Type: text/plain; charset="utf-8" |
| 187 | | MIME-Version: 1.0 |
| 188 | | Content-Transfer-Encoding: quoted-printable |
| 189 | | ... |
| 190 | | This is an important message. |
| 191 | | ... |
| 192 | | Content-Type: text/html; charset="utf-8" |
| 193 | | MIME-Version: 1.0 |
| 194 | | Content-Transfer-Encoding: quoted-printable |
| 195 | | ... |
| 196 | | <p>This is an <strong>important</strong> message.</p> |
| 197 | | ... |
| 198 | | ... |
| 199 | | Content-Type: application/pdf |
| 200 | | MIME-Version: 1.0 |
| 201 | | Content-Transfer-Encoding: base64 |
| 202 | | Content-Disposition: attachment; filename="an attachment.pdf" |
| 203 | | ... |
| 204 | | JVBERi0xLjQuJS4uLg== |
| 205 | | ... |
| 206 | | |
| 207 | | # Make sure that the console backend writes to stdout by default |
| 208 | | >>> connection = console.EmailBackend() |
| 209 | | >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) |
| 210 | | >>> connection.send_messages([email]) |
| 211 | | Content-Type: text/plain; charset="utf-8" |
| 212 | | MIME-Version: 1.0 |
| 213 | | Content-Transfer-Encoding: quoted-printable |
| 214 | | Subject: Subject |
| 215 | | From: from@example.com |
| 216 | | To: to@example.com |
| 217 | | Date: ... |
| 218 | | Message-ID: ... |
| 219 | | |
| 220 | | Content |
| 221 | | ------------------------------------------------------------------------------- |
| 222 | | 1 |
| 223 | | |
| 224 | | # Test that the console backend can be pointed at an arbitrary stream |
| 225 | | >>> s = StringIO() |
| 226 | | >>> connection = mail.get_connection('django.core.mail.backends.console.EmailBackend', stream=s) |
| 227 | | >>> send_mail('Subject', 'Content', 'from@example.com', ['to@example.com'], connection=connection) |
| 228 | | 1 |
| 229 | | >>> print s.getvalue() |
| 230 | | Content-Type: text/plain; charset="utf-8" |
| 231 | | MIME-Version: 1.0 |
| 232 | | Content-Transfer-Encoding: quoted-printable |
| 233 | | Subject: Subject |
| 234 | | From: from@example.com |
| 235 | | To: to@example.com |
| 236 | | Date: ... |
| 237 | | Message-ID: ... |
| 238 | | |
| 239 | | Content |
| 240 | | ------------------------------------------------------------------------------- |
| 241 | | |
| 242 | | # Make sure that dummy backends returns correct number of sent messages |
| 243 | | >>> connection = dummy.EmailBackend() |
| 244 | | >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) |
| 245 | | >>> connection.send_messages([email, email, email]) |
| 246 | | 3 |
| 247 | | |
| 248 | | # Make sure that locmen backend populates the outbox |
| 249 | | >>> mail.outbox = [] |
| 250 | | >>> connection = locmem.EmailBackend() |
| 251 | | >>> email1 = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) |
| 252 | | >>> email2 = EmailMessage('Subject 2', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) |
| 253 | | >>> connection.send_messages([email1, email2]) |
| 254 | | 2 |
| 255 | | >>> len(mail.outbox) |
| 256 | | 2 |
| 257 | | >>> mail.outbox[0].subject |
| 258 | | 'Subject' |
| 259 | | >>> mail.outbox[1].subject |
| 260 | | 'Subject 2' |
| 261 | | |
| 262 | | # Make sure that multiple locmem connections share mail.outbox |
| 263 | | >>> mail.outbox = [] |
| 264 | | >>> connection1 = locmem.EmailBackend() |
| 265 | | >>> connection2 = locmem.EmailBackend() |
| 266 | | >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) |
| 267 | | >>> connection1.send_messages([email]) |
| 268 | | 1 |
| 269 | | >>> connection2.send_messages([email]) |
| 270 | | 1 |
| 271 | | >>> len(mail.outbox) |
| 272 | | 2 |
| 273 | | |
| 274 | | # Make sure that the file backend write to the right location |
| 275 | | >>> tmp_dir = tempfile.mkdtemp() |
| 276 | | >>> connection = filebased.EmailBackend(file_path=tmp_dir) |
| 277 | | >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) |
| 278 | | >>> connection.send_messages([email]) |
| 279 | | 1 |
| 280 | | >>> len(os.listdir(tmp_dir)) |
| 281 | | 1 |
| 282 | | >>> print open(os.path.join(tmp_dir, os.listdir(tmp_dir)[0])).read() |
| 283 | | Content-Type: text/plain; charset="utf-8" |
| 284 | | MIME-Version: 1.0 |
| 285 | | Content-Transfer-Encoding: quoted-printable |
| 286 | | Subject: Subject |
| 287 | | From: from@example.com |
| 288 | | To: to@example.com |
| 289 | | Date: ... |
| 290 | | Message-ID: ... |
| 291 | | |
| 292 | | Content |
| 293 | | ------------------------------------------------------------------------------- |
| 294 | | |
| 295 | | >>> connection2 = filebased.EmailBackend(file_path=tmp_dir) |
| 296 | | >>> connection2.send_messages([email]) |
| 297 | | 1 |
| 298 | | >>> len(os.listdir(tmp_dir)) |
| 299 | | 2 |
| 300 | | >>> connection.send_messages([email]) |
| 301 | | 1 |
| 302 | | >>> len(os.listdir(tmp_dir)) |
| 303 | | 2 |
| 304 | | >>> email.connection = filebased.EmailBackend(file_path=tmp_dir) |
| 305 | | >>> connection_created = connection.open() |
| 306 | | >>> num_sent = email.send() |
| 307 | | >>> len(os.listdir(tmp_dir)) |
| 308 | | 3 |
| 309 | | >>> num_sent = email.send() |
| 310 | | >>> len(os.listdir(tmp_dir)) |
| 311 | | 3 |
| 312 | | >>> connection.close() |
| 313 | | >>> shutil.rmtree(tmp_dir) |
| 314 | | |
| 315 | | # Make sure that get_connection() accepts arbitrary keyword that might be |
| 316 | | # used with custom backends. |
| 317 | | >>> c = mail.get_connection(fail_silently=True, foo='bar') |
| 318 | | >>> c.fail_silently |
| 319 | | True |
| 320 | | |
| 321 | | # Test custom backend defined in this suite. |
| 322 | | >>> conn = mail.get_connection('regressiontests.mail.custombackend.EmailBackend') |
| 323 | | >>> hasattr(conn, 'test_outbox') |
| 324 | | True |
| 325 | | >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) |
| 326 | | >>> conn.send_messages([email]) |
| 327 | | 1 |
| 328 | | >>> len(conn.test_outbox) |
| 329 | | 1 |
| 330 | | |
| 331 | | # Test backend argument of mail.get_connection() |
| 332 | | >>> isinstance(mail.get_connection('django.core.mail.backends.smtp.EmailBackend'), smtp.EmailBackend) |
| 333 | | True |
| 334 | | >>> isinstance(mail.get_connection('django.core.mail.backends.locmem.EmailBackend'), locmem.EmailBackend) |
| 335 | | True |
| 336 | | >>> isinstance(mail.get_connection('django.core.mail.backends.dummy.EmailBackend'), dummy.EmailBackend) |
| 337 | | True |
| 338 | | >>> isinstance(mail.get_connection('django.core.mail.backends.console.EmailBackend'), console.EmailBackend) |
| 339 | | True |
| 340 | | >>> tmp_dir = tempfile.mkdtemp() |
| 341 | | >>> isinstance(mail.get_connection('django.core.mail.backends.filebased.EmailBackend', file_path=tmp_dir), filebased.EmailBackend) |
| 342 | | True |
| 343 | | >>> shutil.rmtree(tmp_dir) |
| 344 | | >>> isinstance(mail.get_connection(), locmem.EmailBackend) |
| 345 | | True |
| 346 | | |
| 347 | | # Test connection argument of send_mail() et al |
| 348 | | >>> connection = mail.get_connection('django.core.mail.backends.console.EmailBackend') |
| 349 | | >>> send_mail('Subject', 'Content', 'from@example.com', ['to@example.com'], connection=connection) |
| 350 | | Content-Type: text/plain; charset="utf-8" |
| 351 | | MIME-Version: 1.0 |
| 352 | | Content-Transfer-Encoding: quoted-printable |
| 353 | | Subject: Subject |
| 354 | | From: from@example.com |
| 355 | | To: to@example.com |
| 356 | | Date: ... |
| 357 | | Message-ID: ... |
| 358 | | |
| 359 | | Content |
| 360 | | ------------------------------------------------------------------------------- |
| 361 | | 1 |
| 362 | | |
| 363 | | >>> send_mass_mail([ |
| 364 | | ... ('Subject1', 'Content1', 'from1@example.com', ['to1@example.com']), |
| 365 | | ... ('Subject2', 'Content2', 'from2@example.com', ['to2@example.com']) |
| 366 | | ... ], connection=connection) |
| 367 | | Content-Type: text/plain; charset="utf-8" |
| 368 | | MIME-Version: 1.0 |
| 369 | | Content-Transfer-Encoding: quoted-printable |
| 370 | | Subject: Subject1 |
| 371 | | From: from1@example.com |
| 372 | | To: to1@example.com |
| 373 | | Date: ... |
| 374 | | Message-ID: ... |
| 375 | | |
| 376 | | Content1 |
| 377 | | ------------------------------------------------------------------------------- |
| 378 | | Content-Type: text/plain; charset="utf-8" |
| 379 | | MIME-Version: 1.0 |
| 380 | | Content-Transfer-Encoding: quoted-printable |
| 381 | | Subject: Subject2 |
| 382 | | From: from2@example.com |
| 383 | | To: to2@example.com |
| 384 | | Date: ... |
| 385 | | Message-ID: ... |
| 386 | | |
| 387 | | Content2 |
| 388 | | ------------------------------------------------------------------------------- |
| 389 | | 2 |
| 390 | | |
| 391 | | >>> mail_admins('Subject', 'Content', connection=connection) |
| 392 | | Content-Type: text/plain; charset="utf-8" |
| 393 | | MIME-Version: 1.0 |
| 394 | | Content-Transfer-Encoding: quoted-printable |
| 395 | | Subject: [Django] Subject |
| 396 | | From: root@localhost |
| 397 | | To: nobody@example.com |
| 398 | | Date: ... |
| 399 | | Message-ID: ... |
| 400 | | |
| 401 | | Content |
| 402 | | ------------------------------------------------------------------------------- |
| 403 | | |
| 404 | | >>> mail_managers('Subject', 'Content', connection=connection) |
| 405 | | Content-Type: text/plain; charset="utf-8" |
| 406 | | MIME-Version: 1.0 |
| 407 | | Content-Transfer-Encoding: quoted-printable |
| 408 | | Subject: [Django] Subject |
| 409 | | From: root@localhost |
| 410 | | To: nobody@example.com |
| 411 | | Date: ... |
| 412 | | Message-ID: ... |
| 413 | | |
| 414 | | Content |
| 415 | | ------------------------------------------------------------------------------- |
| 416 | | |
| 417 | | >>> settings.ADMINS = old_admins |
| 418 | | >>> settings.MANAGERS = old_managers |
| 419 | | |
| 420 | | # Add Cc to the email argument list (#7722) |
| 421 | | |
| 422 | | >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com'], cc=['cc@example.com']) |
| 423 | | >>> message = email.message() |
| 424 | | >>> message['Cc'] |
| 425 | | 'cc@example.com' |
| 426 | | >>> email.recipients() |
| 427 | | ['to@example.com', 'cc@example.com'] |
| 428 | | |
| 429 | | >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com','other@example.com'], cc=['cc@example.com', 'cc.other@example.com']) |
| 430 | | >>> message = email.message() |
| 431 | | >>> message['Cc'] |
| 432 | | 'cc@example.com, cc.other@example.com' |
| 433 | | >>> email.recipients() |
| 434 | | ['to@example.com', 'other@example.com', 'cc@example.com', 'cc.other@example.com'] |
| 435 | | |
| 436 | | >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com','other@example.com'], cc=['cc@example.com', 'cc.other@example.com'], bcc=['bcc@example.com']) |
| 437 | | >>> message = email.message() |
| 438 | | >>> email.recipients() |
| 439 | | ['to@example.com', 'other@example.com', 'cc@example.com', 'cc.other@example.com', 'bcc@example.com'] |
| 440 | | |
| 441 | | >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com'], cc=['cc@example.com']) |
| 442 | | >>> message = email.message() |
| 443 | | >>> message.as_string() |
| 444 | | 'Content-Type: text/plain; charset="utf-8"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\nSubject: Subject\nFrom: from@example.com\nTo: to@example.com\nCc: cc@example.com\nDate: ...\nMessage-ID: <...>\n\nContent' |
| 445 | | |
| 446 | | """ |
| | 2 | """Tests for the django.core.mail.""" |
| | 3 | |
| | 4 | import os |
| | 5 | import shutil |
| | 6 | import tempfile |
| | 7 | import unittest |
| | 8 | from email import message_from_file, message_from_string |
| | 9 | from StringIO import StringIO |
| | 10 | |
| | 11 | from django.conf import settings |
| | 12 | from django.core import mail |
| | 13 | from django.core.mail import BadHeaderError |
| | 14 | from django.core.mail import EmailMessage, EmailMultiAlternatives |
| | 15 | from django.core.mail import mail_admins, mail_managers |
| | 16 | from django.core.mail import send_mail, send_mass_mail |
| | 17 | from django.core.mail.backends import console, dummy, filebased, locmem, smtp |
| | 18 | from django.utils.translation import ugettext_lazy |
| | 19 | |
| | 20 | |
| | 21 | class MailTests(unittest.TestCase): |
| | 22 | |
| | 23 | def test_ascii_characters(self): |
| | 24 | email = EmailMessage('Subject', 'Content', 'from@example.com', |
| | 25 | ['to@example.com']) |
| | 26 | message = email.message() |
| | 27 | self.assertEqual(message['Subject'].encode(), 'Subject') |
| | 28 | self.assertEqual(message.get_payload(), 'Content') |
| | 29 | self.assertEqual(message['From'], 'from@example.com') |
| | 30 | self.assertEqual(message['To'], 'to@example.com') |
| | 31 | |
| | 32 | def test_multiple_recipients(self): |
| | 33 | email = EmailMessage('Subject', 'Content', 'from@example.com', |
| | 34 | ['to@example.com','other@example.com']) |
| | 35 | message = email.message() |
| | 36 | self.assertEqual(message['Subject'].encode(), 'Subject') |
| | 37 | self.assertEqual(message.get_payload(), 'Content') |
| | 38 | self.assertEqual(message['From'], 'from@example.com') |
| | 39 | self.assertEqual(message['To'], 'to@example.com, other@example.com') |
| | 40 | |
| | 41 | def test_header_injection(self): |
| | 42 | email = EmailMessage('Subject\nInjection Test', 'Content', |
| | 43 | 'from@example.com', ['to@example.com']) |
| | 44 | self.assertRaises(BadHeaderError, email.message) |
| | 45 | # again with lazy translation |
| | 46 | email = EmailMessage(ugettext_lazy('Subject\nInjection Test'), |
| | 47 | 'Content', 'from@example.com', |
| | 48 | ['to@example.com']) |
| | 49 | self.assertRaises(BadHeaderError, email.message) |
| | 50 | |
| | 51 | def test_continuation_char_in_long_header(self): |
| | 52 | # Regression test for #7747 |
| | 53 | email = EmailMessage( |
| | 54 | ('Long subject lines that get wrapped should use a space ' |
| | 55 | 'continuation character to get expected behaviour in Outlook ' |
| | 56 | 'and Thunderbird'), 'Content', |
| | 57 | 'from@example.com', ['to@example.com']) |
| | 58 | message = email.message() |
| | 59 | self.assertEqual(str(message['Subject']), |
| | 60 | ('Long subject lines that get wrapped should use a space continuation\n' |
| | 61 | ' character to get expected behaviour in Outlook and Thunderbird')) |
| | 62 | |
| | 63 | def test_custom_message_id(self): |
| | 64 | # Regression test for #9233 |
| | 65 | date_str = 'Fri, 09 Nov 2001 01:08:47 -0000' |
| | 66 | headers = {'date': date_str, 'Message-ID': 'foo'} |
| | 67 | email = EmailMessage('subject', 'content', 'from@example.com', |
| | 68 | ['to@example.com'], headers=headers) |
| | 69 | message = email.message() |
| | 70 | self.assertEqual(str(message['Message-ID']), 'foo') |
| | 71 | self.assertEqual(str(message['date']), date_str) |
| | 72 | |
| | 73 | def test_ignore_empty_managers(self): |
| | 74 | # Test that mail_admins/mail_managers doesn't connect to the |
| | 75 | # mail server if there are no recipients (#9383). |
| | 76 | old_admins = settings.ADMINS |
| | 77 | old_managers = settings.MANAGERS |
| | 78 | settings.ADMINS = [] |
| | 79 | settings.MANAGERS = [] |
| | 80 | mail.outbox = [] |
| | 81 | try: |
| | 82 | mail_admins('hi','there') |
| | 83 | self.assertEqual(len(mail.outbox), 0) |
| | 84 | mail_managers('hi','there') |
| | 85 | self.assertEqual(len(mail.outbox), 0) |
| | 86 | settings.ADMINS = settings.MANAGERS = [ |
| | 87 | ('nobody','nobody@example.com')] |
| | 88 | mail_admins('hi','there') |
| | 89 | self.assertEqual(len(mail.outbox), 1) |
| | 90 | mail.outbox = [] |
| | 91 | mail_managers('hi','there') |
| | 92 | self.assertEqual(len(mail.outbox), 1) |
| | 93 | finally: |
| | 94 | settings.ADMINS = old_admins |
| | 95 | settings.MANAGER = old_managers |
| | 96 | |
| | 97 | def test_set_from_header_manually(self): |
| | 98 | # Regression test for #9214 |
| | 99 | email = EmailMessage('Subject', 'Content', 'bounce@example.com', |
| | 100 | ['to@example.com'], |
| | 101 | headers={'From': 'from@example.com'}) |
| | 102 | message = email.message() |
| | 103 | self.assertEqual(message['From'], 'from@example.com') |
| | 104 | |
| | 105 | def test_headers_dont_change(self): |
| | 106 | # Regression for #13259 - Make sure that headers are not |
| | 107 | # changed when calling EmailMessage.message() |
| | 108 | email = EmailMessage('Subject', 'Content', 'bounce@example.com', |
| | 109 | ['to@example.com'], |
| | 110 | headers={'From': 'from@example.com'}) |
| | 111 | message = email.message() |
| | 112 | self.assertEqual(message['From'], 'from@example.com') |
| | 113 | message = email.message() |
| | 114 | self.assertEqual(message['From'], 'from@example.com') |
| | 115 | |
| | 116 | def test_parse_unicode_addresses(self): |
| | 117 | # Regression for #11144 - When a to/from/cc header contains |
| | 118 | # unicode, make sure the email addresses are parsed correctly |
| | 119 | # (especially with regards to commas) |
| | 120 | email = EmailMessage('Subject', 'Content', 'from@example.com', |
| | 121 | ['"Firstname Sürname" <to@example.com>', |
| | 122 | 'other@example.com']) |
| | 123 | self.assertEqual(email.message()['To'], |
| | 124 | ('=?utf-8?q?Firstname_S=C3=BCrname?= ' |
| | 125 | '<to@example.com>, other@example.com')) |
| | 126 | |
| | 127 | email = EmailMessage('Subject', 'Content', 'from@example.com', |
| | 128 | ['"Sürname, Firstname" <to@example.com>', |
| | 129 | 'other@example.com']) |
| | 130 | self.assertEqual(email.message()['To'], |
| | 131 | ('=?utf-8?q?S=C3=BCrname=2C_Firstname?= ' |
| | 132 | '<to@example.com>, other@example.com')) |
| | 133 | |
| | 134 | def test_header_encoding(self): |
| | 135 | # Regression for #6918 - When a header contains unicode, |
| | 136 | # make sure headers can be set with a different encoding than utf-8 |
| | 137 | email = EmailMessage('Message from Firstname Sürname', 'Content', |
| | 138 | 'from@example.com', |
| | 139 | ['"Sürname, Firstname" <to@example.com>', |
| | 140 | 'other@example.com']) |
| | 141 | email.encoding = 'iso-8859-1' |
| | 142 | self.assertEqual(email.message()['To'], |
| | 143 | '=?iso-8859-1?q?S=FCrname=2C_Firstname?= <to@example.com>, other@example.com') |
| | 144 | self.assertEqual(email.message()['Subject'].encode(), |
| | 145 | u'=?iso-8859-1?q?Message_from_Firstname_S=FCrname?=') |
| | 146 | |
| | 147 | def test_header_encoding_multipart(self): |
| | 148 | # Make sure headers can be set with a different encoding than |
| | 149 | # utf-8 in SafeMIMEMultipart as well |
| | 150 | headers = {"Date": "Fri, 09 Nov 2001 01:08:47 -0000", |
| | 151 | "Message-ID": "foo"} |
| | 152 | subject, from_email, to = 'hello', 'from@example.com', '"Sürname, Firstname" <to@example.com>' |
| | 153 | text_content = 'This is an important message.' |
| | 154 | html_content = '<p>This is an <strong>important</strong> message.</p>' |
| | 155 | msg = EmailMultiAlternatives('Message from Firstname Sürname', |
| | 156 | text_content, from_email, [to], |
| | 157 | headers=headers) |
| | 158 | msg.attach_alternative(html_content, "text/html") |
| | 159 | msg.encoding = 'iso-8859-1' |
| | 160 | self.assertEqual(msg.message()['To'], |
| | 161 | '=?iso-8859-1?q?S=FCrname=2C_Firstname?= <to@example.com>') |
| | 162 | self.assertEqual(msg.message()['Subject'].encode(), |
| | 163 | u'=?iso-8859-1?q?Message_from_Firstname_S=FCrname?=') |
| | 164 | |
| | 165 | def test_body_encoding(self): |
| | 166 | # Regression for #12791 - Encode body correctly with other |
| | 167 | # encodings than utf-8 |
| | 168 | email = EmailMessage('Subject', 'Firstname Sürname is a great guy.', |
| | 169 | 'from@example.com', ['other@example.com']) |
| | 170 | email.encoding = 'iso-8859-1' |
| | 171 | message = email.message() |
| | 172 | self.assertEqual(str(message['Content-Type']), |
| | 173 | 'text/plain; charset="iso-8859-1"') |
| | 174 | self.assertEqual(message.get_payload(), |
| | 175 | 'Firstname S=FCrname is a great guy.') |
| | 176 | |
| | 177 | def test_attachment_encoding(self): |
| | 178 | # Make sure MIME attachments also works correctly with other |
| | 179 | # encodings than utf-8 |
| | 180 | text_content = 'Firstname Sürname is a great guy.' |
| | 181 | html_content = '<p>Firstname Sürname is a <strong>great</strong> guy.</p>' |
| | 182 | email = EmailMultiAlternatives('Subject', text_content, |
| | 183 | 'from@example.com', ['to@example.com']) |
| | 184 | email.encoding = 'iso-8859-1' |
| | 185 | email.attach_alternative(html_content, 'text/html') |
| | 186 | message = email.message() |
| | 187 | payload0 = message.get_payload(0) |
| | 188 | payload1 = message.get_payload(1) |
| | 189 | self.assertEqual(payload0['Content-Type'], |
| | 190 | 'text/plain; charset="iso-8859-1"') |
| | 191 | self.assertEqual(payload0.get_payload(), |
| | 192 | 'Firstname S=FCrname is a great guy.') |
| | 193 | self.assertEqual(payload1['Content-Type'], |
| | 194 | 'text/html; charset="iso-8859-1"') |
| | 195 | self.assertEqual(payload1.get_payload(), |
| | 196 | '<p>Firstname S=FCrname is a <strong>great</strong> guy.</p>') |
| | 197 | |
| | 198 | def test_handle_attachments(self): |
| | 199 | # Handle attachments within an multipart/alternative mail |
| | 200 | # correctly (#9367) (test is not as precise/clear as it could |
| | 201 | # be w.r.t. email tree structure, but it's good enough.) |
| | 202 | headers = {"Date": "Fri, 09 Nov 2001 01:08:47 -0000", |
| | 203 | "Message-ID": "foo"} |
| | 204 | subject, from_email, to = 'hello', 'from@example.com', 'to@example.com' |
| | 205 | text_content = 'This is an important message.' |
| | 206 | html_content = '<p>This is an <strong>important</strong> message.</p>' |
| | 207 | email = EmailMultiAlternatives(subject, text_content, from_email, |
| | 208 | [to], headers=headers) |
| | 209 | email.attach_alternative(html_content, "text/html") |
| | 210 | email.attach("an attachment.pdf", "%PDF-1.4.%...", |
| | 211 | mimetype="application/pdf") |
| | 212 | message = email.message() |
| | 213 | payload0 = message.get_payload(0) |
| | 214 | payload1 = message.get_payload(1) |
| | 215 | self.assert_(payload0['Content-Type'].startswith('multipart/alternative')) |
| | 216 | self.assertEqual(payload0.get_payload(0)['Content-Type'], |
| | 217 | 'text/plain; charset="utf-8"') |
| | 218 | self.assertEqual(payload0.get_payload(1)['Content-Type'], |
| | 219 | 'text/html; charset="utf-8"') |
| | 220 | self.assertEqual(payload0.get_payload(0)['Content-Transfer-Encoding'], |
| | 221 | 'quoted-printable') |
| | 222 | self.assertEqual(payload0.get_payload(1)['Content-Transfer-Encoding'], |
| | 223 | 'quoted-printable') |
| | 224 | self.assertEqual(payload0.get_payload(0).get_payload(), |
| | 225 | 'This is an important message.') |
| | 226 | self.assertEqual(payload0.get_payload(1).get_payload(), |
| | 227 | '<p>This is an <strong>important</strong> message.</p>') |
| | 228 | self.assertEqual(payload1['Content-Type'], 'application/pdf') |
| | 229 | self.assertEqual(payload1['Content-Disposition'], |
| | 230 | 'attachment; filename="an attachment.pdf"') |
| | 231 | self.assertEqual(payload1['Content-Transfer-Encoding'], 'base64') |
| | 232 | |
| | 233 | def test_console_backend(self): |
| | 234 | # Make sure that the console backend write to arbitrary streams. |
| | 235 | stream = StringIO() |
| | 236 | connection = console.EmailBackend(stream=stream) |
| | 237 | email = EmailMessage('Subject', 'Content', 'bounce@example.com', |
| | 238 | ['to@example.com'], |
| | 239 | headers={'From': 'from@example.com'}) |
| | 240 | self.assertEqual(connection.send_messages([email]), 1) |
| | 241 | lines = stream.getvalue().splitlines() |
| | 242 | self.assert_('MIME-Version: 1.0' in lines) |
| | 243 | self.assert_('Subject: Subject' in lines) |
| | 244 | self.assert_('From: from@example.com' in lines) |
| | 245 | self.assert_('To: to@example.com' in lines) |
| | 246 | |
| | 247 | def test_dummy_backend(self): |
| | 248 | # Make sure that dummy backends returns correct number of sent |
| | 249 | # messages |
| | 250 | connection = dummy.EmailBackend() |
| | 251 | email = EmailMessage('Subject', 'Content', 'bounce@example.com', |
| | 252 | ['to@example.com'], |
| | 253 | headers={'From': 'from@example.com'}) |
| | 254 | self.assertEqual(connection.send_messages([email, email, email]), 3) |
| | 255 | |
| | 256 | def test_locmem_backend(self): |
| | 257 | # Make sure that locmen backend populates the outbox |
| | 258 | mail.outbox = [] |
| | 259 | connection = locmem.EmailBackend() |
| | 260 | email1 = EmailMessage('Subject', 'Content', 'bounce@example.com', |
| | 261 | ['to@example.com'], |
| | 262 | headers={'From': 'from@example.com'}) |
| | 263 | email2 = EmailMessage('Subject 2', 'Content', 'bounce@example.com', |
| | 264 | ['to@example.com'], |
| | 265 | headers={'From': 'from@example.com'}) |
| | 266 | self.assertEqual(connection.send_messages([email1, email2]), 2) |
| | 267 | self.assertEqual(len(mail.outbox), 2) |
| | 268 | self.assertEqual(mail.outbox[0].subject, 'Subject') |
| | 269 | self.assertEqual(mail.outbox[1].subject, 'Subject 2') |
| | 270 | |
| | 271 | def test_locmem_backend_multiple(self): |
| | 272 | # Make sure that multiple locmem connections share mail.outbox |
| | 273 | mail.outbox = [] |
| | 274 | connection1 = locmem.EmailBackend() |
| | 275 | connection2 = locmem.EmailBackend() |
| | 276 | email = EmailMessage('Subject', 'Content', 'bounce@example.com', |
| | 277 | ['to@example.com'], |
| | 278 | headers={'From': 'from@example.com'}) |
| | 279 | self.assertEqual(connection1.send_messages([email]), 1) |
| | 280 | self.assertEqual(connection2.send_messages([email]), 1) |
| | 281 | self.assertEqual(len(mail.outbox), 2) |
| | 282 | |
| | 283 | def test_file_backend(self): |
| | 284 | # Make sure that the file backend write to the right location |
| | 285 | tmp_dir = tempfile.mkdtemp() |
| | 286 | connection = filebased.EmailBackend(file_path=tmp_dir) |
| | 287 | email = EmailMessage('Subject', 'Content', 'bounce@example.com', |
| | 288 | ['to@example.com'], |
| | 289 | headers={'From': 'from@example.com'}) |
| | 290 | self.assertEqual(connection.send_messages([email]), 1) |
| | 291 | self.assertEqual(len(os.listdir(tmp_dir)), 1) |
| | 292 | fp = open(os.path.join(tmp_dir, os.listdir(tmp_dir)[0])) |
| | 293 | message = message_from_file(fp) |
| | 294 | fp.close() |
| | 295 | self.assertEqual(message['Content-Type'], |
| | 296 | 'text/plain; charset="utf-8"') |
| | 297 | self.assertEqual(message['Subject'], 'Subject') |
| | 298 | self.assertEqual(message['From'], 'from@example.com') |
| | 299 | self.assertEqual(message['To'], 'to@example.com') |
| | 300 | |
| | 301 | connection2 = filebased.EmailBackend(file_path=tmp_dir) |
| | 302 | self.assertEqual(connection2.send_messages([email]), 1) |
| | 303 | self.assertEqual(len(os.listdir(tmp_dir)), 2) |
| | 304 | self.assertEqual(connection.send_messages([email]), 1) |
| | 305 | self.assertEqual(len(os.listdir(tmp_dir)), 2) |
| | 306 | |
| | 307 | email.connection = filebased.EmailBackend(file_path=tmp_dir) |
| | 308 | connection.open() |
| | 309 | email.send() |
| | 310 | self.assertEqual(len(os.listdir(tmp_dir)), 3) |
| | 311 | email.send() |
| | 312 | self.assertEqual(len(os.listdir(tmp_dir)), 3) |
| | 313 | connection.close() |
| | 314 | shutil.rmtree(tmp_dir) |
| | 315 | |
| | 316 | def test_get_connection(self): |
| | 317 | # Make sure that get_connection() accepts arbitrary keyword |
| | 318 | # that might be used with custom backends. |
| | 319 | c = mail.get_connection(fail_silently=True, foo='bar') |
| | 320 | self.assertEqual(c.fail_silently, True) |
| | 321 | |
| | 322 | def test_custom_backend(self): |
| | 323 | # Test custom backend defined in this suite. |
| | 324 | conn = mail.get_connection( |
| | 325 | 'regressiontests.mail.custombackend.EmailBackend') |
| | 326 | self.assert_(hasattr(conn, 'test_outbox')) |
| | 327 | email = EmailMessage('Subject', 'Content', 'bounce@example.com', |
| | 328 | ['to@example.com'], |
| | 329 | headers={'From': 'from@example.com'}) |
| | 330 | self.assertEqual(conn.send_messages([email]), 1) |
| | 331 | self.assertEqual(len(conn.test_outbox), 1) |
| | 332 | |
| | 333 | def test_builtin_backends(self): |
| | 334 | # Test backend argument of mail.get_connection() |
| | 335 | path = 'django.core.mail.backends.%s.EmailBackend' |
| | 336 | self.assert_(isinstance(mail.get_connection(path % 'smtp'), |
| | 337 | smtp.EmailBackend)) |
| | 338 | self.assert_(isinstance(mail.get_connection(path % 'locmem'), |
| | 339 | locmem.EmailBackend)) |
| | 340 | self.assert_(isinstance(mail.get_connection(path % 'dummy'), |
| | 341 | dummy.EmailBackend)) |
| | 342 | self.assert_(isinstance(mail.get_connection(path % 'console'), |
| | 343 | console.EmailBackend)) |
| | 344 | tmp_dir = tempfile.mkdtemp() |
| | 345 | self.assert_(isinstance(mail.get_connection(path % 'filebased', |
| | 346 | file_path=tmp_dir), |
| | 347 | filebased.EmailBackend)) |
| | 348 | shutil.rmtree(tmp_dir) |
| | 349 | # the default (for tests) |
| | 350 | self.assert_(isinstance(mail.get_connection(), locmem.EmailBackend)) |
| | 351 | |
| | 352 | def test_connection_argument(self): |
| | 353 | # Test connection argument of send_mail() et al |
| | 354 | stream = StringIO() |
| | 355 | connection = mail.get_connection( |
| | 356 | 'django.core.mail.backends.console.EmailBackend', stream=stream) |
| | 357 | self.assertEqual(send_mail('Subject', 'Content', 'from@example.com', |
| | 358 | ['to@example.com'], connection=connection), |
| | 359 | 1) |
| | 360 | message = message_from_string(stream.getvalue()) |
| | 361 | self.assertEqual(message['Content-Type'], |
| | 362 | 'text/plain; charset="utf-8"') |
| | 363 | self.assertEqual(message['Subject'], 'Subject') |
| | 364 | self.assertEqual(message['From'], 'from@example.com') |
| | 365 | |
| | 366 | stream = StringIO() |
| | 367 | connection = mail.get_connection( |
| | 368 | 'django.core.mail.backends.console.EmailBackend', stream=stream) |
| | 369 | self.assertEqual(send_mass_mail([ |
| | 370 | ('Subject1', 'Content1', |
| | 371 | 'from1@example.com', ['to1@example.com']), |
| | 372 | ('Subject2', 'Content2', |
| | 373 | 'from2@example.com', ['to2@example.com']) |
| | 374 | ], connection=connection), 2) |
| | 375 | # message separator in stream is '-'*79 |
| | 376 | raw = [x.strip() for x in stream.getvalue().split('-'*79)] |
| | 377 | first, second, _ = map(message_from_string, raw) |
| | 378 | self.assertEqual(first['Subject'], 'Subject1') |
| | 379 | self.assertEqual(second['Subject'], 'Subject2') |
| | 380 | self.assertEqual(first.get_payload(), 'Content1') |
| | 381 | self.assertEqual(second.get_payload(), 'Content2') |
| | 382 | |
| | 383 | stream = StringIO() |
| | 384 | connection = mail.get_connection( |
| | 385 | 'django.core.mail.backends.console.EmailBackend', stream=stream) |
| | 386 | old_admins = settings.ADMINS |
| | 387 | settings.ADMINS = [('nobody','nobody@example.com')] |
| | 388 | try: |
| | 389 | mail_admins('Subject', 'Content', connection=connection) |
| | 390 | finally: |
| | 391 | settings.ADMINS = old_admins |
| | 392 | message = message_from_string(stream.getvalue()) |
| | 393 | self.assertEqual(message['From'], 'root@localhost') |
| | 394 | self.assertEqual(message['To'], 'nobody@example.com') |
| | 395 | |
| | 396 | stream = StringIO() |
| | 397 | connection = mail.get_connection( |
| | 398 | 'django.core.mail.backends.console.EmailBackend', stream=stream) |
| | 399 | old_managers = settings.MANAGERS |
| | 400 | settings.MANAGERS = [('nobody','nobody@example.com')] |
| | 401 | try: |
| | 402 | mail_managers('Subject', 'Content', connection=connection) |
| | 403 | finally: |
| | 404 | settings.MANAGERS = old_managers |
| | 405 | message = message_from_string(stream.getvalue()) |
| | 406 | self.assertEqual(message['From'], 'root@localhost') |
| | 407 | self.assertEqual(message['To'], 'nobody@example.com') |
| | 408 | |
| | 409 | def test_cc(self): |
| | 410 | # Add Cc to the email argument list (#7722) |
| | 411 | email = EmailMessage('Subject', 'Content', 'from@example.com', |
| | 412 | ['to@example.com'], cc=['cc@example.com']) |
| | 413 | message = email.message() |
| | 414 | self.assertEqual(message['Cc'], 'cc@example.com') |
| | 415 | self.assertEqual(email.recipients(), ['to@example.com', |
| | 416 | 'cc@example.com']) |
| | 417 | |
| | 418 | email = EmailMessage('Subject', 'Content', 'from@example.com', |
| | 419 | ['to@example.com','other@example.com'], |
| | 420 | cc=['cc@example.com', 'cc.other@example.com']) |
| | 421 | message = email.message() |
| | 422 | self.assertEqual(message['Cc'], |
| | 423 | 'cc@example.com, cc.other@example.com') |
| | 424 | self.assertEqual(email.recipients(), |
| | 425 | ['to@example.com', 'other@example.com', |
| | 426 | 'cc@example.com', 'cc.other@example.com']) |
| | 427 | |
| | 428 | def test_bcc(self): |
| | 429 | email = EmailMessage('Subject', 'Content', 'from@example.com', |
| | 430 | ['to@example.com','other@example.com'], |
| | 431 | cc=['cc@example.com', 'cc.other@example.com'], |
| | 432 | bcc=['bcc@example.com']) |
| | 433 | self.assertEqual(email.recipients(), |
| | 434 | ['to@example.com', 'other@example.com', |
| | 435 | 'cc@example.com', 'cc.other@example.com', |
| | 436 | 'bcc@example.com']) |