Giter Site home page Giter Site logo

vintasoftware / django-templated-email Goto Github PK

View Code? Open in Web Editor NEW
697.0 53.0 130.0 284 KB

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

License: MIT License

Python 99.89% HTML 0.11%

django-templated-email's Introduction

Django-Templated-Email

GitterBadge PypiversionBadge PythonVersionsBadge LicenseBadge

Info:A Django oriented templated email sending class
Original Author:Bradley Whittington (http://github.com/bradwhittington, http://twitter.com/darb)
Maintained by:Vinta Software: https://www.vinta.com.br/
Tests:GABadge 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, 3.10, 3.11)
  • Django (3.2, 4.0, 4.1)

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.

Settings

You can configure Django-Templated-Email by setting the following settings

TEMPLATED_EMAIL_FROM_EMAIL = None                 # String containing the email to send the email from - fallback to DEFAULT_FROM_EMAIL
TEMPLATED_EMAIL_BACKEND = TemplateBackend         # The backend class that will send the email, as a string like 'foo.bar.TemplateBackend' or the class reference itself
TEMPLATED_EMAIL_TEMPLATE_DIR = 'templated_email/' # The directory containing the templates, use '' if using the top level
TEMPLATED_EMAIL_FILE_EXTENSION = 'email'          # The file extension of the template files
TEMPLATED_EMAIL_AUTO_PLAIN = True                 # Set to false to disable the behavior of calculating the plain part from the html part of the email when `html2text <https://pypi.python.org/pypi/html2text>` is installed
TEMPLATED_EMAIL_PLAIN_FUNCTION = None             # Specify a custom function that converts from HTML to the plain part

# Specific for anymail integration:
TEMPLATED_EMAIL_EMAIL_MESSAGE_CLASS = 'django.core.mail.EmailMessage'                     # Replaces django.core.mail.EmailMessage
TEMPLATED_EMAIL_EMAIL_MULTIALTERNATIVES_CLASS = 'django.core.mail.EmailMultiAlternatives' # Replaces django.core.mail.EmailMultiAlternatives

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

Vinta Logo

This project, as other Vinta Software open-source projects is used in products of Vinta's clients. We are always looking for exciting work, so if you need any commercial support, feel free to get in touch: [email protected]

django-templated-email's People

Contributors

aericson avatar andersonresende avatar bastbnl avatar bblanchon avatar bradwhittington avatar chocoelho avatar clokep avatar dconlon avatar ekohl avatar fanshuai avatar fjsj avatar gak avatar gitter-badger avatar gnarvaja avatar lampslave avatar longhotsummer avatar mpasternak avatar nitinhayaran avatar rach avatar rangelfinal avatar timgates42 avatar tlevine avatar tuliolages avatar victorcarrico avatar yesimon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-templated-email's Issues

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.

AWS SES SERVICE INTEGRATION

Hi Team,

Is it possible to incorporate AWS SES in django-templated-email.

Note:
I already tried above scenario but i got below errors:
SAXParseException at /url
:1:0: syntax error

Mailgun support

Is it possible to send emails via Mailgun backend with this package?
Actually django-mailgun package doesn't support templated emails.

won't work with Django 1.8

Environment:

Request Method: POST
Request URL: http://localhost:8020/en/customer/signup/

Django Version: 1.8
Python Version: 2.7.6
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'crispy_forms',
'landing',
'customer',
'exchangeclients',
'accountant')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware')

Traceback:
File "/home/denis/envs/cbroker/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response

  1.                 response = wrapped_callback(request, _callback_args, *_callback_kwargs)
    
    File "/home/denis/envs/cbroker/local/lib/python2.7/site-packages/django/views/generic/base.py" in view
  2.         return self.dispatch(request, _args, *_kwargs)
    
    File "/home/denis/envs/cbroker/local/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
  3.     return handler(request, _args, *_kwargs)
    
    File "/home/denis/workz/cbroker/customer/views.py" in post
  4.                 context={'verification_url': verification_url})
    
    File "/home/denis/envs/cbroker/local/lib/python2.7/site-packages/templated_email/init.py" in send_templated_mail
  5.                        headers=headers, **kwargs)
    
    File "/home/denis/envs/cbroker/local/lib/python2.7/site-packages/templated_email/backends/vanilla_django.py" in send
  6.                                file_extension=file_extension)
    
    File "/home/denis/envs/cbroker/local/lib/python2.7/site-packages/templated_email/backends/vanilla_django.py" in get_email_message
  7.                                template_suffix or file_extension)
    
    File "/home/denis/envs/cbroker/local/lib/python2.7/site-packages/templated_email/backends/vanilla_django.py" in _render_email
  8.                 response[part] = _get_node(multi_part, render_context, name=part)
    
    File "/home/denis/envs/cbroker/local/lib/python2.7/site-packages/templated_email/utils.py" in _get_node
  9. for node in template:
    

