Skip to content

Commit

Permalink
Merge pull request #142 from vintasoftware/docs/settings
Browse files Browse the repository at this point in the history
Add settings section to docs
  • Loading branch information
rangelfinal authored Sep 29, 2023
2 parents ca1729a + 119e33d commit 43ed02a
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 63 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@ name: Run tests

on:
- push
- pull_request

jobs:
build:
runs-on: ubuntu-latest

strategy:
matrix:
python-version: ['3.6', '3.7', '3.8', '3.9', '3.10', '3.11']
python-version: ['3.8', '3.9', '3.10', '3.11']

steps:
- uses: actions/checkout@v3
Expand Down
18 changes: 18 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,24 @@ Methods:
a celery's task for example or to handle errors.


Settings
=============

You can configure Django-Templated-Email by setting the following settings

.. code-block:: python
TEMPLATED_EMAIL_FROM_EMAIL = None # String containing the email to send the email from - fallback to DEFAULT_FROM_EMAIL
TEMPLATED_EMAIL_BACKEND = TemplateBackend # The backend class that will send the email, as a string like 'foo.bar.TemplateBackend' or the class reference itself
TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/' # The directory containing the templates, use '' if using the top level
TEMPLATED_EMAIL_FILE_EXTENSION = 'email' # The file extension of the template files
TEMPLATED_EMAIL_AUTO_PLAIN = True # Set to false to disable the behavior of calculating the plain part from the html part of the email when `html2text <https://pypi.python.org/pypi/html2text>` is installed
TEMPLATED_EMAIL_PLAIN_FUNCTION = None # Specify a custom function that converts from HTML to the plain part
# Specific for anymail integration:
TEMPLATED_EMAIL_EMAIL_MESSAGE_CLASS = 'django.core.mail.EmailMessage' # Replaces django.core.mail.EmailMessage
TEMPLATED_EMAIL_EMAIL_MULTIALTERNATIVES_CLASS = 'django.core.mail.EmailMultiAlternatives' # Replaces django.core.mail.EmailMultiAlternatives
Future Plans
=============

Expand Down
68 changes: 36 additions & 32 deletions tests/backends/test_vanilla_django_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@

from django.test import TestCase, override_settings
from django.core.mail import EmailMessage, EmailMultiAlternatives
from django.core.files.storage import get_storage_class
try:
from django.core.files.storage import get_storage_class
except ImportError:
from django.core.files.storage import storages

def get_storage_class(s):
storages[s]

from django.template import TemplateDoesNotExist
from django.core import mail

import pytest
from mock import patch, Mock
from unittest.mock import patch, Mock
from anymail.message import AnymailMessage

from templated_email.backends.vanilla_django import TemplateBackend, EmailRenderException
Expand Down Expand Up @@ -69,17 +76,11 @@ class TemplateBackendTestCase(MockedNetworkTestCaseMixin,
template_backend_klass = TemplateBackend

def setUp(self):
self.storage_mock = Mock(wraps=get_storage_class())()
self.storage_mock.save = Mock()
self.backend = self.template_backend_klass()
self.context = {'username': 'vintasoftware',
'joindate': date(2016, 8, 22),
'full_name': 'Foo Bar'}

def patch_storage(self):
return patch('django.core.files.storage.default_storage._wrapped',
self.storage_mock)

def test_inexistent_base_email(self):
try:
self.backend._render_email('inexistent_base.email', {})
Expand Down Expand Up @@ -168,22 +169,23 @@ def test_get_email_message_with_create_link(self, mocked):
uuid=uuid)
self.assertEqual(saved_email.content, HTML_RESULT)

