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
A python mailserver meant for friends who value privacy and a hard to use interface....

python-mail A python mailserver meant for friends who value privacy and a hard to use interface.... Basic info This mailserver was just a random proje

Hashm 2 Jan 19, 2022
Send email in Python conveniently for gmail using yagmail

yagmail -- Yet Another GMAIL/SMTP client For the asynchronous asyncio version, look here: https://github.com/kootenpv/aioyagmail The goal here is to m

Pascal van Kooten 2.4k Dec 31, 2022
A news curator and newsletter subscription package for Django

django-newsfeed What is django-newsfeed? django-newsfeed is a news curator and newsletter subscription package for django. It can be used to create a

Maksudul Haque 179 Nov 14, 2022
A Django app that allows you to send email asynchronously in Django. Supports HTML email, database backed templates and logging.

Django Post Office Django Post Office is a simple app to send and manage your emails in Django. Some awesome features are: Allows you to send email as

User Inspired 856 Dec 25, 2022
Automatically Send Custom Named Certificates via Mail

Welcome to Certificate Launchpad 🚀 Automatically Send Custom Named Certificates via Email Intro After any event, sending certificates to attendees or

Dc7 16 Oct 16, 2022
Using this repository you can send mails to multiple recipients.Was created in support of Ukraine, to turn society`s attention to war.

mails-in-support-of-UA Using this repository you can send mails to multiple recipients.Was created in support of Ukraine, to turn society`s attention

Oleksii Budzinskiy 2 Mar 04, 2022
A functional demo of the O365 Module to send an email on an authenticated, tokenized account.

O365_email A functional demo of the O365 Module to send an email on an authenticated, tokenized account. Prep Create an app in Azure Developer's porta

2 Oct 14, 2022
Search email inbox with python and filter with search criteria via IMAP4 and fastapi or console

Search email inbox with python and filter with search criteria via IMAP4 and fastapi or console

Karma Computing 0 Sep 07, 2021
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
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
Mail hosting made simple

Modoboa Modoboa is a mail hosting and management platform including a modern and simplified Web User Interface. It provides useful components such as

Modoboa 2.4k Jan 03, 2023
Tempmail API aswell as a SMTP server.

Tempmail API/Server Tempmail API aswell as a SMTP server. Website · Report Bug · Request Feature Setup Firstly create a mongodb account, and proceed t

femboy.party 16 Mar 09, 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
GMailBomber is a form of Internet abuse which is perpetrated through the sending of massive volumes of email to a specific email address with the goal of overflowing the mailbox and overwhelming the mail server hosting the address, making it into some form of denial of service attack.

GMailBomber is a form of Internet abuse which is perpetrated through the sending of massive volumes of email to a specific email address with the goal of overflowing the mailbox and overwhelming the

Muneeb 5 Nov 13, 2022
check disk storage's amount and if necessary, send alert message by email

DiskStorageAmountChecker What is this script? (このスクリプトは何ですか?) This script check disk storage's available amount of specified servers and send alerting

Hajime Kurita 1 Oct 22, 2021
An API to send emails through python3's smtplib module.

An API to send emails through python3's smtplib module. Just configure your SMTP server credentials and you are ready to send a lot of emails through API, designed to be used as a newsletter service.

Adnan Ahmad 15 Nov 24, 2022
Django module to easily send templated emails using django templates, or using a transactional mail provider (mailchimp, silverpop, etc.)

Django-Templated-Email Info: A Django oriented templated email sending class Author: Bradley Whittington (http://github.com/bradwhittington, http://tw

Vinta Software 659 Dec 27, 2022
spam_box is a self hosted temp mail service by hacksec

spam_box spam_box is a self hosted temp mail service by hacksec Requirement python3 open port 25 and 6660 root access in a vps How to install in linux

ScRiPt1337 25 Dec 14, 2022
Python script for imap, pop3, smtp and IPv4 analyze

Python script for imap, pop3, smtp and IPv4 analyze

Vladislav Kotletkin 1 Jan 30, 2022
Mailer is python3 script use for sending spear-phishing to target email...It was created by Spider Anongreyhat

Mailer Mailer is a python3 script. It's used for sending spear-phishing to target email...It was created by Spider Anongreyhat Screenshots Installatio

Spider Anongreyhat 31 Dec 05, 2022