Exception Type: TypeError at /en/customer/signup/
Exception Value: 'Template' object is not iterable

Email inliner support

There is a tool called django-inliner which works well. Maybe there is a way to integrate into this project somehow.

Refactor backends to django email backend

Currently django-templated-email has two functions: building EmailMessage objects and sending them. I propose that we refactor sending email to plain django email backends. These could be split off in a separate package as well.

I'd suggest that the first step would be making sure we only pass around EmailMessage objects. Maybe create a TemplatedEmailMessage class so we can store some extra information and/or make instantiation easier. When that's done we can make sure our backends we can switch to the default get_connection available in django.

Main benefit would be better integration with existing django features. It would also make it easier to add support for more things, such as attachments.

The reason I make an issue instead of a pull request is that I first would like to get your opinion about this.

TemplateDoesNotExist

vanilla_django.py seems to keep defaulting to templated_email/test.txt, instead of using the custom django-templated-email variables in settings.py. I tried:

from django.conf import settings

template_name = 'test'
template_prefix=getattr(settings,'TEMPLATED_EMAIL_TEMPLATE_DIR','templated_email/')
template_suffix=getattr(settings,'TEMPLATED_EMAIL_FILE_EXTENSION','email')
prefixed_template_name = ''.join((template_prefix,template_name))
debug_string = '%s.%s' % (prefixed_template_name,template_suffix)

This correctly builds the 'TEMPLATED_EMAIL_TEMPLATE_DIR/test.TEMPLATED_EMAIL_FILE_EXTENSION' template name in debug_string using the variables in settings.py. Have you ever seen this problem? I keep making small changes but haven't found the answer.

Thank you very much for your help!

Allow 'any' template names

Hi Brad,

I thought I'd make use of your package but I ran into two little issues.

You see, your package assumes that all templates will be stored in the 'templated_email/' directory but is possible that people want to have a different directory structure. For example: I like to all my emails and templates for a particular app to be in a particular directory together.

The second issues is that it assumes that all emails will have the '.email' extension. However, I'd like to have a simple '.mail' extension.

How about allowing one to force a path? I could inherit the Vanilla Template Backend and do this but for such tiny package, it defies the whole purpose of not having to write any extra code. Thanks.

Including image in the email

Hey there guys, how can i include an image in my Html email template??

i tried : <p><img src="{{site_domain}}/static/images/logo_email.jpg" alt="" height="109" width="65"></p> with no luck

Django1.9: TemplateDoesNotExist

I am upgrading my project to django1.9.

I am using django-templated-email with basic template inheritance.
The layout of my emails are in emplated_email/email_layout.email and in the individual mail I load this via the extends template_tag:

{% extends "templated_email/email_layout.email" %}

In django1.8 everything worked fine, but now I am getting a TemplateDoesNotExist.
Django can't find my email_layout.email any more.

django.template.loaders.filesystem.Loader: /home/.../templates/templated_email/email_layout.email (Skipped)

This file exists. What does the Skipped mean?
Had anyone similar problems while upgrading to django1.9?

Here the complete Traceback:

