Merge pull request #99 from Wrhector/v2.0-dev3

Allow Mandrill specific options to be set globally in the settings file.

Closes #97
This commit is contained in:
Mike Edmunds
2015-07-14 11:33:03 -07:00
4 changed files with 165 additions and 1 deletions

View File

@@ -17,3 +17,4 @@ Sameer Al-Sakran
Kyle Gibson Kyle Gibson
Wes Winham Wes Winham
nikolay-saskovets nikolay-saskovets
William Hector

View File

@@ -63,6 +63,12 @@ class DjrillBackend(BaseEmailBackend):
self.api_key = getattr(settings, "MANDRILL_API_KEY", None) self.api_key = getattr(settings, "MANDRILL_API_KEY", None)
self.api_url = MANDRILL_API_URL self.api_url = MANDRILL_API_URL
self.session = None self.session = None
self.global_settings = {}
for setting_key in getattr(settings, "MANDRILL_SETTINGS", {}):
if not isinstance(settings.MANDRILL_SETTINGS, dict):
raise ImproperlyConfigured("MANDRILL_SETTINGS must be a dict "
"in the settings.py file.")
self.global_settings[setting_key] = settings.MANDRILL_SETTINGS[setting_key]
self.subaccount = getattr(settings, "MANDRILL_SUBACCOUNT", None) self.subaccount = getattr(settings, "MANDRILL_SUBACCOUNT", None)
@@ -233,6 +239,8 @@ class DjrillBackend(BaseEmailBackend):
'async', 'ip_pool' 'async', 'ip_pool'
] ]
for attr in mandrill_attrs: for attr in mandrill_attrs:
if attr in self.global_settings:
api_params[attr] = self.global_settings[attr]
if hasattr(message, attr): if hasattr(message, attr):
api_params[attr] = getattr(message, attr) api_params[attr] = getattr(message, attr)
@@ -270,14 +278,24 @@ class DjrillBackend(BaseEmailBackend):
msg_dict['subaccount'] = self.subaccount msg_dict['subaccount'] = self.subaccount
for attr in mandrill_attrs: for attr in mandrill_attrs:
if attr in self.global_settings:
msg_dict[attr] = self.global_settings[attr]
if hasattr(message, attr): if hasattr(message, attr):
msg_dict[attr] = getattr(message, attr) msg_dict[attr] = getattr(message, attr)
# Allow simple python dicts in place of Mandrill # Allow simple python dicts in place of Mandrill
# [{name:name, value:value},...] arrays... # [{name:name, value:value},...] arrays...
# Allow merge of global and per message global_merge_var, the former taking precedent
global_merge_vars = {}
if 'global_merge_vars' in self.global_settings:
global_merge_vars.update(self.global_settings['global_merge_vars'])
if hasattr(message, 'global_merge_vars'): if hasattr(message, 'global_merge_vars'):
global_merge_vars.update(message.global_merge_vars)
if global_merge_vars:
msg_dict['global_merge_vars'] = \ msg_dict['global_merge_vars'] = \
self._expand_merge_vars(message.global_merge_vars) self._expand_merge_vars(global_merge_vars)
if hasattr(message, 'merge_vars'): if hasattr(message, 'merge_vars'):
# For testing reproducibility, we sort the recipients # For testing reproducibility, we sort the recipients
msg_dict['merge_vars'] = [ msg_dict['merge_vars'] = [

View File

@@ -540,6 +540,133 @@ class DjrillMandrillFeatureTests(DjrillBackendMockAPITestCase):
self.message.send() self.message.send()
@override_settings(MANDRILL_SETTINGS={
'from_name': 'Djrill Test',
'important': True,
'track_opens': True,
'track_clicks': True,
'auto_text': True,
'auto_html': True,
'inline_css': True,
'url_strip_qs': True,
'tags': ['djrill'],
'preserve_recipients': True,
'view_content_link': True,
'tracking_domain': 'example.com',
'signing_domain': 'example.com',
'return_path_domain': 'example.com',
'google_analytics_domains': ['example.com/test'],
'google_analytics_campaign': ['UA-00000000-1'],
'metadata': ['djrill'],
'merge_language': 'mailchimp',
'global_merge_vars': {'TEST': 'djrill'},
'async': False,
'ip_pool': 'Pool1',
'invalid': 'invalid',
})
class DjrillMandrillGlobalFeatureTests(DjrillBackendMockAPITestCase):
"""Test Djrill backend support for global ovveride Mandrill-specific features"""
def setUp(self):
super(DjrillMandrillGlobalFeatureTests, self).setUp()
self.message = mail.EmailMessage('Subject', 'Text Body',
'from@example.com', ['to@example.com'])
def test_global_options(self):
"""Test that any global settings get passed through
"""
self.message.send()
self.assert_mandrill_called("/messages/send.json")
data = self.get_api_call_data()
self.assertEqual(data['message']['from_name'], 'Djrill Test')
self.assertTrue(data['message']['important'], True)
self.assertTrue(data['message']['track_opens'], True)
self.assertTrue(data['message']['track_clicks'], True)
self.assertTrue(data['message']['auto_text'], True)
self.assertTrue(data['message']['auto_html'], True)
self.assertTrue(data['message']['inline_css'], True)
self.assertTrue(data['message']['url_strip_qs'], True)
self.assertEqual(data['message']['tags'], ['djrill'])
self.assertTrue(data['message']['preserve_recipients'], True)
self.assertTrue(data['message']['view_content_link'], True)
self.assertEqual(data['message']['tracking_domain'], 'example.com')
self.assertEqual(data['message']['signing_domain'], 'example.com')
self.assertEqual(data['message']['return_path_domain'], 'example.com')
self.assertEqual(data['message']['google_analytics_domains'], ['example.com/test'])
self.assertEqual(data['message']['google_analytics_campaign'], ['UA-00000000-1'])
self.assertEqual(data['message']['metadata'], ['djrill'])
self.assertEqual(data['message']['merge_language'], 'mailchimp')
self.assertEqual(data['message']['global_merge_vars'],
[{'name': 'TEST', 'content': 'djrill'}])
self.assertFalse('merge_vars' in data['message'])
self.assertFalse('recipient_metadata' in data['message'])
# Options at top level of api params (not in message dict):
self.assertFalse('send_at' in data)
self.assertEqual(data['async'], False)
self.assertEqual(data['ip_pool'], 'Pool1')
# Option that shouldn't be added
self.assertFalse('invalid' in data['message'])
def test_global_options_override(self):
"""Test that manually settings options overrides global settings
"""
self.message.important = True
self.message.auto_text = True
self.message.auto_html = True
self.message.inline_css = True
self.message.preserve_recipients = True
self.message.view_content_link = False
self.message.tracking_domain = "click.example.com"
self.message.signing_domain = "example.com"
self.message.return_path_domain = "support.example.com"
self.message.subaccount = "marketing-dept"
self.message.async = True
self.message.ip_pool = "Bulk Pool"
self.message.send()
data = self.get_api_call_data()
self.assertEqual(data['message']['important'], True)
self.assertEqual(data['message']['auto_text'], True)
self.assertEqual(data['message']['auto_html'], True)
self.assertEqual(data['message']['inline_css'], True)
self.assertEqual(data['message']['preserve_recipients'], True)
self.assertEqual(data['message']['view_content_link'], False)
self.assertEqual(data['message']['tracking_domain'], "click.example.com")
self.assertEqual(data['message']['signing_domain'], "example.com")
self.assertEqual(data['message']['return_path_domain'], "support.example.com")
self.assertEqual(data['message']['subaccount'], "marketing-dept")
self.assertEqual(data['async'], True)
self.assertEqual(data['ip_pool'], "Bulk Pool")
def test_global_options_override_tracking(self):
"""Test that manually settings options overrides global settings
"""
self.message.track_opens = False
self.message.track_clicks = False
self.message.url_strip_qs = False
self.message.send()
data = self.get_api_call_data()
self.assertEqual(data['message']['track_opens'], False)
self.assertEqual(data['message']['track_clicks'], False)
self.assertEqual(data['message']['url_strip_qs'], False)
def test_global_merge(self):
# Test that global settings merge in
self.message.global_merge_vars = {'GREETING': "Hello"}
self.message.send()
data = self.get_api_call_data()
self.assertEqual(data['message']['global_merge_vars'],
[{'name': "GREETING", 'content': "Hello"},
{'name': 'TEST', 'content': 'djrill'}])
def test_global_merge_overwrite(self):
# Test that global merge settings are overwritten
self.message.global_merge_vars = {'TEST': "Hello"}
self.message.send()
data = self.get_api_call_data()
self.assertEqual(data['message']['global_merge_vars'],
[{'name': 'TEST', 'content': 'Hello'}])
@override_settings(EMAIL_BACKEND="djrill.mail.backends.djrill.DjrillBackend") @override_settings(EMAIL_BACKEND="djrill.mail.backends.djrill.DjrillBackend")
class DjrillImproperlyConfiguredTests(TestCase): class DjrillImproperlyConfiguredTests(TestCase):
"""Test Djrill backend without Djrill-specific settings in place""" """Test Djrill backend without Djrill-specific settings in place"""

View File

@@ -103,11 +103,25 @@ Some notes and limitations:
Mandrill-Specific Options Mandrill-Specific Options
------------------------- -------------------------
.. setting:: MANDRILL_SETTINGS
Most of the options from the Mandrill Most of the options from the Mandrill
`messages/send API <https://mandrillapp.com/api/docs/messages.html#method=send>`_ `messages/send API <https://mandrillapp.com/api/docs/messages.html#method=send>`_
`message` struct can be set directly on an :class:`~django.core.mail.EmailMessage` `message` struct can be set directly on an :class:`~django.core.mail.EmailMessage`
(or subclass) object: (or subclass) object:
Most of these options can be globally set in your project's :file:`settings.py`
using :setting:`MANDRILL_SETTINGS`. For Example::
MANDRILL_SETTINGS = {
'tracking_domain': 'example.com',
'track_opens': True,
}
.. note::
``merge_vars`` and ``recipient_metadata`` cannot be set globally. ``global_merge_vars`` is merged
(see :attribute:`global_merge_vars`)
.. These attributes are in the same order as they appear in the Mandrill API docs... .. These attributes are in the same order as they appear in the Mandrill API docs...
.. attribute:: important .. attribute:: important
@@ -201,6 +215,10 @@ Most of the options from the Mandrill
Merge data must be strings or other JSON-serializable types. Merge data must be strings or other JSON-serializable types.
(See :ref:`formatting-merge-data` for details.) (See :ref:`formatting-merge-data` for details.)
.. note::
If using :setting:`MANDRILL_SETTINGS` then the message ``dict`` will be merged and overwrite any duplicates.
.. attribute:: merge_vars .. attribute:: merge_vars
``dict``: per-recipient merge variables (most useful with :ref:`mandrill-templates`). The keys ``dict``: per-recipient merge variables (most useful with :ref:`mandrill-templates`). The keys