@patch('django.core.files.storage.FileSystemStorage.save')
@patch('django.core.files.storage.FileSystemStorage.url')
@patch.object(
template_backend_klass, '_render_email',
return_value={'html': HTML_RESULT, 'plain': PLAIN_RESULT,
'subject': SUBJECT_RESULT}
)
def test_get_email_message_with_inline_image(self, mocked):
self.storage_mock.save = Mock(return_value='saved_url')
with self.patch_storage():
self.backend.get_email_message(
'foo.email', {'an_image': InlineImage('file.png', b'foo',
subtype='png')},
from_email='[email protected]', cc=['[email protected]'],
bcc=['[email protected]'], to=['[email protected]'],
create_link=True)
second_call_context = mocked.call_args_list[1][0][1]
self.assertEqual(second_call_context['an_image'], '/media/saved_url')
def test_get_email_message_with_inline_image(self, mock_render_email, mock_url, mock_save):
mock_url.return_value = 'media/saved_url'
self.backend.get_email_message(
'foo.email', {'an_image': InlineImage('file.png', b'foo',
subtype='png')},
from_email='[email protected]', cc=['[email protected]'],
bcc=['[email protected]'], to=['[email protected]'],
create_link=True)
second_call_context = mock_render_email.call_args_list[1][0][1]
self.assertEqual(second_call_context['an_image'], 'media/saved_url')

