Repository: Stranger6667/postmarker
Pull request #63 (2016-10-27 18:56:35)

Tags for Django messages.

codecov-io: ## [Current coverage](https://codecov.io/gh/Stranger6667/postmarker/pull/63?src=pr) is 100% (diff: 100%)
> Merging [#63](https://codecov.io/gh/Stranger6667/postmarker/pull/63?src=pr) into [master](https://codecov.io/gh/Stranger6667/postmarker/branch/master?src=pr) will not change coverage

```diff
@@           master   #63   diff @@
===================================
  Files          13    13          
  Lines         414   428    +14   
  Methods         0     0          
  Messages        0     0          
  Branches       45    45          
===================================
+ Hits          414   428    +14   
  Misses          0     0          
  Partials        0     0          
```

> Powered by [Codecov](https://codecov.io?src=pr). Last update [066e5e3...a3a0d53](https://codecov.io/gh/Stranger6667/postmarker/compare/066e5e39ba00a096b9fbf3835ac62cdad0449626...a3a0d53f171f9d80b6c232b1cf63b81f07ce8fff?src=pr)

Patch:
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 414017b..4bce3e0 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -3,6 +3,11 @@
 Changelog
 =========
 
+0.5.3 - TBD
+-----------
+
+- Tags for Django messages. `#59`_
+
 0.5.2 - 27.10.2016
 ------------------
 
@@ -66,6 +71,7 @@ Changelog
 
 
 .. _#60: https://github.com/Stranger6667/postmarker/issues/60
+.. _#59: https://github.com/Stranger6667/postmarker/issues/59
 .. _#55: https://github.com/Stranger6667/postmarker/issues/55
 .. _#51: https://github.com/Stranger6667/postmarker/issues/51
 .. _#46: https://github.com/Stranger6667/postmarker/issues/46
diff --git a/docs/django.rst b/docs/django.rst
index 46ff223..2ed075a 100644
--- a/docs/django.rst
+++ b/docs/django.rst
@@ -44,6 +44,20 @@ When it is set to ``True`` all interactions will be conducted with a special tes
 
 To globally turn on ``TrackOpens`` feature, set ``TRACK_OPENS`` to ``True``.
 
+To mark messages with tags you could use ``postmarker.django.PostmarkEmailMessage`` /  ``postmarker.django.PostmarkEmailMultiAlternatives``
+instead of ``EmailMessage`` / ``EmailMultiAlternatives`` from Django.
+Example:
+
+.. code-block:: python
+
+    >>> from postmarker.django import PostmarkEmailMessage
+    >>> PostmarkEmailMessage(
+        'Subject', 'Body', 'sender@example.com', ['receiver@example.com'],
+        tag='Test tag'
+    ).send()
+
+You can get the same feature for your own classes with ``PostmarkEmailMixin``.
+
 Known issues
 ~~~~~~~~~~~~
 
diff --git a/postmarker/django.py b/postmarker/django.py
index 201dffc..9cedede 100644
--- a/postmarker/django.py
+++ b/postmarker/django.py
@@ -3,6 +3,7 @@ from __future__ import absolute_import
 
 from django.conf import settings
 from django.core.exceptions import ImproperlyConfigured
+from django.core.mail import EmailMessage, EmailMultiAlternatives
 from django.core.mail.backends.base import BaseEmailBackend
 
 from .core import TEST_TOKEN, PostmarkClient
@@ -52,7 +53,7 @@ class EmailBackend(BaseEmailBackend):
     def send_messages(self, email_messages):
         try:
             client_created = self.open()
-            prepared_messages = [message.message() for message in email_messages]
+            prepared_messages = [self.prepare_message(message) for message in email_messages]
             response = self.client.emails.send_batch(*prepared_messages, TrackOpens=self.get_option('TRACK_OPENS'))
             msg_count = len(response)
             if client_created:
@@ -61,3 +62,26 @@ class EmailBackend(BaseEmailBackend):
         except Exception:
             if not self.fail_silently:
                 raise
+
+    def prepare_message(self, message):
+        instance = message.message()
+        instance.tag = getattr(message, 'tag', None)
+        return instance
+
+
+class PostmarkEmailMixin(object):
+    """
+    Provides an ability to set tags on Django email instances.
+    """
+
+    def __init__(self, *args, **kwargs):
+        self.tag = kwargs.pop('tag', None)
+        super(PostmarkEmailMixin, self).__init__(*args, **kwargs)
+
+
+class PostmarkEmailMessage(PostmarkEmailMixin, EmailMessage):
+    pass
+
+
+class PostmarkEmailMultiAlternatives(PostmarkEmailMixin, EmailMultiAlternatives):
+    pass
diff --git a/postmarker/models/emails.py b/postmarker/models/emails.py
index 3e87eb1..f235a72 100644
--- a/postmarker/models/emails.py
+++ b/postmarker/models/emails.py
@@ -175,8 +175,9 @@ class Email(BaseEmail):
         cc = prepare_header(message['Cc'])
         bcc = prepare_header(message['Bcc'])
         reply_to = prepare_header(message['Reply-To'])
+        tag = getattr(message, 'tag', None)
         return cls(manager=manager, From=sender, To=to, TextBody=text, HtmlBody=html, Subject=subject, Cc=cc, Bcc=bcc,
-                   ReplyTo=reply_to, Attachments=attachments)
+                   ReplyTo=reply_to, Attachments=attachments, Tag=tag)
 
     def send(self):
         return self._manager._send(**self.as_dict())


Test patch:
diff --git a/tests/django/test_backend.py b/tests/django/test_backend.py
index b034439..e4b04e8 100644
--- a/tests/django/test_backend.py
+++ b/tests/django/test_backend.py
@@ -40,6 +40,7 @@ def test_send_mail(patched_request, settings):
         'Attachments': [],
         'TextBody': 'Here is the message.',
         'HtmlBody': None,
+        'Tag': None,
         'TrackOpens': False,
         'From': 'sender@example.com'
     }, )
