# coding: utf-8 r""" # Tests for the django.core.mail. >>> import os >>> import shutil >>> import tempfile >>> from StringIO import StringIO >>> from django.conf import settings >>> from django.core import mail >>> from django.core.mail import EmailMessage, mail_admins, mail_managers, EmailMultiAlternatives >>> from django.core.mail import send_mail, send_mass_mail >>> from django.core.mail.backends.base import BaseEmailBackend >>> from django.core.mail.backends import console, dummy, locmem, filebased, smtp >>> from django.utils.translation import ugettext_lazy # Test normal ascii character case: >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com']) >>> message = email.message() >>> message['Subject'].encode() 'Subject' >>> message.get_payload() 'Content' >>> message['From'] 'from@example.com' >>> message['To'] 'to@example.com' # Test multiple-recipient case >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com','other@example.com']) >>> message = email.message() >>> message['Subject'].encode() 'Subject' >>> message.get_payload() 'Content' >>> message['From'] 'from@example.com' >>> message['To'] 'to@example.com, other@example.com' # Test for header injection >>> email = EmailMessage('Subject\nInjection Test', 'Content', 'from@example.com', ['to@example.com']) >>> message = email.message() Traceback (most recent call last): ... BadHeaderError: Header values can't contain newlines (got u'Subject\nInjection Test' for header 'Subject') >>> email = EmailMessage(ugettext_lazy('Subject\nInjection Test'), 'Content', 'from@example.com', ['to@example.com']) >>> message = email.message() Traceback (most recent call last): ... BadHeaderError: Header values can't contain newlines (got u'Subject\nInjection Test' for header 'Subject') # Test for space continuation character in long (ascii) subject headers (#7747) >>> 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']) >>> message = email.message() >>> message.as_string() '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' # Specifying dates or message-ids in the extra headers overrides the defaul # values (#9233). >>> headers = {"date": "Fri, 09 Nov 2001 01:08:47 -0000", "Message-ID": "foo"} >>> email = EmailMessage('subject', 'content', 'from@example.com', ['to@example.com'], headers=headers) >>> email.message().as_string() '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' # Test that mail_admins/mail_managers doesn't connect to the mail server if there are no recipients (#9383) >>> old_admins = settings.ADMINS >>> old_managers = settings.MANAGERS >>> settings.ADMINS = [] >>> settings.MANAGERS = [] >>> mail.outbox = [] >>> mail_admins('hi','there') >>> len(mail.outbox) 0 >>> mail.outbox = [] >>> mail_managers('hi','there') >>> len(mail.outbox) 0 >>> settings.ADMINS = settings.MANAGERS = [('nobody','nobody@example.com')] >>> mail.outbox = [] >>> mail_admins('hi','there') >>> len(mail.outbox) 1 >>> mail.outbox = [] >>> mail_managers('hi','there') >>> len(mail.outbox) 1 # Make sure we can manually set the From header (#9214) >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) >>> message = email.message() >>> message['From'] 'from@example.com' # Regression for #13259 - Make sure that headers are not changed # when calling EmailMessage.message() >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) >>> message = email.message() >>> message['From'] 'from@example.com' >>> message = email.message() >>> message['From'] 'from@example.com' # Regression for #11144 - When a to/from/cc header contains unicode, # make sure the email addresses are parsed correctly (especially # with regards to commas) >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['"Firstname Sürname" ','other@example.com']) >>> email.message()['To'] '=?utf-8?q?Firstname_S=C3=BCrname?= , other@example.com' >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['"Sürname, Firstname" ','other@example.com']) >>> email.message()['To'] '=?utf-8?q?S=C3=BCrname=2C_Firstname?= , other@example.com' # Regression for #6918 - When a header contains unicode, # make sure headers can be set with a different encoding than utf-8 >>> email = EmailMessage('Message from Firstname Sürname', 'Content', 'from@example.com', ['"Sürname, Firstname" ','other@example.com']) >>> email.encoding = 'iso-8859-1' >>> email.message()['To'] '=?iso-8859-1?q?S=FCrname=2C_Firstname?= , other@example.com' >>> email.message()['Subject'].encode() u'=?iso-8859-1?q?Message_from_Firstname_S=FCrname?=' # Make sure headers can be set with a different encoding than utf-8 in SafeMIMEMultipart as well >>> headers = {"Date": "Fri, 09 Nov 2001 01:08:47 -0000", "Message-ID": "foo"} >>> subject, from_email, to = 'hello', 'from@example.com', '"Sürname, Firstname" ' >>> text_content = 'This is an important message.' >>> html_content = '

