Django Post Office
Django Post Office is a simple app that allows you to send email asynchronously in Django. Supports HTML email, database backed templates and logging.
post_office
is implemented as a Django EmailBackend
so you don't need to
change any of your code to start sending email asynchronously.
Dependencies
Installation
Install from PyPI (or you can manually download it from PyPI):
pip install django-post_office
Add
post_office
to your INSTALLED_APPS in django'ssettings.py
:
INSTALLED_APPS = (
# other apps
"post_office",
)
Run
syncdb
:python manage.py syncdb
Set
post_office.EmailBackend
as yourEMAIL_BACKEND
in django'ssettings.py
:EMAIL_BACKEND = 'post_office.EmailBackend'
Usage
If you already use Django's send_mail
command and want to send out emails
asynchronously, simply set post_office
as your email backend in
settings.py
and it will automatically queue outgoing emails without you
needing to change anything:
EMAIL_BACKEND = 'post_office.EmailBackend'
To actually send them out, run python manage.py send_queued_mail
. You can schedule this
to run regularly via cron:
* * * * * (/usr/bin/python manage.py send_queued_mail >> send_mail.log 2>&1)
By default, post_office
uses django's SMTP EmailBackend
. If you want to
use a different backend, you can do so by changing POST_OFFICE_BACKEND
.
For example if you want to use django-ses:
POST_OFFICE_BACKEND = 'django_ses.SESBackend'
You can view also queued emails along with their statuses if you have django's admin interface enabled:
INSTALLED_APPS = (
# ...
'django.contrib.admin',
# ...
)
Sending HTML Emails
post_office
also comes with a send_mail
command similar to django's.
It accepts two extra arguments, html_message
and
priority
(high
, medium
, low
or now
).
Here's how to use it:
from post_office import send_mail, PRIORITY
send_mail('subject', 'plaintext message', 'from@example.com', ['to@example.com'],
'<p>HTML message</p>', priority=PRIORITY.medium)
post_office
is also task queue friendly. Passing now
as priority into
send_mail
will deliver the email right away, regardless of how many emails
you have in your queue:
from post_office import send_mail, PRIORITY
send_mail('subject', 'plaintext message', 'from@example.com', ['to@example.com'],
'<p>HTML message</p>', priority=PRIORITY.now)
This is useful if you already use something like django-rq to send emails asynchronously and only need to store email activities and logs.
Email Templates
post_office
also allows you to easily send template rendered emails.
Email templates in post_office
are stored in database and can be easily
added via Django's admin
interface.
Here's how to send templated emails:
- Create an
EmailTemplate
from django'sadmin
interface - Send the email using
send_templated_mail
command:
from post_office.utils import send_templated_mail
send_templated_mail('template_name', 'from@example.com', ['to@example.com'])
# Here's a list of full arguments accepted by send_templated mail
send_templated_mail(
'template_name', # Name of the template
'from@example.com', # Sender email
['to@example.com'], # List of recipient emails
context={'foo': 'bar'}, # Extra data that will be used during template rendering
priority=PRIORITY.now, # Email priority
)
Template Tags and Variables
You can, of course use Django's template tags and variables when in templates.
For example, if you put "Hello, {{ name }}" in the subject line and pass in
{'name': 'Alice'}
as context, you will get "Hello, Alice" as subject:
from post_office.models import EmailTemplate
from post_office.utils import send_templated_mail
EmailTemplate.objects.create(
name='morning_greeting',
subject='Morning, {{ name|capfirst }}',
content='Hi {{ name }}, how are you feeling today?',
html_content='Hi <b>{{ name }}</b>, how are you feeling today?',
)
send_templated_mail(
'morning_greeting',
'from@example.com',
['to@example.com'],
context={'name': 'alice'},
)
# This will create an email with the following content:
subject = 'Morning, Alice',
content = 'Hi alice, how are you feeling today?'
content = 'Hi <strong>alice</strong>, how are you feeling today?'
post_office
will cache EmailTemplate``s by default if Django's caching
mechanism is configured. If for some reason you want to disable caching, you can
set ``POST_OFFICE_CACHE
to False
in settings.py
:
## All cache key will be prefixed by post_office:template:
## To turn OFF caching, you need to explicitly set POST_OFFICE_CACHE to False in settings
POST_OFFICE_CACHE = False
## Optional: to use a non default cache backend, add a "post_office" entry in CACHES
CACHES = {
'post_office': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '127.0.0.1:11211',
}
}
Management Commands
send_queued_mail
- send queued emails, those that aren't successfully sent they will be marked asfailed
.cleanup_mail
- delete all emails created before an X number of days (defaults to 90).
You may want to set these up via cron to run regularly:
* * * * * (cd $PROJECT; python manage.py send_queued_mail >> $PROJECT/cron_mail.log 2>&1) 0 1 * * * (cd $PROJECT; python manage.py cleanup_mail --days=30 >> $PROJECT/cron_mail_cleanup.log 2>&1)
Testing
To run post_office
's test suite:
`which django-admin.py` test post_office --settings=post_office.test_settings --pythonpath=.
Changelog
Version 0.2.1
- Fixed typo in
admin.py
Version 0.2
- Allows sending emails via database backed templates
Version 0.1.5
- Errors when opening connection in
Email.dispatch
method are now logged