django-templated-email

repository·develop·Indexed 21 days ago

https://github.com/vintasoftware/django-templated-email

A Django library for simplifying the process of sending templated emails. It supports template inheritance, multi-part (plain/HTML) emails, and inline images. Key features include the send_templated_mail shortcut, get_templated_mail for EmailMessage objects, a TemplatedEmailFormViewMixin for class-based views, and a web interface for viewing rendered emails. It also integrates with django-anymail and provides a sendtesttemplatedemail management command for testing.

Tokens
4.7K
Snippets
14
Records
16
Agent score
24%

What's inside django-templated-email

  1. Create email templates

    develop

    Templates are expected to be located in your app's template directory under a templated_email/ subdirectory (e.g., my_app/templates/templated_email/welcome.email).

    Use Django template blocks to define different parts of the email:

    • {% block subject %}: The email subject line.
    • {% block plain %}: The plain-text version of the email.
    • {% block html %}: The HTML version of the email.

    If you provide an html block but no plain block, the library will attempt to generate the plain text from the HTML using the html2text package if it is installed.

    {% block subject %}My subject for {{username}}{% endblock %}
    
    {% block plain %}
      Hi {{full_name}},
      You just signed up!
    {% endblock %}
    
    {% block html %}
      <p>Hi {{full_name}},</p>
      <p>You just signed up!</p>
    {% endblock %}
  2. Integrate with Django Anymail

    develop

    To use django-templated-email with django-anymail, follow the Anymail quickstart to configure your ESP. To leverage Anymail's specific features (like AnymailMessage), update your settings to replace the default Django email classes:

    TEMPLATED_EMAIL_EMAIL_MESSAGE_CLASS = 'anymail.message.AnymailMessage'
    TEMPLATED_EMAIL_EMAIL_MULTIALTERNATIVES_CLASS = 'anymail.message.AnymailMessage'
    TEMPLATED_EMAIL_EMAIL_MESSAGE_CLASS = 'anymail.message.AnymailMessage'
    TEMPLATED_EMAIL_EMAIL_MULTIALTERNATIVES_CLASS = 'anymail.message.AnymailMessage'
  3. Use TemplatedEmailFormViewMixin with Django Class-Based Views

    develop

    To send emails automatically after a form submission in a Django view, use the TemplatedEmailFormViewMixin. This mixin is designed to work with views that inherit from Django's FormMixin (like CreateView or UpdateView).

    By default, the email template context will include form_data if the form is valid, or form_errors if the form is invalid.

    To implement the mixin, you must provide a way to identify recipients and a template name (or a method to retrieve template names).

    from templated_email.generic_views import TemplatedEmailFormViewMixin
    from django.views.generic import CreateView
    
    class AuthorCreateView(TemplatedEmailFormViewMixin, CreateView):
        model = Author
        fields = ['name', 'email']
        success_url = '/create_author/'
        template_name = 'authors/create_author.html'
    
        # Mandatory: define who receives the email
        def templated_email_get_recipients(self, form):
            return [form.data['email']]
    
        # Mandatory if templated_email_template_name is not set
        # def templated_email_get_template_names(self, valid):
        #     return 'welcome'
  4. Install django-templated-email

    develop

    Install the package using pip:

    pip install django-templated-email

    Configuration

    By default, the library works out of the box, but you can explicitly set the backend in your settings.py using any of the following methods:

    1. String path (recommended): TEMPLATED_EMAIL_BACKEND = 'templated_email.backends.vanilla_django.TemplateBackend'
    2. Shortcut string: TEMPLATED_EMAIL_BACKEND = 'templated_email.backends.vanilla_django'
    3. Direct class import:
      from templated_email.backends.vanilla_django import TemplateBackend
      TEMPLATED_EMAIL_BACKEND = TemplateBackend
    pip install django-templated-email
  5. View emails on the web

    develop

    You can enable a feature to view a rendered copy of the email in a web browser.

    1. Add 'templated_email' to your INSTALLED_APPS.
    2. Include the library's URLs in your project's urls.py: path('', include('templated_email.urls', namespace='templated_email')).
    3. When calling send_templated_mail, set create_link=True.
    4. In your template, use the email_uuid variable to generate a link to the web view.

    Note: A copy of the rendered email is stored in your database. You are responsible for managing this storage growth.

    # urls.py
    from django.urls import path, include
    
    urlpatterns = [
        path('', include('templated_email.urls', namespace='templated_email')),
    ]
    
    # Sending the mail
    send_templated_mail(
        template_name='welcome', 
        from_email='from@example.com',
        recipient_list=['to@example.com'],
        context={}, 
        create_link=True
    )
    
    # In template
    {% if email_uuid %}
      <a href="http://www.yoursite.com{% url 'templated_email:show_email' uuid=email_uuid %}">
        view this e-mail on the web
      </a>
    {% endif %}
  6. Add inline images to emails

    develop

    To include images directly in the email body, use the InlineImage class.

    1. Read the image content (from a file or a Django ImageField).
    2. Create an InlineImage instance with a filename and content.
    3. Pass the InlineImage object into the email context.
    4. In your HTML template, use the object directly in an <img> tag.

    Note: All InlineImage objects in the context will be attached to the email, even if they aren't used in the template. These images are uploaded to your media storage.

    from templated_email import InlineImage
    
    # 1. Get content
    with open('pikachu.png', 'rb') as f:
        image_data = f.read()
    
    # 2. Create InlineImage
    inline_image = InlineImage(filename="pikachu.png", content=image_data)
    
    # 3. Pass to context
    send_templated_mail(
        template_name='welcome',
        from_email='from@example.com',
        recipient_list=['to@example.com'],
        context={'pikachu_image': inline_image}
    )
    
    # 4. In template HTML block:
    # <img src="{{ pikachu_image }}">
  7. Configure template directory and extension

    develop

    You can globally override the template directory and file extension in your settings.py:

    • TEMPLATED_EMAIL_TEMPLATE_DIR: The directory to look in (ensure it has a trailing slash; use '' for the top-level template directory).
    • TEMPLATED_EMAIL_FILE_EXTENSION: The file extension used for templates (e.g., 'email').

    Additionally, you can control plain-text generation:

    • TEMPLATED_EMAIL_AUTO_PLAIN: Set to False to disable automatic HTML-to-text conversion.
    • TEMPLATED_EMAIL_PLAIN_FUNCTION: Set to a custom function that converts HTML to text.
    TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/'
    TEMPLATED_EMAIL_FILE_EXTENSION = 'email'
    TEMPLATED_EMAIL_AUTO_PLAIN = False
    
    def convert_html_to_text(html):
        # custom logic
        pass
    
    TEMPLATED_EMAIL_PLAIN_FUNCTION = convert_html_to_text
  8. Configure Django-Templated-Email settings

    develop

    Configure the library behavior in your Django settings.py using the following keys:

    TEMPLATED_EMAIL_FROM_EMAIL = None                 # Sender email address
    TEMPLATED_EMAIL_BACKEND = TemplateBackend         # Backend class (string path or class reference)
    TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/' # Directory for templates
    TEMPLATED_EMAIL_FILE_EXTENSION = 'email'          # Template file extension
    TEMPLATED_EMAIL_AUTO_PLAIN = True                 # If True, calculates plain text from HTML using html2text
    TEMPLATED_EMAIL_PLAIN_FUNCTION = None             # Custom function for HTML to plain conversion
    
    # Anymail integration settings
    TEMPLATED_EMAIL_EMAIL_MESSAGE_CLASS = 'django.core.mail.EmailMessage'
    TEMPLATED_EMAIL_EMAIL_MULTIALTERNATIVES_CLASS = 'django.core.mail.EmailMultiAlternatives'
  9. Send templated emails with send_templated_mail

    develop

    Use send_templated_mail as a shortcut to render a template and send an email immediately. It is similar to Django's render_to_response but for emails.

    Parameters:

    • template_name: The name of the template (without extension).
    • from_email: The sender's email address.
    • recipient_list: A list of recipient email addresses.
    • context: A dictionary of variables to pass to the template.
    • cc (optional): List of CC recipients.
    • bcc (optional): List of BCC recipients.
    • headers (optional): Dictionary of custom email headers.
    • template_prefix (optional): Directory prefix for templates (must end with /).
    • template_suffix (optional): File suffix for templates.
    from templated_email import send_templated_mail
    
    send_templated_mail(
        template_name='welcome',
        from_email='from@example.com',
        recipient_list=['to@example.com'],
        context={
            'username': request.user.username,
            'full_name': request.user.get_full_name(),
            'signup_date': request.user.date_joined
        },
        # Optional:
        # cc=['cc@example.com'],
        # bcc=['bcc@example.com'],
        # headers={'My-Custom-Header': 'Custom Value'},
        # template_prefix="my_emails/",
        # template_suffix="email",
    )
  10. Override parameters in send_templated_mail

    develop

    When calling send_templated_mail directly, you can override several default parameters to customize the specific email being sent.

    from templated_email import send_templated_mail
    
    send_templated_mail(
        template_name='welcome',
        recipient_list=['user@example.com'],
        from_email='your.email@com/',          # Override sender
        template_prefix='your_template_dir/',  # Override template search path
        template_suffix='email',              # Override file extension
        cc=['fubar@example.com'],             # Add CC
        bcc=['fubar@example.com'],            # Add BCC
        template_dir='your_template_dir/',   # Override template directory
        connection=your_connection,            # Django mail backend connection
        auth_user='username',                 # Auth user for backend
        auth_password='password'               # Auth password for backend
    )
  11. Customize TemplatedEmailFormViewMixin behavior

    develop

    When using TemplatedEmailFormViewMixin, you can override several attributes and methods to control how and when emails are sent.

    Attributes

    • templated_email_template_name (str): The name of the template to use (e.g., 'welcome'). Mandatory if templated_email_get_template_names() is not implemented.
    • templated_email_send_on_success (bool): Whether to send the email if the form is valid. Defaults to True.
    • templated_email_send_on_failure (bool): Whether to send the email if the form is invalid. Defaults to False.
    • templated_email_from_email (str): The sender email address. Falls back to settings.TEMPLATED_EMAIL_FROM_EMAIL or DEFAULT_FROM_EMAIL.

    Methods

    • templated_email_get_template_names(self, valid): Returns a string (single template) or a list (uses the first existing template in the list). Mandatory if templated_email_template_name is not set.
    • templated_email_get_recipients(self, form): Mandatory. Returns the list of recipient email addresses.
    • templated_email_get_context_data(**kwargs): Optional. Add extra data to the template context. Always call super().templated_email_get_context_data(**kwargs) to preserve default context.
    • templated_email_get_send_email_kwargs(self, valid, form): Optional. Add or modify kwargs used by the mail sending process (e.g., adding bcc). Call super() to get defaults.
    • templated_email_send_templated_mail(*args, **kwargs): Optional. Override to change how the mail is dispatched (e.g., offloading to a Celery task).