@@ -77,6 +78,7 @@ def test_send_mail_html_message(patched_request):
         'TextBody': 'Here is the message.',
         'HtmlBody': '<html></html>',
         'TrackOpens': False,
+        'Tag': None,
         'From': 'sender@example.com'
     }, )
 
@@ -107,6 +109,7 @@ def test_extra_options(settings, patched_request):
         'Attachments': [],
         'TextBody': 'Here is the message.',
         'HtmlBody': None,
+        'Tag': None,
         'TrackOpens': True,
         'From': 'sender@example.com'
     },)
@@ -126,6 +129,7 @@ def test_context_manager(patched_request):
         'Attachments': [],
         'TextBody': 'Body',
         'HtmlBody': None,
+        'Tag': None,
         'TrackOpens': True,
         'From': 'sender@example.com'
     },)
diff --git a/tests/django/test_mixins.py b/tests/django/test_mixins.py
new file mode 100644
index 0000000..728ed55
--- /dev/null
+++ b/tests/django/test_mixins.py
@@ -0,0 +1,33 @@
+# coding: utf-8
+import pytest
+from django.core.mail import EmailMultiAlternatives
+
+from postmarker.django import PostmarkEmailMixin
+
+
+pytestmark = pytest.mark.usefixtures('outbox')
+
+
+class TaggedEmail(PostmarkEmailMixin, EmailMultiAlternatives):
+    pass
+
+
+def test_tags(patched_request):
+    TaggedEmail(
+        'Subject', 'Body', 'sender@example.com', ['receiver@example.com'],
+        tag='Test tag'
+    ).send()
+    assert patched_request.call_args[1]['json'][0] == {
+        'ReplyTo': None,
+        'Subject': 'Subject',
+        'To': 'receiver@example.com',
+        'Bcc': None,
+        'Headers': [],
+        'Cc': None,
+        'Attachments': [],
+        'TextBody': 'Body',
+        'HtmlBody': None,
+        'TrackOpens': True,
+        'Tag': 'Test tag',
+        'From': 'sender@example.com'
+    }
diff --git a/tests/models/test_emails.py b/tests/models/test_emails.py
index 0d86058..eee9205 100644
--- a/tests/models/test_emails.py
+++ b/tests/models/test_emails.py
@@ -166,6 +166,7 @@ class TestSimpleSend:
             'ReplyTo': 'replyto@example.com',
             'Subject': 'Test subject',
             'TextBody': 'Text',
+            'Tag': None,
             'To': 'receiver@example.com'
         }