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

This is useful to set options such as tracking_domain etc per instance when using subaccounts with Mandrill.
This commit is contained in:
William Hector
2015-07-12 01:19:59 +01:00
parent bac85511b5
commit 883b23362c
3 changed files with 140 additions and 0 deletions

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,11 +278,16 @@ 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...
if 'global_merge_vars' in self.global_settings:
msg_dict['global_merge_vars'] = self._expand_merge_vars(
self.global_settings['global_merge_vars'])
if hasattr(message, 'global_merge_vars'): if hasattr(message, '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(message.global_merge_vars)

View File

@@ -540,6 +540,123 @@ 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):
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"}])
@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,21 @@ 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,
}
.. 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