@override_settings(TEMPLATED_EMAIL_EMAIL_MESSAGE_CLASS='anymail.message.AnymailMessage')
@patch.object(
Expand Down Expand Up @@ -496,30 +498,32 @@ def test_removal_of_legacy(self):
except TemplateDoesNotExist as e:
self.assertEqual(e.args[0], 'templated_email/legacy.email')

def test_host_inline_image_if_not_exist(self):
@patch('django.core.files.storage.FileSystemStorage.url')
@patch('django.core.files.storage.FileSystemStorage.save')
def test_host_inline_image_if_not_exist(self, mock_save, mock_url):
mock_url.return_value = 'media/saved_url'
inline_image = InlineImage('foo.jpg', b'bar')
self.storage_mock.save = Mock(return_value='saved_url')

with self.patch_storage():
filename = self.backend.host_inline_image(inline_image)
self.assertEqual(filename, '/media/saved_url')
self.storage_mock.save.assert_called_once()
name, content = self.storage_mock.save.call_args[0]
filename = self.backend.host_inline_image(inline_image)
self.assertEqual(filename, 'media/saved_url')
mock_save.assert_called_once()
name, content = mock_save.call_args[0]
self.assertEqual(
name,
'templated_email/37b51d194a7513e45b56f6524f2d51f2foo.jpg')
self.assertTrue(isinstance(content, BytesIO))

def test_host_inline_image_if_exist(self):
@patch('django.core.files.storage.FileSystemStorage.exists')
@patch('django.core.files.storage.FileSystemStorage.save')
def test_host_inline_image_if_exist(self, mock_save, mock_exists):
inline_image = InlineImage('foo.jpg', b'bar')
self.storage_mock.exists = Mock(return_value=True)
mock_exists.return_value = True

with self.patch_storage():
filename = self.backend.host_inline_image(inline_image)
filename = self.backend.host_inline_image(inline_image)
self.assertEqual(
filename,
'/media/templated_email/37b51d194a7513e45b56f6524f2d51f2foo.jpg')

self.storage_mock.save.assert_not_called()
self.storage_mock.exists.assert_called_once_with(
mock_save.assert_not_called()
mock_exists.assert_called_once_with(
'templated_email/37b51d194a7513e45b56f6524f2d51f2foo.jpg')
10 changes: 5 additions & 5 deletions tests/generic_views/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from django.core.exceptions import ImproperlyConfigured
from django.core import mail

import mock
from unittest.mock import patch

from templated_email.generic_views import TemplatedEmailFormViewMixin
from tests.generic_views.views import AuthorCreateView
Expand Down Expand Up @@ -44,10 +44,10 @@ def test_templated_email_get_recipients(self):
self.mixin_object.templated_email_get_recipients,
form=None)

@mock.patch.object(TemplatedEmailFormViewMixin,
@patch.object(TemplatedEmailFormViewMixin,
'templated_email_get_template_names',
return_value=['template'])
@mock.patch.object(TemplatedEmailFormViewMixin,
@patch.object(TemplatedEmailFormViewMixin,
'templated_email_get_recipients',
return_value=['[email protected]'])
def test_templated_email_get_send_email_kwargs_valid(
Expand All @@ -65,10 +65,10 @@ class FakeForm(object):
self.assertEqual(kwargs['recipient_list'], ['[email protected]'])
self.assertEqual(kwargs['context'], {'form_data': 'foo'})

@mock.patch.object(TemplatedEmailFormViewMixin,
@patch.object(TemplatedEmailFormViewMixin,
'templated_email_get_template_names',
return_value=['template'])
@mock.patch.object(TemplatedEmailFormViewMixin,
@patch.object(TemplatedEmailFormViewMixin,
'templated_email_get_recipients',
return_value=['[email protected]'])
def test_templated_email_get_send_email_kwargs_not_valid(
Expand Down
2 changes: 1 addition & 1 deletion tests/test_get_templated_mail.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.test import TestCase

from mock import patch
from unittest.mock import patch

from templated_email import get_templated_mail

Expand Down
2 changes: 1 addition & 1 deletion tests/test_send_templated_mail.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.test import TestCase

from mock import patch, Mock
from unittest.mock import patch, Mock

from templated_email import send_templated_mail

Expand Down
8 changes: 4 additions & 4 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import mock
from unittest.mock import patch, Mock

from django.test import TestCase

Expand All @@ -23,11 +23,11 @@ def test_generate_cid(self):
str(self.inline_image)
self.assertIsNotNone(self.inline_image._content_id)

@mock.patch('templated_email.utils.make_msgid', return_value='foo')
@patch('templated_email.utils.make_msgid', return_value='foo')
def test_str(self, mocked):
self.assertEqual(str(self.inline_image), 'cid:foo')

@mock.patch('templated_email.utils.make_msgid', return_value='foo')
@patch('templated_email.utils.make_msgid', return_value='foo')
def test_should_cache_cid(self, mocked):
str(self.inline_image)
str(self.inline_image)
Expand All @@ -45,7 +45,7 @@ def test_changing_content_should_generate_new_cid(self):
self.assertNotEqual(cid2, cid3)

def test_attach_to_message(self):
message = mock.Mock()
message = Mock()
self.inline_image.attach_to_message(message)
mimeimage = message.attach.call_args[0][0]
self.assertEqual(mimeimage.get('Content-ID'),
Expand Down
4 changes: 2 additions & 2 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import mock
import unittest.mock


class MockedNetworkTestCaseMixin(object):
# getfqdn can be too slow, mock it for speed.
# See: https://code.djangoproject.com/ticket/24380
@classmethod
def setUpClass(cls):
cls.getfqdn_patcher = mock.patch(
cls.getfqdn_patcher = unittest.mock.patch(
'django.core.mail.utils.socket.getfqdn',
return_value='vinta.local')
cls.getfqdn_patcher.start()
Expand Down
1 change: 0 additions & 1 deletion tox-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ django-anymail
django-pytest
django-render-block
html2text
mock
pytest
pytest-django
pytest-pythonpath
Expand Down
30 changes: 15 additions & 15 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
[tox]
envlist =
py36-{flake8},
{py36,py37,py38,py39}-django32,
{py38,py39,py310,py311}-django{40,41,main},
envlist = {linux}-py{38,39,310,311}-django{32,40,41,42}

[gh-actions]
python =
3.6: py36
3.7: py37
3.8: py38
3.9: py39
3.10: py310
3.11: py311


[gh-actions:env]
OS =
ubuntu-latest: linux
DJANGO =
3.2: django32
4.0: django40
4.1: django41
4.2: django42

[testenv]
commands=
py.test --cov=templated_email tests/
deps=
-rtox-requirements.txt
pytest-cov
django32: Django==3.2
django40: Django>=4.0,<4.1
django41: Django>=4.1,<4.2
djangomain: https://github.com/django/django/archive/main.tar.gz

[testenv:py36-flake8]
commands = flake8 templated_email tests --ignore=E501
deps =
flake8
django32: django~=3.2
django40: django~=4.0
django41: django~=4.1
django42: django~=4.2

0 comments on commit 43ed02a

Please sign in to comment.