Django module to easily send templated emails using django templates, or using a transactional mail provider (mailchimp, silverpop, etc.)

Overview

Django-Templated-Email

GitterBadge PypiversionBadge PythonVersionsBadge LicenseBadge

Info: A Django oriented templated email sending class
Author: Bradley Whittington (http://github.com/bradwhittington, http://twitter.com/darb)
Tests: TravisBadge CoverageBadge

Overview

django-templated-email is oriented towards sending templated emails. The library supports template inheritance, adding cc'd and bcc'd recipients, configurable template naming and location.

The send_templated_email method can be thought of as the render_to_response shortcut for email.

Make sure you are reading the correct documentation:

develop branch: https://github.com/vintasoftware/django-templated-email/blob/develop/README.rst

stable pypi/master: https://github.com/vintasoftware/django-templated-email/blob/master/README.rst

Requirements

  • Python (3.6, 3.7, 3.8, 3.9)
  • Django (2.2, 3.1, 3.2)

We highly recommend and only officially support the latest patch release of each Python and Django series.

Getting going - installation

Installing:

pip install django-templated-email

You can add the following to your settings.py (but it works out the box):

TEMPLATED_EMAIL_BACKEND = 'templated_email.backends.vanilla_django.TemplateBackend'

# You can use a shortcut version
TEMPLATED_EMAIL_BACKEND = 'templated_email.backends.vanilla_django'

# You can also use a class directly
from templated_email.backends.vanilla_django import TemplateBackend
TEMPLATED_EMAIL_BACKEND = TemplateBackend

Sending templated emails

Example usage using vanilla_django TemplateBackend backend

Python to send mail:

from templated_email import send_templated_mail
send_templated_mail(
        template_name='welcome',
        from_email='[email protected]',
        recipient_list=['[email protected]'],
        context={
            'username':request.user.username,
            'full_name':request.user.get_full_name(),
            'signup_date':request.user.date_joined
        },
        # Optional:
        # cc=['[email protected]'],
        # bcc=['[email protected]'],
        # headers={'My-Custom-Header':'Custom Value'},
        # template_prefix="my_emails/",
        # template_suffix="email",
)

If you would like finer control on sending the email, you can use get_templated_email, which will return a django EmailMessage object, prepared using the vanilla_django backend:

from templated_email import get_templated_mail
get_templated_mail(
        template_name='welcome',
        from_email='[email protected]',
        to=['[email protected]'],
        context={
            'username':request.user.username,
            'full_name':request.user.get_full_name(),
            'signup_date':request.user.date_joined
        },
        # Optional:
        # cc=['[email protected]'],
        # bcc=['[email protected]'],
        # headers={'My-Custom-Header':'Custom Value'},
        # template_prefix="my_emails/",
        # template_suffix="email",
)

You can also cc and bcc recipients using cc=['[email protected]'].

Your template

The templated_email/ directory needs to be the templates directory.

The backend will look in my_app/templates/templated_email/welcome.email :

{% block subject %}My subject for {{username}}{% endblock %}
{% block plain %}
  Hi {{full_name}},

  You just signed up for my website, using:
      username: {{username}}
      join date: {{signup_date}}

  Thanks, you rock!
{% endblock %}

If you want to include an HTML part to your emails, simply use the 'html' block :

{% block html %}
  <p>Hi {{full_name}},</p>

  <p>You just signed up for my website, using:
      <dl>
        <dt>username</dt><dd>{{username}}</dd>
        <dt>join date</dt><dd>{{signup_date}}</dd>
      </dl>
  </p>

  <p>Thanks, you rock!</p>
{% endblock %}

The plain part can also be calculated from the HTML using html2text. If you don't specify the plain block and html2text package is installed, the plain part will be calculated from the HTML part. You can disable this behaviour in settings.py :

TEMPLATED_EMAIL_AUTO_PLAIN = False

You can also specify a custom function that converts from HTML to the plain part :

def convert_html_to_text(html):
    ...

TEMPLATED_EMAIL_PLAIN_FUNCTION = convert_html_to_text

You can globally override the template dir, and file extension using the following variables in settings.py :

TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/' #use '' for top level template dir, ensure there is a trailing slash
TEMPLATED_EMAIL_FILE_EXTENSION = 'email'

You can also set a value for template_prefix and template_suffix for every time you call send_templated_mail, if you wish to store a set of templates in a different directory. Remember to include a trailing slash.

Using with Django Anymail

Anymail integrates several transactional email service providers (ESPs) into Django, with a consistent API that lets you use ESP-added features without locking your code to a particular ESP. It supports Mailgun, Postmark, SendGrid, SparkPost and more.

You can use it with django-templated-email, just follow their instructions in their quick start to configure it.

Optionally you can use their custom EmailMessage class with django-templated-email by using the following settings:

# This replaces django.core.mail.EmailMessage
TEMPLATED_EMAIL_EMAIL_MESSAGE_CLASS='anymail.message.AnymailMessage'

# This replaces django.core.mail.EmailMultiAlternatives
TEMPLATED_EMAIL_EMAIL_MULTIALTERNATIVES_CLASS='anymail.message.AnymailMessage'

Inline images

You can add inline images to your email using the InlineImage class.

First get the image content from a file or a ImageField:

# From a file
with open('pikachu.png', 'rb') as pikachu:
  image = pikachu.read()

# From an ImageField
# Suppose we have this model
class Company(models.Model):
  logo = models.ImageField()

image = company.logo.read()

Then create an instance of InlineImage:

from templated_email import InlineImage

inline_image = InlineImage(filename="pikachu.png", content=image)

Now pass the object on the context to the template when you send the email.

send_templated_mail(template_name='welcome',
                    from_email='[email protected]',
                    recipient_list=['[email protected]'],
                    context={'pikachu_image': inline_image})

Finally in your template add the image on the html template block:

<img src="{{ pikachu_image }}">

Note: All InlineImage objects you add to the context will be attached to the e-mail, even if they are not used in the template.

Add link to view the email on the web

# Add templated email to INSTALLED_APPS
INSTALLED_APPS = [
  ...
  'templated_email'
]
# and this to your url patterns
url(r'^', include('templated_email.urls', namespace='templated_email')),
# when sending the email use the *create_link* parameter.
send_templated_mail(
    template_name='welcome', from_email='[email protected]',
    recipient_list=['[email protected]'],
    context={}, create_link=True)

And, finally add the link to your template.

<!-- With the 'if' the link will only appear on the email. -->
{% if email_uuid %}
  <!-- Note: you will need to add your site since you will need to access
             it from the email -->
  You can view this e-mail on the web here:
  <a href="http://www.yoursite.com{% url 'templated_email:show_email' uuid=email_uuid %}">
    here
  </a>
{% endif %}
Notes:
  • A copy of the rendered e-mail will be stored on the database. This can grow if you send too many e-mails. You are responsible for managing it.
  • If you use InlineImage all images will be uploaded to your media storage, keep that in mind too.

Class Based Views

It's pretty common for emails to be sent after a form is submitted. We include a mixin to be used with any view that inherit from Django's FormMixin.

In your view add the mixin and the usual Django's attributes:

from templated_email.generic_views import TemplatedEmailFormViewMixin

class AuthorCreateView(TemplatedEmailFormViewMixin, CreateView):
    model = Author
    fields = ['name', 'email']
    success_url = '/create_author/'
    template_name = 'authors/create_author.html'

By default the template will have the form_data if the form is valid or from_errors if the form is not valid in it's context.

You can view an example here

Now you can use the following attributes/methods to customize it's behavior:

Attributes:

templated_email_template_name (mandatory if you don't implement templated_email_get_template_names()):
String naming the template you want to use for the email. ie: templated_email_template_name = 'welcome'.
templated_email_send_on_success (default: True):
This attribute tells django-templated-email to send an email if the form is valid.
templated_email_send_on_failure (default: False):
This attribute tells django-templated-email to send an email if the form is invalid.
templated_email_from_email (default: settings.TEMPLATED_EMAIL_FROM_EMAIL):
String containing the email to send the email from.

Methods:

templated_email_get_template_names(self, valid) (mandatory if you don't set templated_email_template_name):
If the method returns a string it will use it as the template to render the email. If it returns a list it will send the email only with the first existing template.
templated_email_get_recipients(self, form) (mandatory):
Return the recipient list to whom the email will be sent to. ie:
def templated_email_get_recipients(self, form):
    return [form.data['email']]
templated_email_get_context_data(**kwargs) (optional):
Use this method to add extra data to the context used for rendering the template. You should get the parent class's context from calling super. ie:
def templated_email_get_context_data(self, **kwargs):
    context = super(ThisClassView, self).templated_email_get_context_data(**kwargs)
    # add things to context
    return context
templated_email_get_send_email_kwargs(self, valid, form) (optional):
Add or change the kwargs that will be used to send the e-mail. You should call super to get the default kwargs. ie:
def templated_email_get_send_email_kwargs(valid, form):
  kwargs = super(ThisClassView, self).templated_email_get_send_email_kwargs(valid, form)
  kwargs['bcc'] = ['[email protected]']
  return kwargs
templated_email_send_templated_mail(*args, **kwargs) (optional):
This method calls django-templated-email's send_templated_mail method. You could change this method to use a celery's task for example or to handle errors.

Future Plans

See https://github.com/vintasoftware/django-templated-email/issues?state=open

Using django_templated_email in 3rd party applications

If you would like to use django_templated_email to handle mail in a reusable application, you should note that:

  • Your calls to send_templated_mail should set a value for template_dir, so you can keep copies of your app-specific templates local to your app (although the loader will find your email templates if you store them in <your app>/templates/templated_email, if TEMPLATED_EMAIL_TEMPLATE_DIR has not been overridden)
  • If you do (and you should) set a value for template_dir, remember to include a trailing slash, i.e. 'my_app_email/'
  • The deployed app may use a different backend which doesn't use the django templating backend, and as such make a note in your README warning developers that if they are using django_templated_email already, with a different backend, they will need to ensure their email provider can send all your templates (ideally enumerate those somewhere convenient)

Notes on specific backends

Using vanilla_django

This is the default backend, and as such requires no special configuration, and will work out of the box. By default it assumes the following settings (should you wish to override them):

TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/' #Use '' for top level template dir
TEMPLATED_EMAIL_FILE_EXTENSION = 'email'

For legacy purposes you can specify email subjects in your settings file (but, the preferred method is to use a {% block subject %} in your template):

TEMPLATED_EMAIL_DJANGO_SUBJECTS = {
    'welcome':'Welcome to my website',
}

Additionally you can call send_templated_mail and optionally override the following parameters:

template_prefix='your_template_dir/'  # Override where the method looks for email templates (alternatively, use template_dir)
template_suffix='email'               # Override the file extension of the email templates (alternatively, use file_extension)
cc=['[email protected]']              # Set a CC on the mail
bcc=['[email protected]']             # Set a BCC on the mail
template_dir='your_template_dir/'     # Override where the method looks for email templates
connection=your_connection            # Takes a django mail backend connection, created using **django.core.mail.get_connection**
auth_user='username'                  # Override the user that the django mail backend uses, per **django.core.mail.send_mail**
auth_password='password'              # Override the password that the django mail backend uses, per **django.core.mail.send_mail**

Releasing a new version of this package:

Update CHANGELOG file.

Execute the following commands:

bumpversion [major,minor,patch]
python setup.py publish
git push origin --tags

Commercial Support

This library, as others, is used in projects of Vinta clients. We are always looking for exciting work, so if you need any commercial support, feel free to get in touch: [email protected]

Comments
  • Bump version number on PyPi with new Django 1.8 fix

    Bump version number on PyPi with new Django 1.8 fix

    Currently doing a "pip install django-templated-email" will break a Django 1.8 instance as the latest compatibility code hasn't been put into pypi.

    opened by bradbeattie 15
  • Template' object is not iterable

    Template' object is not iterable

    Hi, when I try to send a mail I got Template' object is not iterable

    I found in utils.py this part: for node in template

    but template is not a list. Instead I can fix and get app running if I make something like:

    for node in template.template.nodelist:

    It's my problem? Anyone else?

    Thanks.

    opened by acarmisc 12
  • Problem found when extending an email template

    Problem found when extending an email template

    When extending an email template I get an error, I think it's because the template doesn't have the plain/html blocks.... I'm having this error:

    UnboundLocalError at /checkout/thanks/ local variable 'e' referenced before assignment

    in vanilla_django.py on line 138: return e.extra_headers.get('Message-Id',None)

    opened by julian-amaya 12
  • Explicit template name for third party integration

    Explicit template name for third party integration

    I'm trying to use django-templated-email as a backed for a third party app that provides some default email templates. The usual method for html templates in apps tries to namespace itself like <app name>/my_template.html under the path <app name>/templates/<app name>/my_template.html, which can be found using the app directories template loader and thus the get_template function call.

    My problem is the implicit template path generation from TEMPLATED_EMAIL_FILE_EXTENSION and TEMPLATED_EMAIL_TEMPLATE_DIR settings. If the user changes these settings my pluggable app will break since I would place my templates according to the defaults into the following location <app name>/templates/templated_email/my_template.email. Therefore the user would either be stuck using default settings or copy/sylink templates to another app. Can you enlighten me as to why the default behavior doesn't just try to load the template.email file from regular template loaders? I think that naming the templates like <app name>/templates/<app name>/my_template.email as a non-enforced best practice would be fairly self-explanatory and then you can just pass os.path.join(<app_name>, my_template.email) as the template_name insend_templated_mail`.

    I understand that this might break backwards compatibility so perhaps we can add a kwarg to send_templated_mail called template that would just try to load the template as an explicit path for a loader and we can maintain both template_name and template as arguments that can be passed in.

    opened by yesimon 7
  • Use 3rd party package for rendering template blocks

    Use 3rd party package for rendering template blocks

    This is similar to #38, but actually uses a separate package (django-render-block). This is based on the snippets used to make Django-Block-Render, but updated and with a lot more features:

    • Tests
    • Supports Django 1.8/1.9/1.10
    • Set up to support more than just Django templates (I have partial support for Jinja2 as well)
    • pip installable (and on pypi)

    In full disclosure, the django-render-block package is mine.

    The single test added in this is pretty lame, but I wasn't sure what else to add. Suggestions are welcome! (Note the tests will pass without the change here. :)) If there's a particular behavior you want tested in terms of template inheritance, etc. they'd probably make more sense as part of the django-render-block repo.

    Fixes #28 Fixes #46

    opened by clokep 6
  • Can't use a custom connection/EmailBackend when using django's mail sender (and consequently set auth_user/password per mail)

    Can't use a custom connection/EmailBackend when using django's mail sender (and consequently set auth_user/password per mail)

    Hi -

    When sending out an email with eg this code:

    send_templated_mail(
            template_name='error-in-validation',
            from_email='[email protected]',
            recipient_list=['[email protected]'],
            context={
                'key': key
            },
        )
    

    the from_email is overwritten with my EMAIL_HOST_USER setting. In Django, while sending a message, it's possible to give extra parameters (auth_user and auth_password) to override the default settings. Is this possible with django-templated-email?

    Thanks!

    opened by LaundroMat 6
  • The subject block cannot be overwrite when inherit the email template.

    The subject block cannot be overwrite when inherit the email template.

    Is the subject block treated specially and did not get into the Django template inheritance process? I had to use this work around that is put this in my base.email {% block subject %}{{ subject }}{% endblock %}

    And every time when call send email, the context need to have the subject line.

    opened by sunshineo 5
  • Backend shortcuts

    Backend shortcuts

    TEMPLATED_EMAIL_BACKEND = 'templated_email.backends.vanilla_django.TemplateBackend' is more than 80 chars length. It would be nice to have some sort of shortcut for this :)

    opened by zerko 5
  • Auto-escape only the HTML part

    Auto-escape only the HTML part

    This PR enables auto-escaping on the HTML part but not on the plain text and subject parts. It fixes #108, fixes #109, and closes #111 with a simpler alternative that doesn't rely on html.parser.

    It relies on https://github.com/clokep/django-render-block/pull/21, that's why I bumped the requirement to django-render-block==0.8.

    opened by bblanchon 4
  • Strip whitespace out of email subject

    Strip whitespace out of email subject

    Templates often add a lots of whitespace around content. While this is not a thing for web browsers, email client shows whitespace in subject. Keeping template clean of whitespace is not an option since most of IDE would like to reformat template with indentation.

    opened by xy2 4
  • Migrating the project

    Migrating the project

    Even though I have permission to commit in this repository I don't have permission to publish it in pypi. We lost touch with the old developer @BradWhittington .

    I will leave this issue open for a few days and if there is no objection we will create a new Pypi package and migrate the project there, that's the only way to go forward with the project.

    opened by aericson 4
  • [FEATURE SUGGESTION] Provide an admin interface for templates

    [FEATURE SUGGESTION] Provide an admin interface for templates

    Thanks for maintaining this repo! I have a feature suggestion that would really help some nontechnical members of my team.

    A really nice feature to have would be an admin interface for non-technical users to view templates and, ideally using a WYSIWYG editor, edit the templates.

    For templates built in a html file, providing a read-only admin interface would be nice as well, including the template as well as the to, from, subject, etc. fields that are part of the email.

    Is this something that would be a welcome addition? Any thoughts on whether this would be reasonably doable? For a WYSIWYG editor it would likely mean storing those templates that use WYSIWYG in the database.

    Thanks again fro maintaining django templated email, and for considering this!

    opened by YPCrumble 1
  • Allow empty from_email param

    Allow empty from_email param

    Resolves #97

    The context and recipient_listparams also had to be set as default=None otherwise it wouldn't be possible to set from_email=None.

    It doesn't change the order of the params, so it's not a breaking change.

    It also removes the empty context params {} which are not required anymore.

    opened by tuliolages 1
Releases(3.0.1)
Owner
Vinta Software
Python, Django and React Experts
Vinta Software
send email & telegram message whenever an analog in is recieved

send email & telegram message whenever an analog in is recieved (so when attached to an alarm siren out it will alert via mail)

Naor Livne 2 Feb 11, 2022
Send e-mails asyncronously using cron

django-yubin Django Yubin allows the programmer to control when he wants to send the e-mail in this application, making the web application to answer

APSL 44 Sep 24, 2022
Secret Service Email Encryption/Steganography

SecretService Decoy Encrypted Emailer

Unit 221B 6 Aug 05, 2022
Simple, powerfull and nonobstructive django email middleware.

djmail djmail is a BSD Licensed, simple and nonobstructive django email middleware. Why use djmail? Because it: Sends emails asynchronously without ad

David Barragán Merino 77 Aug 30, 2021
this is django project through this project you can easily sends message to any email

SEND-EMAIL this is django project through this project you can easily sends message to any email home when you run the server then you will see this t

Ankit jadhav 1 Oct 17, 2021
Esio_dev 3 Oct 15, 2021
Django email backends and webhooks for Amazon SES, Mailgun, Mailjet, Postmark, SendGrid, Sendinblue, SparkPost and more

Django email backends and webhooks for Amazon SES, Mailgun, Mailjet, Postmark, SendGrid, Sendinblue, SparkPost and more

1.4k Jan 01, 2023
You take an email and password from the combo list file and check it on mail.com

Brute-Force-mail tool information: Combo Type: email:pass Domains: All domains of the site Url: https://www.mail.com Api: ☑️ Proxy: No ☑️ The correct

6 Jun 05, 2022
SMTP In some vulnerable configurations, email servers can also be aggregated Use information that gives us information about the host or network Give

SMTP In some vulnerable configurations, email servers can also be aggregated Use information that gives us information about the host or network Give. The SMTP protocol supports some basic commands s

m3hr44n 1 Jan 16, 2022
Convert emails without attachments to pdf and send as email

Email to PDF to email This script will check an imap folder for unread emails. Any unread email that does not have an attachment will be converted to

Robert Luke 21 Nov 22, 2022
An automation program that checks whether email addresses are real, whether they exist and whether they are a validated mail

Email Validator It is an automation program that checks whether email addresses are real, whether they exist and whether they are a validated mail. Re

Ender MIRIZ 4 Dec 22, 2021
A Django email backend that uses a celery task for sending the email.

django-celery-email - A Celery-backed Django Email Backend A Django email backend that uses a Celery queue for out-of-band sending of the messages. Wa

Paul McLanahan 430 Dec 16, 2022
Mail-Checker is a python script that lets you see your mails directly from the terminal without having to login each time.

Mail-Checker ##Mail-Checker is a python script that lets you see your mails directly from the terminal without having to login each time. ##Before you

Siddharth Pradeep 1 Jan 12, 2022
Email-osint - Email OSINT tool written in python3

Email-osint - Email OSINT tool written in python3

Surtains 7 Nov 28, 2022
Temp-SMS-Receive - A Program Which Allows You To Receive Temp SMS

Welcome to Temp-SMS-Receive 👋 A Program Which Allows You To Receive Temp SMS AP

Sandaru Ashen Fernando 21 Dec 10, 2022
PGP encrypted / multipart templated emails for Django

Created by Stephen McDonald Introduction django-email-extras is a Django reusable app providing the ability to send PGP encrypted and multipart emails

stephenmcd 75 May 14, 2022
Send Emails through the terminal , fast and secure

Send Emails through the terminal , fast and secure

11 Aug 07, 2022
Disposable Temporary Email (Python Library)

Disposable Temporary Email (Python Library)

krypton 13 Nov 24, 2022
Spam-bot - Simple email-spammer discord bot

📝 Functional [ ✔️ ] Premium system via .json [ ✔️ ] Spammer [ ✔️ ] Validater [ ✔️ ] Discord bot ❓ How to launch ➡️ 1) Make discord bot ➡️ 2) Paste to

1 Feb 18, 2022
Python Email Sender (PES) is a program made with Python using smtplib, socket and tkinter.

Python Email Sender (PES) is a program made with Python using smtplib, socket and tkinter. This program was made for sender email to be a gmail account because that's what I used when testing it out,

Zacky2613 1 Aug 26, 2022