TemplateDoesNotExist at /api/contact/
templated_email/email_layout.email
Request Method: GET
Request URL:    http://localhost:8000/api/contact/
Django Version: 1.9.2
Exception Type: TemplateDoesNotExist
Exception Value:    
templated_email/email_layout.email
Exception Location: /home/ilse/myvenv/lib/python3.4/site-packages/django/template/engine.py in find_template, line 169
Python Executable:  /home/ilse/myvenv/bin/python
Python Version: 3.4.3
Python Path:    
['/home/ilse/workspace/wgcast_django',
 '/home/ilse/myvenv/src/django-cities',
 '/home/ilse/myvenv/lib/python3.4',
 '/home/ilse/myvenv/lib/python3.4/plat-x86_64-linux-gnu',
 '/home/ilse/myvenv/lib/python3.4/lib-dynload',
 '/usr/lib/python3.4',
 '/usr/lib/python3.4/plat-x86_64-linux-gnu',
 '/home/ilse/myvenv/lib/python3.4/site-packages',
 'lib',
 '/home/ilse/workspace/wgcast_django']
Server time:    Sun, 21 Feb 2016 20:48:38 +0100
Template-loader postmortem

Django tried loading these templates, in this order:

Using engine :
django.template.loaders.filesystem.Loader: /home/ilse/workspace/wgcast_django/templates/templated_email/email_layout.email (Skipped)
django.template.loaders.app_directories.Loader: /home/ilse/myvenv/lib/python3.4/site-packages/django/contrib/auth/templates/templated_email/email_layout.email (Source does not exist)
django.template.loaders.app_directories.Loader: /home/ilse/myvenv/lib/python3.4/site-packages/django/contrib/admin/templates/templated_email/email_layout.email (Source does not exist)
django.template.loaders.app_directories.Loader: /home/ilse/myvenv/lib/python3.4/site-packages/django/contrib/gis/templates/templated_email/email_layout.email (Source does not exist)
django.template.loaders.app_directories.Loader: /home/ilse/myvenv/lib/python3.4/site-packages/debug_toolbar/templates/templated_email/email_layout.email (Source does not exist)
django.template.loaders.app_directories.Loader: /home/ilse/myvenv/lib/python3.4/site-packages/rest_framework/templates/templated_email/email_layout.email (Source does not exist)
django.template.loaders.app_directories.Loader: /home/ilse/myvenv/lib/python3.4/site-packages/notifications/templates/templated_email/email_layout.email (Source does not exist)
django.template.loaders.app_directories.Loader: /home/ilse/myvenv/lib/python3.4/site-packages/allauth/templates/templated_email/email_layout.email (Source does not exist)
django.template.loaders.app_directories.Loader: /home/ilse/myvenv/lib/python3.4/site-packages/allauth/socialaccount/providers/facebook/templates/templated_email/email_layout.email (Source does not exist)
django.template.loaders.app_directories.Loader: /home/ilse/myvenv/lib/python3.4/site-packages/djcelery/templates/templated_email/email_layout.email (Source does not exist)
django.template.loaders.app_directories.Loader: /home/ilse/workspace/wgcast_django/base/templates/templated_email/email_layout.email (Skipped)
django.template.loaders.app_directories.Loader: /home/ilse/myvenv/lib/python3.4/site-packages/rest_framework_swagger/templates/templated_email/email_layout.email (Source does not exist)
Traceback Switch to copy-and-paste view

/home/ilse/myvenv/lib/python3.4/site-packages/templated_email/utils.py in _get_node
        return _iter_nodes(template, context, name, block_lookups) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/templated_email/utils.py in _iter_nodes
    for node in template: ...
▶ Local vars
During handling of the above exception ('Template' object is not iterable), another exception occurred:
/home/ilse/myvenv/lib/python3.4/site-packages/django/core/handlers/base.py in get_response
                    response = self.process_exception_by_middleware(e, request) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/django/core/handlers/base.py in get_response
                    response = wrapped_callback(request, *callback_args, **callback_kwargs) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/django/views/decorators/csrf.py in wrapped_view
        return view_func(*args, **kwargs) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/django/views/generic/base.py in view
            return self.dispatch(request, *args, **kwargs) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/rest_framework/views.py in dispatch
            response = self.handle_exception(exc) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/rest_framework/views.py in dispatch
            response = handler(request, *args, **kwargs) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/rest_framework/decorators.py in handler
            return func(*args, **kwargs) ...