This is an important message.

' >>> msg = EmailMultiAlternatives('Message from Firstname Sürname', text_content, from_email, [to], headers=headers) >>> msg.attach_alternative(html_content, "text/html") >>> msg.encoding = 'iso-8859-1' >>> msg.message()['To'] '=?iso-8859-1?q?S=FCrname=2C_Firstname?= ' >>> msg.message()['Subject'].encode() u'=?iso-8859-1?q?Message_from_Firstname_S=FCrname?=' # Regression for #12791 - Encode body correctly with other encodings than utf-8 >>> email = EmailMessage('Subject', 'Firstname Sürname is a great guy.', 'from@example.com', ['other@example.com']) >>> email.encoding = 'iso-8859-1' >>> message = email.message() >>> message.as_string() '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.' # Make sure MIME attachments also works correctly with other encodings than utf-8 >>> text_content = 'Firstname Sürname is a great guy.' >>> html_content = '

Firstname Sürname is a great guy.

' >>> msg = EmailMultiAlternatives('Subject', text_content, 'from@example.com', ['to@example.com']) >>> msg.encoding = 'iso-8859-1' >>> msg.attach_alternative(html_content, "text/html") >>> msg.message().get_payload(0).as_string() '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.' >>> msg.message().get_payload(1).as_string() 'Content-Type: text/html; charset="iso-8859-1"\nMIME-Version: 1.0\nContent-Transfer-Encoding: quoted-printable\n\n

Firstname S=FCrname is a great guy.

' # Handle attachments within an multipart/alternative mail correctly (#9367) # (test is not as precise/clear as it could be w.r.t. email tree structure, # but it's good enough.) >>> headers = {"Date": "Fri, 09 Nov 2001 01:08:47 -0000", "Message-ID": "foo"} >>> subject, from_email, to = 'hello', 'from@example.com', 'to@example.com' >>> text_content = 'This is an important message.' >>> html_content = '

This is an important message.

' >>> msg = EmailMultiAlternatives(subject, text_content, from_email, [to], headers=headers) >>> msg.attach_alternative(html_content, "text/html") >>> msg.attach("an attachment.pdf", "%PDF-1.4.%...", mimetype="application/pdf") >>> print msg.message().as_string() Content-Type: multipart/mixed; boundary="..." MIME-Version: 1.0 Subject: hello From: from@example.com To: to@example.com Date: Fri, 09 Nov 2001 01:08:47 -0000 Message-ID: foo ... Content-Type: multipart/alternative;... ... Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable ... This is an important message. ... Content-Type: text/html; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable ...

This is an important message.

