cradmin_email — Utilities for working with email¶
The purpose of this app is to make it easier to work with email, especially with HTML email.
Usage¶
Add django_cradmin.apps.cradmin_email
to you INSTALLED_APPS
-setting.
See django_cradmin.apps.cradmin_email.emailutils.AbstractEmail
for example usage.
Settings¶
- DJANGO_CRADMIN_EMAIL_SUBJECT_PREFIX
- Use this to specify a default prefix for email subjects send with
django_cradmin.apps.cradmin_email.emailutils.AbstractEmail
. - DJANGO_CRADMIN_EMAIL_DEFAULT_CONTEXT_DATA
- Documented below.
- DJANGO_CRADMIN_EMAIL_LOGO_HTML
- HTML for the logo in HTML emails. Used by the default email header template. More documentation below.
- DJANGO_CRADMIN_SITENAME
- Use this to specify a site name that you can use in your email templates. Used by the default email header template.
HTML email formatting guide¶
HTML formatting in email is not like formatting in browsers. You actually need to forget more or less every good practice from the last 10 years of web development, and instead:
- Use tables for layout (yes, TABLES for layout).
- Avoid images. Many spam engines use the ratio between images and text, so do not use many images.
- Set styles directly on elements.
Our solution¶
To make this easier to handle, we suggest the following:
- For the actual content of your emails, use
<br>
to emulate paragraphs, and keep the formatting to the<a>
,<strong>
,<em>
and<big>
tags. For advanced formatting/layout, use<table>
, but you should not need that if you use our template tags. - Use a common base template that styles the surrounding content for all your emails.
We make this easy to do by providing the cradmin_email/html_message_base.django.html
template that you can extend in your html message templates:
- You just have to override the
contents
block. - The template is styled via the
DJANGO_CRADMIN_EMAIL_DEFAULT_CONTEXT_DATA
setting.
Styling and tuning the html_message_base template¶
The easiest thing to adjust is the styles. You do this via
the DJANGO_CRADMIN_EMAIL_DEFAULT_CONTEXT_DATA
setting (a dict).
You can set the following values:
- body_style
- The styles of the body element. Note that gmail ignores this.
- outer_table_style
- The CSS styles of the outer table.
- common_td_style
Common styles for header, contents and footer. Make sure this ends with
;
. Example:font-family: Arial, sans-serif; font-size: 16px; line-height: 1.42857143; letter-spacing: 0.5px; padding-left: 10px; padding-right: 10px;- header_td_style
- The CSS styles of the header block. This is a
<td>
element.- contents_td_style
- The CSS styles of the contents block. This is a
<td>
element.- footer_td_style
- The CSS styles of the footer block. This is a
<td>
element.- link_style
This is not used by the base template, but you should use it on all the links you create to make it easy to style your links. Example:
<a href="http://example.com" style="{{ link_style }}">Go to example.com</a>- footer_link_style
This is not used by the base template, but you should use it on all the links you create in your footer template to make it easy to style your links. Example:
<a href="http://example.com" style="{{ footer_link_style }}">Go to example.com</a>- primary_button_link_style
- Styles for the
cradmin_email_primary_buttonlink()
template tag.- secondary_button_link_style
- Styles for the
cradmin_email_secondary_buttonlink()
template tag.- logo_style
- Style for the logo. This is a
<span>
element. This element is rendered by the default header include template if you set theDJANGO_CRADMIN_EMAIL_LOGO_HTML
setting.
Templates¶
- cradmin_email/html_message_base.django.html
- The base template for all HTML emails. You should not need to override this, but just extend it in all your email templates. How to style this template via DJANGO_CRADMIN_EMAIL_DEFAULT_CONTEXT_DATA is described above.
- cradmin_email/include/html_message_header.django.html
Included
cradmin_email/html_message_base.django.html
to render the header. You can override this in one of your own apps - just ensure the app is listed beforedjango_cradmin.apps.cradmin_email
inINSTALLED_APPS
.The template should not need to be overridden if you can render your logo/header using HTML and CSS. You should instead adjust the
logo_style
,header_td_style
and perhaps theheader_td_style
via theDJANGO_CRADMIN_EMAIL_DEFAULT_CONTEXT_DATA
setting.
Design/develop/debug email rendering¶
To make it easy to visually develop the email template, we provide a view that you can add to your url config:
url(r'^cradmin_email/', include('django_cradmin.apps.cradmin_email.urls')),
And go to one of these URLs to debug email rendering:
- http://lokalttest.net:8000/cradmin_email/emaildesign/
- http://lokalttest.net:8000/cradmin_email/emaildesign/plaintext
Remember to test that your styles are responsive, and try to test with as many clients as possible. https://litmus.com/ is a good solution for this.
Resources¶
- http://templates.mailchimp.com/getting-started/html-email-basics/
- http://webdesign.tutsplus.com/articles/build-an-html-email-template-from-scratch–webdesign-12770
- https://www.campaignmonitor.com/dev-resources/guides/coding/
- https://www.campaignmonitor.com/css/
- https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design
Template tags¶
Render a normal link.
Examples
Url as string:
{% load cradmin_email_tags %} {% cradmin_email_link "http://example.com" %} A link {% end_cradmin_email_link %}
Url as context variable:
{% load cradmin_email_tags %} {% cradmin_email_link someurl %} A link {% end_cradmin_email_link %}
Render a link as a primary button.
Examples
Url as string:
{% load cradmin_email_tags %} {% cradmin_email_primary_buttonlink "http://example.com" %} A primary button link {% end_cradmin_email_primary_buttonlink %}
Url as context variable:
{% load cradmin_email_tags %} {% cradmin_email_primary_buttonlink someurl %} A primary button link {% end_cradmin_email_primary_buttonlink %}
Render a link as a secondary button.
Examples
Url as string:
{% load cradmin_email_tags %} {% cradmin_email_secondary_buttonlink "http://example.com" %} A secondary button link {% end_cradmin_email_secondary_buttonlink %}
Url as context variable:
{% load cradmin_email_tags %} {% cradmin_email_secondary_buttonlink someurl %} A secondary button link {% end_cradmin_email_secondary_buttonlink %}
API¶
-
convert_html_to_plaintext
(html)¶ Convert the given
html
to plain text.
-
class
AbstractEmail
(recipient=None, recipient_list=None, extra_context_data=None, from_email=None)¶ Bases:
object
Abstract class for sending email.
Examples
Simple example:
from django_cradmin.apps.cradmin_email import emailutils class SimpleEmail(emailutils.AbstractEmail): subject_template = 'myapp/subject.django.txt' html_message_template = 'myapp/html_message.django.html' SimpleEmail(recipient='test@example.com').send()
Specify a sender:
SimpleEmail(recipient='test@example.com', from_email='admin@example.com').send()
Build a common abstract class that defaults to something other than
settings.DEFAULT_FROM_EMAIL
:class AbstractAccountEmail(emailutils.AbstractEmail): def get_default_from_email(self): return 'account@example.com'
Specify a plaintext template instead of converting the HTML email to plaintext:
class WithPlaintextEmail(emailutils.AbstractEmail): subject_template = 'myapp/subject.django.txt' html_message_template = 'myapp/html_message.django.html' plaintext_message_template = 'myapp/plaintext_message.django.txt'
Set subject via a translation string instead of a template (you can do this for the message as well):
class StringSubjectEmail(emailutils.AbstractEmail): html_message_template = 'myapp/html_message.django.html' def render_subject(self): return _('My subject')
Provide context data for the templates:
SimpleEmail(recipient='test@example.com', extra_context_data={ 'name': 'Peter Pan', }).send()
Parameters: - recipient (str) – The recipient of the email.
- recipient_list (list) – The recipients of the email. Use this instead of
recipient
if you want to send the message to multiple people. - extra_context_data (dict) – An optional dict with extra context data for the templates.
- from_email – The email address we send the message from.
Defaults to
get_default_from_email()
.
-
subject_template
= None¶ The Django template for the subject. You must set this in subclasses, or override
get_subject_template()
orrender_subject()
.
-
html_message_template
= None¶ The Django template for the HTML message. You must set this in subclasses, or override
get_html_message_template()
orrender_html_message()
.
-
plaintext_message_template
= None¶ The Django template for the Plain text message. If this or
get_plaintext_message_template()
orrender_subject()
is not set in subclasses, we autoconvert the HTML message to plain text.
-
DEFAULT_CONTEXT_DATA
= {'body_style': 'background-color: #fff;', 'contents_td_style': 'padding: 20px; ', 'primary_button_link_style': 'font-size: 16px; font-family: Arial, sans-serif; color: #fff; text-decoration: none; font-weight: bold; text-transform: uppercase; letter-spacing: 1px; background-color: #377CA8; border-top: 10px solid #377CA8; border-bottom: 10px solid #377CA8; border-right: 16px solid #377CA8; border-left: 16px solid #377CA8; border-radius: 3px; -webkit-border-radius: 3px; -moz-border-radius: 3px; display: inline-block;', 'logo_style': 'font-size: 30px; font-weight: bold; padding: 0; ', 'link_style': 'color: #377CA8; text-decoration: underline;', 'secondary_button_link_style': 'font-size: 16px; font-family: Arial, sans-serif; color: #fff; text-decoration: none; font-weight: bold; text-transform: uppercase; letter-spacing: 1px; background-color: #999999; border-top: 10px solid #999999; border-bottom: 10px solid #999999; border-right: 16px solid #999999; border-left: 16px solid #999999; border-radius: 3px; -webkit-border-radius: 3px; -moz-border-radius: 3px; display: inline-block;', 'header_td_style': 'padding: 20px; ', 'common_td_style': 'font-family: Arial, sans-serif; font-size: 16px; line-height: 1.42857143; margin: 0; letter-spacing: 0.5px; ', 'footer_td_style': 'padding-left: 20px; padding-right: 20px; color: #555; '}¶ Fallback value of the DJANGO_CRADMIN_EMAIL_DEFAULT_CONTEXT_DATA setting is not set.
-
get_subject_template
()¶ Alternative way to specify
subject_template
. This takes presedence oversubject_template
.
-
get_html_message_template
()¶ Alternative way to specify
html_message_template
. This takes presedence overhtml_message_template
.
-
get_plaintext_message_template
()¶ Alternative way to specify
plaintext_message_template
. This takes presedence overplaintext_message_template
.
-
get_subject_prefix
()¶ Get the prefix to use for the subject.
Defaults to
settings.DJANGO_CRADMIN_EMAIL_SUBJECT_PREFIX
, falling back to empty string.If your privide a prefix, you should most likely include an empty space at the end of it.
-
render_subject
()¶ Render the subject. You can override this if you want to adjust template rendering or avoid using a template.
-
render_html_message
()¶ Render the html message. You can override this if you want to adjust template rendering or avoid using a template.
-
render_plaintext_message
()¶ Render the plaintext message. You can override this if you want to adjust template rendering or avoid using a template.
If no
plaintext_message_template
orget_plaintext_message_template()
is specified, we convert the HTML message to plaintext usingconvert_html_to_plaintext()
.
-
get_default_context_data
()¶ Get the default context data.
You should normally not override this, but rather use it if you override
get_context_data()
and callingsuper().get_context_data()
is not a suitable solution.
-
get_context_data
()¶ Get the template context data sent to
subject_template
,html_message_template
andplaintext_message_template
.By default this returns:
from_email
.DJANGO_CRADMIN_SITENAME
(if set as a Django setting).- anything you send as the
extra_context_data
argument to the constructor. - Anything in the
DJANGO_CRADMIN_EMAIL_DEFAULT_CONTEXT_DATA
setting.
-
get_from_email
()¶ Get the email address of the sender. Override this if you want to provide the
from_email
as a method instead of argument to the constructor.
-
get_recipient_list
()¶ Get the list of recipients. Override this if you want to provide the
recipient_list
as a method instead of argument to the constructor.
-
get_send_mail_kwargs
()¶ Get a dict with kwargs for
django.core.mail.send_mail()
.We default to building this from the various methods on this class, but you can override this to adjust the kwargs.
-
send
()¶ Send the email.
-
get_default_from_email
()¶ Get the fallback value for
from_email
. Defaults tosettings.DEFAULT_FROM_EMAIL
, but you can override this to provide a common superclass that defaults to sending from a different address.