▶ Local vars
/home/ilse/workspace/wgcast_django/static_pages/views.py in contact
                                       'user_id': user_id}) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/templated_email/__init__.py in get_templated_mail
                                       template_suffix=template_suffix) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/templated_email/backends/vanilla_django.py in get_email_message
                                   template_suffix or file_extension) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/templated_email/backends/vanilla_django.py in _render_email
                    response[part] = _get_node(multi_part, render_context, name=part) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/templated_email/utils.py in _get_node
        return _iter_nodes(template.template, context, name, block_lookups) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/templated_email/utils.py in _iter_nodes
            return _get_node(node.get_parent(context), context, name, lookups) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/django/template/loader_tags.py in get_parent
        return self.find_template(parent, context) ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/django/template/loader_tags.py in find_template
            template_name, skip=history, ...
▶ Local vars
/home/ilse/myvenv/lib/python3.4/site-packages/django/template/engine.py in find_template
        raise TemplateDoesNotExist(name, tried=tried) ...
▶ Local vars

Use templated-email on Google App Engine

Not so much an issue but more a question.... I'm porting a Django app to Google App Engine which relies on templated-email for sending out various emails. I just added the templated-email directory to my app directory and deployed to GAE. Although GAE does not complain about my code using the templated-email module, my app doesn't send out any emails either. I found this:

https://developers.google.com/appengine/docs/python/mail/sendingmail

on sending emails from GAE and I'm not sure whether templated-email will work for GAE without modification.

Any insights would be much appreciated!

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.

Allow for a selection of mail templates

I'd like the user to be able to select a template using that users' language preference and fallback to a default, for instance when there's no translated item there.

Why would you want this instead of just translating the message? One might want to add additional information to the template, use different logos, different subject prefix, etc. I think you get the idea.

PR coming up.

Move project to Jazzband

Jazzband is a project to share responsibility for administration of open source projects. django-templated-email is a good candidate because:

  • The project is mature and widely used.
  • By moving to jazzband, its easier for contributors to merge changes and make official releases. In the best case, this will spark some additional contribution to fix long broken features. In the worst case, the people that really need support for the latest Django will be able to publish a compatible version.

To move to jazzband, follow the guidelines.

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.

Readme typos

plz fix readme, actual pypi packed name is django-templated-email

Templated email example with generic CRUD

Following https://docs.djangoproject.com/en/1.8/topics/class-based-views/generic-editing/

views.py

from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.core.urlresolvers import reverse_lazy
from myapp.models import Author

class AuthorCreate(CreateView):
    model = Author
    fields = ['name','email']

class AuthorUpdate(UpdateView):
    model = Author
    fields = ['name','email']

class AuthorDelete(DeleteView):
    model = Author
    success_url = reverse_lazy('author-list')

I am trying to figure out how django-templated-email can be used to send email to the user's 'email' field and to 'settings.MANAGERS' upon Author creation and Update. Any example or hint will be cool. The hardest part is how all fit together, piece by piece makes sense though.

Using extends kills the subject

base.email

{% block html %}
    my html
    {% block body %}{% endblock %}
    more html
{% endblock %}

myemail.email

{% extends 'emails/base.email' %}
{% block subject %} banana {% endblock %}
{% block body %}my body{% endblock %}

I run DTE against myemail. The body/HTML side of things is working great, but the subject is completely ignored. If I add a subject tag to the base.email it will use that, but won't let me override it from myemail.email.

Am I structuring this incorrectly?

Is Django 1.10 really required?

Django 1.10 isn't LTS, I had to drop down to templated-email==1.0 and that's fine (since I'm ok with 1.9 right now). Just seems weird to have the version hard coded like that. Wanted to make sure that was intentional.

Wouldn't it make more sense to do:
Django>=1.8

Add a backend for Mandrill

http://mandrill.com/ is a transactional service by the same creators as MailChimp. It seems to be more in line with what serious django devs would use because it is transactional as opposed to newsletter-based. For now it looks really good and a backend hooking into saved templated would be nice.

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)

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 :)

ImportError: cannot import name 'InlineImage'