... ... Content-Type: application/pdf MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="an attachment.pdf" ... JVBERi0xLjQuJS4uLg== ... # Make sure that the console backend writes to stdout by default >>> connection = console.EmailBackend() >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) >>> connection.send_messages([email]) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: Subject From: from@example.com To: to@example.com Date: ... Message-ID: ... Content ------------------------------------------------------------------------------- 1 # Test that the console backend can be pointed at an arbitrary stream >>> s = StringIO() >>> connection = mail.get_connection('django.core.mail.backends.console.EmailBackend', stream=s) >>> send_mail('Subject', 'Content', 'from@example.com', ['to@example.com'], connection=connection) 1 >>> print s.getvalue() Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: Subject From: from@example.com To: to@example.com Date: ... Message-ID: ... Content ------------------------------------------------------------------------------- # Make sure that dummy backends returns correct number of sent messages >>> connection = dummy.EmailBackend() >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) >>> connection.send_messages([email, email, email]) 3 # Make sure that locmen backend populates the outbox >>> mail.outbox = [] >>> connection = locmem.EmailBackend() >>> email1 = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) >>> email2 = EmailMessage('Subject 2', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) >>> connection.send_messages([email1, email2]) 2 >>> len(mail.outbox) 2 >>> mail.outbox[0].subject 'Subject' >>> mail.outbox[1].subject 'Subject 2' # Make sure that multiple locmem connections share mail.outbox >>> mail.outbox = [] >>> connection1 = locmem.EmailBackend() >>> connection2 = locmem.EmailBackend() >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) >>> connection1.send_messages([email]) 1 >>> connection2.send_messages([email]) 1 >>> len(mail.outbox) 2 # Make sure that the file backend write to the right location >>> tmp_dir = tempfile.mkdtemp() >>> connection = filebased.EmailBackend(file_path=tmp_dir) >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) >>> connection.send_messages([email]) 1 >>> len(os.listdir(tmp_dir)) 1 >>> print open(os.path.join(tmp_dir, os.listdir(tmp_dir)[0])).read() Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: Subject From: from@example.com To: to@example.com Date: ... Message-ID: ... Content ------------------------------------------------------------------------------- >>> connection2 = filebased.EmailBackend(file_path=tmp_dir) >>> connection2.send_messages([email]) 1 >>> len(os.listdir(tmp_dir)) 2 >>> connection.send_messages([email]) 1 >>> len(os.listdir(tmp_dir)) 2 >>> email.connection = filebased.EmailBackend(file_path=tmp_dir) >>> connection_created = connection.open() >>> num_sent = email.send() >>> len(os.listdir(tmp_dir)) 3 >>> num_sent = email.send() >>> len(os.listdir(tmp_dir)) 3 >>> connection.close() >>> shutil.rmtree(tmp_dir) # Make sure that get_connection() accepts arbitrary keyword that might be # used with custom backends. >>> c = mail.get_connection(fail_silently=True, foo='bar') >>> c.fail_silently True # Test custom backend defined in this suite. >>> conn = mail.get_connection('regressiontests.mail.custombackend.EmailBackend') >>> hasattr(conn, 'test_outbox') True >>> email = EmailMessage('Subject', 'Content', 'bounce@example.com', ['to@example.com'], headers={'From': 'from@example.com'}) >>> conn.send_messages([email]) 1 >>> len(conn.test_outbox) 1 # Test backend argument of mail.get_connection() >>> isinstance(mail.get_connection('django.core.mail.backends.smtp.EmailBackend'), smtp.EmailBackend) True >>> isinstance(mail.get_connection('django.core.mail.backends.locmem.EmailBackend'), locmem.EmailBackend) True >>> isinstance(mail.get_connection('django.core.mail.backends.dummy.EmailBackend'), dummy.EmailBackend) True >>> isinstance(mail.get_connection('django.core.mail.backends.console.EmailBackend'), console.EmailBackend) True >>> tmp_dir = tempfile.mkdtemp() >>> isinstance(mail.get_connection('django.core.mail.backends.filebased.EmailBackend', file_path=tmp_dir), filebased.EmailBackend) True >>> shutil.rmtree(tmp_dir) >>> isinstance(mail.get_connection(), locmem.EmailBackend) True # Test connection argument of send_mail() et al >>> connection = mail.get_connection('django.core.mail.backends.console.EmailBackend') >>> send_mail('Subject', 'Content', 'from@example.com', ['to@example.com'], connection=connection) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: Subject From: from@example.com To: to@example.com Date: ... Message-ID: ... Content ------------------------------------------------------------------------------- 1 >>> send_mass_mail([ ... ('Subject1', 'Content1', 'from1@example.com', ['to1@example.com']), ... ('Subject2', 'Content2', 'from2@example.com', ['to2@example.com']) ... ], connection=connection) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: Subject1 From: from1@example.com To: to1@example.com Date: ... Message-ID: ... Content1 ------------------------------------------------------------------------------- Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: Subject2 From: from2@example.com To: to2@example.com Date: ... Message-ID: ... Content2 ------------------------------------------------------------------------------- 2 >>> mail_admins('Subject', 'Content', connection=connection) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: [Django] Subject From: root@localhost To: nobody@example.com Date: ... Message-ID: ... Content ------------------------------------------------------------------------------- >>> mail_managers('Subject', 'Content', connection=connection) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: [Django] Subject From: root@localhost To: nobody@example.com Date: ... Message-ID: ... Content ------------------------------------------------------------------------------- >>> settings.ADMINS = old_admins >>> settings.MANAGERS = old_managers # Add Cc to the email argument list (#7722) >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com'], cc=['cc@example.com']) >>> message = email.message() >>> message['Cc'] 'cc@example.com' >>> email.recipients() ['to@example.com', 'cc@example.com'] >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com','other@example.com'], cc=['cc@example.com', 'cc.other@example.com']) >>> message = email.message() >>> message['Cc'] 'cc@example.com, cc.other@example.com' >>> email.recipients() ['to@example.com', 'other@example.com', 'cc@example.com', 'cc.other@example.com'] >>> 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']) >>> message = email.message() >>> email.recipients() ['to@example.com', 'other@example.com', 'cc@example.com', 'cc.other@example.com', 'bcc@example.com'] >>> email = EmailMessage('Subject', 'Content', 'from@example.com', ['to@example.com'], cc=['cc@example.com']) >>> message = email.message() >>> message.as_string() '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' """