123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400 |
- # -*- coding: utf-8 -*-
- from __future__ import unicode_literals
- from datetime import date, datetime
-
- from django.core import mail
- from django.core.files.base import ContentFile
- from django.conf import settings
-
- from django.test import TestCase
- from django.test.utils import override_settings
-
- from ..settings import get_batch_size, get_log_level, get_threads_per_process
- from ..models import Email, EmailTemplate, Attachment, PRIORITY, STATUS
- from ..mail import (create, get_queued,
- send, send_many, send_queued, _send_bulk)
-
-
- connection_counter = 0
-
-
- class ConnectionTestingBackend(mail.backends.base.BaseEmailBackend):
- '''
- An EmailBackend that increments a global counter when connection is opened
- '''
-
- def open(self):
- global connection_counter
- connection_counter += 1
-
- def send_messages(self, email_messages):
- pass
-
-
- class MailTest(TestCase):
-
- @override_settings(EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend')
- def test_send_queued_mail(self):
- """
- Check that only queued messages are sent.
- """
- kwargs = {
- 'to': ['to@example.com'],
- 'from_email': 'bob@example.com',
- 'subject': 'Test',
- 'message': 'Message',
- }
- failed_mail = Email.objects.create(status=STATUS.failed, **kwargs)
- none_mail = Email.objects.create(status=None, **kwargs)
-
- # This should be the only email that gets sent
- queued_mail = Email.objects.create(status=STATUS.queued, **kwargs)
- send_queued()
- self.assertNotEqual(Email.objects.get(id=failed_mail.id).status, STATUS.sent)
- self.assertNotEqual(Email.objects.get(id=none_mail.id).status, STATUS.sent)
- self.assertEqual(Email.objects.get(id=queued_mail.id).status, STATUS.sent)
-
- @override_settings(EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend')
- def test_send_queued_mail_multi_processes(self):
- """
- Check that send_queued works well with multiple processes
- """
- kwargs = {
- 'to': ['to@example.com'],
- 'from_email': 'bob@example.com',
- 'subject': 'Test',
- 'message': 'Message',
- 'status': STATUS.queued
- }
-
- # All three emails should be sent
- self.assertEqual(Email.objects.filter(status=STATUS.sent).count(), 0)
- for i in range(3):
- Email.objects.create(**kwargs)
- total_sent, total_failed = send_queued(processes=2)
- self.assertEqual(total_sent, 3)
-
- def test_send_bulk(self):
- """
- Ensure _send_bulk() properly sends out emails.
- """
- email = Email.objects.create(
- to=['to@example.com'], from_email='bob@example.com',
- subject='send bulk', message='Message', status=STATUS.queued,
- backend_alias='locmem')
- _send_bulk([email], uses_multiprocessing=False)
- self.assertEqual(Email.objects.get(id=email.id).status, STATUS.sent)
- self.assertEqual(len(mail.outbox), 1)
- self.assertEqual(mail.outbox[0].subject, 'send bulk')
-
- @override_settings(EMAIL_BACKEND='post_office.tests.test_mail.ConnectionTestingBackend')
- def test_send_bulk_reuses_open_connection(self):
- """
- Ensure _send_bulk() only opens connection once to send multiple emails.
- """
- global connection_counter
- self.assertEqual(connection_counter, 0)
- email = Email.objects.create(to=['to@example.com'],
- from_email='bob@example.com', subject='',
- message='', status=STATUS.queued, backend_alias='connection_tester')
- email_2 = Email.objects.create(to=['to@example.com'],
- from_email='bob@example.com', subject='',
- message='', status=STATUS.queued,
- backend_alias='connection_tester')
- _send_bulk([email, email_2])
- self.assertEqual(connection_counter, 1)
-
- def test_get_queued(self):
- """
- Ensure get_queued returns only emails that should be sent
- """
- kwargs = {
- 'to': 'to@example.com',
- 'from_email': 'bob@example.com',
- 'subject': 'Test',
- 'message': 'Message',
- }
- self.assertEqual(list(get_queued()), [])
-
- # Emails with statuses failed, sent or None shouldn't be returned
- Email.objects.create(status=STATUS.failed, **kwargs)
- Email.objects.create(status=None, **kwargs)
- Email.objects.create(status=STATUS.sent, **kwargs)
- self.assertEqual(list(get_queued()), [])
-
- # Email with queued status and None as scheduled_time should be included
- queued_email = Email.objects.create(status=STATUS.queued,
- scheduled_time=None, **kwargs)
- self.assertEqual(list(get_queued()), [queued_email])
-
- # Email scheduled for the future should not be included
- Email.objects.create(status=STATUS.queued,
- scheduled_time=date(2020, 12, 13), **kwargs)
- self.assertEqual(list(get_queued()), [queued_email])
-
- # Email scheduled in the past should be included
- past_email = Email.objects.create(status=STATUS.queued,
- scheduled_time=date(2010, 12, 13), **kwargs)
- self.assertEqual(list(get_queued()), [queued_email, past_email])
-
- def test_get_batch_size(self):
- """
- Ensure BATCH_SIZE setting is read correctly.
- """
- previous_settings = settings.POST_OFFICE
- self.assertEqual(get_batch_size(), 100)
- setattr(settings, 'POST_OFFICE', {'BATCH_SIZE': 10})
- self.assertEqual(get_batch_size(), 10)
- settings.POST_OFFICE = previous_settings
-
- def test_get_threads_per_process(self):
- """
- Ensure THREADS_PER_PROCESS setting is read correctly.
- """
- previous_settings = settings.POST_OFFICE
- self.assertEqual(get_threads_per_process(), 5)
- setattr(settings, 'POST_OFFICE', {'THREADS_PER_PROCESS': 10})
- self.assertEqual(get_threads_per_process(), 10)
- settings.POST_OFFICE = previous_settings
-
- def test_get_log_level(self):
- """
- Ensure LOG_LEVEL setting is read correctly.
- """
- previous_settings = settings.POST_OFFICE
- self.assertEqual(get_log_level(), 2)
- setattr(settings, 'POST_OFFICE', {'LOG_LEVEL': 1})
- self.assertEqual(get_log_level(), 1)
- # Restore ``LOG_LEVEL``
- setattr(settings, 'POST_OFFICE', {'LOG_LEVEL': 2})
- settings.POST_OFFICE = previous_settings
-
- def test_create(self):
- """
- Test basic email creation
- """
-
- # Test that email is persisted only when commit=True
- email = create(
- sender='from@example.com', recipients=['to@example.com'],
- commit=False
- )
- self.assertEqual(email.id, None)
- email = create(
- sender='from@example.com', recipients=['to@example.com'],
- commit=True
- )
- self.assertNotEqual(email.id, None)
-
- # Test that email is created with the right status
- email = create(
- sender='from@example.com', recipients=['to@example.com'],
- priority=PRIORITY.now
- )
- self.assertEqual(email.status, None)
- email = create(
- sender='from@example.com', recipients=['to@example.com'],
- priority=PRIORITY.high
- )
- self.assertEqual(email.status, STATUS.queued)
-
- # Test that email is created with the right content
- context = {
- 'subject': 'My subject',
- 'message': 'My message',
- 'html': 'My html',
- }
- now = datetime.now()
- email = create(
- sender='from@example.com', recipients=['to@example.com'],
- subject='Test {{ subject }}', message='Test {{ message }}',
- html_message='Test {{ html }}', context=context,
- scheduled_time=now, headers={'header': 'Test header'},
- )
- self.assertEqual(email.from_email, 'from@example.com')
- self.assertEqual(email.to, ['to@example.com'])
- self.assertEqual(email.subject, 'Test My subject')
- self.assertEqual(email.message, 'Test My message')
- self.assertEqual(email.html_message, 'Test My html')
- self.assertEqual(email.scheduled_time, now)
- self.assertEqual(email.headers, {'header': 'Test header'})
-
- def test_send_many(self):
- """Test send_many creates the right emails """
- kwargs_list = [
- {'sender': 'from@example.com', 'recipients': ['a@example.com']},
- {'sender': 'from@example.com', 'recipients': ['b@example.com']},
- ]
- send_many(kwargs_list)
- self.assertEqual(Email.objects.filter(to=['a@example.com']).count(), 1)
-
- def test_send_with_attachments(self):
- attachments = {
- 'attachment_file1.txt': ContentFile('content'),
- 'attachment_file2.txt': ContentFile('content'),
- }
- email = send(recipients=['a@example.com', 'b@example.com'],
- sender='from@example.com', message='message',
- subject='subject', attachments=attachments)
-
- self.assertTrue(email.pk)
- self.assertEqual(email.attachments.count(), 2)
-
- def test_send_with_render_on_delivery(self):
- """
- Ensure that mail.send() create email instances with appropriate
- fields being saved
- """
- template = EmailTemplate.objects.create(
- subject='Subject {{ name }}',
- content='Content {{ name }}',
- html_content='HTML {{ name }}'
- )
- context = {'name': 'test'}
- email = send(recipients=['a@example.com', 'b@example.com'],
- template=template, context=context,
- render_on_delivery=True)
- self.assertEqual(email.subject, '')
- self.assertEqual(email.message, '')
- self.assertEqual(email.html_message, '')
- self.assertEqual(email.template, template)
-
- # context shouldn't be persisted when render_on_delivery = False
- email = send(recipients=['a@example.com'],
- template=template, context=context,
- render_on_delivery=False)
- self.assertEqual(email.context, None)
-
- def test_send_with_attachments_multiple_recipients(self):
- """Test reusing the same attachment objects for several email objects"""
- attachments = {
- 'attachment_file1.txt': ContentFile('content'),
- 'attachment_file2.txt': ContentFile('content'),
- }
- email = send(recipients=['a@example.com', 'b@example.com'],
- sender='from@example.com', message='message',
- subject='subject', attachments=attachments)
-
- self.assertEqual(email.attachments.count(), 2)
- self.assertEqual(Attachment.objects.count(), 2)
-
- def test_create_with_template(self):
- """If render_on_delivery is True, subject and content
- won't be rendered, context also won't be saved."""
-
- template = EmailTemplate.objects.create(
- subject='Subject {{ name }}',
- content='Content {{ name }}',
- html_content='HTML {{ name }}'
- )
- context = {'name': 'test'}
- email = create(
- sender='from@example.com', recipients=['to@example.com'],
- template=template, context=context, render_on_delivery=True
- )
- self.assertEqual(email.subject, '')
- self.assertEqual(email.message, '')
- self.assertEqual(email.html_message, '')
- self.assertEqual(email.context, context)
- self.assertEqual(email.template, template)
-
- def test_create_with_template_and_empty_context(self):
- """If render_on_delivery is False, subject and content
- will be rendered, context won't be saved."""
-
- template = EmailTemplate.objects.create(
- subject='Subject {% now "Y" %}',
- content='Content {% now "Y" %}',
- html_content='HTML {% now "Y" %}'
- )
- context = None
- email = create(
- sender='from@example.com', recipients=['to@example.com'],
- template=template, context=context
- )
- today = date.today()
- current_year = today.year
- self.assertEqual(email.subject, 'Subject %d' % current_year)
- self.assertEqual(email.message, 'Content %d' % current_year)
- self.assertEqual(email.html_message, 'HTML %d' % current_year)
- self.assertEqual(email.context, None)
- self.assertEqual(email.template, None)
-
- def test_backend_alias(self):
- """Test backend_alias field is properly set."""
-
- email = send(recipients=['a@example.com'],
- sender='from@example.com', message='message',
- subject='subject')
- self.assertEqual(email.backend_alias, '')
-
- email = send(recipients=['a@example.com'],
- sender='from@example.com', message='message',
- subject='subject', backend='locmem')
- self.assertEqual(email.backend_alias, 'locmem')
-
- with self.assertRaises(ValueError):
- send(recipients=['a@example.com'], sender='from@example.com',
- message='message', subject='subject', backend='foo')
-
- @override_settings(LANGUAGES=(('en', 'English'), ('ru', 'Russian')))
- def test_send_with_template(self):
- """If render_on_delivery is False, subject and content
- will be rendered, context won't be saved."""
-
- template = EmailTemplate.objects.create(
- subject='Subject {{ name }}',
- content='Content {{ name }}',
- html_content='HTML {{ name }}'
- )
- russian_template = EmailTemplate(
- default_template=template,
- language='ru',
- subject='предмет {{ name }}',
- content='содержание {{ name }}',
- html_content='HTML {{ name }}'
- )
- russian_template.save()
-
- context = {'name': 'test'}
- email = send(recipients=['to@example.com'], sender='from@example.com',
- template=template, context=context)
- email = Email.objects.get(id=email.id)
- self.assertEqual(email.subject, 'Subject test')
- self.assertEqual(email.message, 'Content test')
- self.assertEqual(email.html_message, 'HTML test')
- self.assertEqual(email.context, None)
- self.assertEqual(email.template, None)
-
- # check, if we use the Russian version
- email = send(recipients=['to@example.com'], sender='from@example.com',
- template=russian_template, context=context)
- email = Email.objects.get(id=email.id)
- self.assertEqual(email.subject, 'предмет test')
- self.assertEqual(email.message, 'содержание test')
- self.assertEqual(email.html_message, 'HTML test')
- self.assertEqual(email.context, None)
- self.assertEqual(email.template, None)
-
- # Check that send picks template with the right language
- email = send(recipients=['to@example.com'], sender='from@example.com',
- template=template, context=context, language='ru')
- email = Email.objects.get(id=email.id)
- self.assertEqual(email.subject, 'предмет test')
-
- email = send(recipients=['to@example.com'], sender='from@example.com',
- template=template, context=context, language='ru',
- render_on_delivery=True)
- self.assertEqual(email.template.language, 'ru')
-
- def test_send_bulk_with_faulty_template(self):
- template = EmailTemplate.objects.create(
- subject='{% if foo %}Subject {{ name }}',
- content='Content {{ name }}',
- html_content='HTML {{ name }}'
- )
- email = Email.objects.create(to='to@example.com', from_email='from@example.com',
- template=template, status=STATUS.queued)
- _send_bulk([email], uses_multiprocessing=False)
- email = Email.objects.get(id=email.id)
- self.assertEqual(email.status, STATUS.failed)
|