I follow the instructions as is, Import things in the correct order, I get:


Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x1060b4598>
Traceback (most recent call last):
  File "/Users/natumyers/Code/virtualenvpy34/testapp/lib/python3.4/site-packages/django/utils/autoreload.py", line 226, in wrapper
    fn(*args, **kwargs)
  File "/Users/natumyers/Code/virtualenvpy34/testapp/lib/python3.4/site-packages/django/core/management/commands/runserver.py", line 116, in inner_run
    self.check(display_num_errors=True)
  File "/Users/natumyers/Code/virtualenvpy34/testapp/lib/python3.4/site-packages/django/core/management/base.py", line 426, in check
    include_deployment_checks=include_deployment_checks,
  File "/Users/natumyers/Code/virtualenvpy34/testapp/lib/python3.4/site-packages/django/core/checks/registry.py", line 75, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/Users/natumyers/Code/virtualenvpy34/testapp/lib/python3.4/site-packages/django/core/checks/urls.py", line 13, in check_url_config
    return check_resolver(resolver)
  File "/Users/natumyers/Code/virtualenvpy34/testapp/lib/python3.4/site-packages/django/core/checks/urls.py", line 23, in check_resolver
    for pattern in resolver.url_patterns:
  File "/Users/natumyers/Code/virtualenvpy34/testapp/lib/python3.4/site-packages/django/utils/functional.py", line 33, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/Users/natumyers/Code/virtualenvpy34/testapp/lib/python3.4/site-packages/django/core/urlresolvers.py", line 417, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/Users/natumyers/Code/virtualenvpy34/testapp/lib/python3.4/site-packages/django/utils/functional.py", line 33, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/Users/natumyers/Code/virtualenvpy34/testapp/lib/python3.4/site-packages/django/core/urlresolvers.py", line 410, in urlconf_module
    return import_module(self.urlconf_name)
  File "/Users/natumyers/Code/virtualenvpy34/testapp/lib/python3.4/importlib/__init__.py", line 109, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 2254, in _gcd_import
  File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
  File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1129, in _exec
  File "<frozen importlib._bootstrap>", line 1471, in exec_module
  File "<frozen importlib._bootstrap>", line 321, in _call_with_frames_removed
  File "/Users/natumyers/Code/testappproject/testappdjango/testappdjango/urls.py", line 26, in <module>
    url('',include('testappapp.urls'))
  File "/Users/natumyers/Code/virtualenvpy34/testapp/lib/python3.4/site-packages/django/conf/urls/__init__.py", line 52, in include
    urlconf_module = import_module(urlconf_module)
  File "/Users/natumyers/Code/virtualenvpy34/testapp/lib/python3.4/importlib/__init__.py", line 109, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 2254, in _gcd_import
  File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
  File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
  File "<frozen importlib._bootstrap>", line 1129, in _exec
  File "<frozen importlib._bootstrap>", line 1471, in exec_module
  File "<frozen importlib._bootstrap>", line 321, in _call_with_frames_removed
  File "/Users/natumyers/Code/testappproject/testappdjango/testappapp/urls.py", line 2, in <module>
    from testappapp import views
  File "/Users/natumyers/Code/testappproject/testappdjango/testappapp/views.py", line 13, in <module>
    from templated_email import InlineImage
ImportError: cannot import name 'InlineImage'


Just a word of warning to Django 1.4 users

Comment out 'django.template.loaders.app_directories.load_template_source' in your TEMPLATE_LOADERS settings in order to prevent Error importing template source loader django.template.loaders.filesystem.load_template_source: "'module' object has no attribute 'load_template_source'.

django.template.loaders.app_directories.load_template_source states that

 "'django.template.loaders.app_directories.load_template_source' is deprecated; use 'django.template.loaders.app_directories.Loader' instead.",

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.

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!

EmailRenderException

I am getting this error:

EmailRenderException: Couldn't render email parts. Errors: {'plain': BlockNotFound("Node 'plain' could not be found in template.",), 'html': BlockNotFound("Node 'html' could not be found in template.",), 'subject': BlockNotFound("Node 'subject' could not be found in template.",)}

Even though the entire contents of my reminder.html file are as such:

{% block subject %}A reminder of {{ reminder.created_at|date }}...{% endblock %}

{% block plain %}
Hello {% include 'username.html' with user=reminder.user %},

...
{% endblock %}

What am I missing?

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.