MailViews
=========

Introduction
------------

Rendering and sending emails in Django can quickly become repetitive and
error-prone. By encapsulating message rendering within view classes, you can
easily compose messages in a structured and clear manner.

Basic Usage
-----------

.. code:: python

    from mailviews.messages import TemplatedEmailMessageView

    # Subclass the `TemplatedEmailMessageView`, adding the templates you want to render.
    class WelcomeMessageView(EmailMessageView):
        subject_template_name = 'emails/welcome/subject.txt'
        body_template_name = 'emails/welcome/body.txt'

    # Instantiate and send a message.
    message = WelcomeMessageView().send(extra_context={
        'user': user,
    }, to=(user.email,))

This isn't actually the best pattern for sending messages to a user -- read the
notes under "Best Practices" for a better approach.

Best Practices
--------------

* Try and avoid using the ``extra_context`` argument when sending emails.
  Instead, create an ``TemplatedEmailMessageView`` subclass whose constructor accepts
  as arguments all of the objects that you require to generate the context and
  send the message. For example, the code shown in "Basic Usage" could written
  instead as the following:

.. code:: python

    from mailviews.messages import TemplatedEmailMessageView

    class WelcomeMessageView(EmailMessageView):
        subject_template_name = 'emails/welcome/subject.txt'
        body_template_name = 'emails/welcome/body.txt'

        def __init__(self, user, *args, **kwargs):
            super(WelcomeMessageView, self).__init__(*args, **kwargs)
            self.user = user

        def get_context_data(self, **kwargs):
            context = super(WelcomeMessageView, self).get_context_data(**kwargs)
            context['user'] = self.user
            return context

        def render_to_message(self, *args, **kwargs):
            assert 'to' not in kwargs  # this should only be sent to the user
            kwargs['to'] = (self.user.email,)
            return super(WelcomeMessageView, self).render_to_message(*args, **kwargs)

    # Instantiate and send a message.
    WelcomeMessageView(user).send()

In fact, you might find it helpful to encapsulate the above "message for a user"
pattern into a mixin or subclass that provides a standard abstraction for all
user-related emails.