Skip to main content

Django library for separating the message content from transmission method

Project description

# django-herald

[![Latest PyPI version](https://badge.fury.io/py/django-herald.svg)](https://pypi-hypernode.com/pypi/django-herald)
[![Build Status](https://travis-ci.org/worthwhile/django-herald.svg?branch=master)](https://travis-ci.org/worthwhile/django-herald)
[![Coverage Status](https://coveralls.io/repos/github/worthwhile/django-herald/badge.svg?branch=master)](https://coveralls.io/github/worthwhile/django-herald?branch=master)

[![Logo](https://github.com/worthwhile/django-herald/blob/master/logo.png)](https://github.com/worthwhile/django-herald)

Django library for separating the message content from transmission method

# Installation

1. `pip install django-herald`
2. Add `herald` and `django.contrib.sites` to `INSTALLED_APPS`.
3. Add herald's URLS:

if settings.DEBUG:
urlpatterns = [
url(r'^herald/', include('herald.urls')),
] + urlpatterns

# Usage

1. Create a `notifications.py` file in any django app. This is where your notification classes will live. Add a class like this:

from herald import registry
from herald.base import EmailNotification


class WelcomeEmail(EmailNotification): # extend from EmailNotification for emails
template_name = 'welcome_email' # name of template, without extension
subject = 'Welcome' # subject of email

def __init__(self, user): # optionally customize the initialization
self.context = {'user': user} # set context for the template rendering
self.to_emails = [user.email] # set list of emails to send to

@staticmethod
def get_demo_args(): # define a static method to return list of args needed to initialize class for testing
from users.models import User
return [User.objects.order_by('?')[0]]

registry.register(WelcomeEmail) # finally, register your notification class

# Alternatively, a class decorator can be used to register the notification:

@registry.register_decorator()
class WelcomeEmail(EmailNotification):
...


2. Create templates for rendering the email using this file structure:

templates/
herald/
text/
welcome_email.txt
html/
welcome_email.html

3. Test how your email looks by navigating to `/herald/`.

4. Send your email wherever you need in your code:

WelcomeEmail(user).send()

5. View the sent emails in django admin and even be able to resend it.


## Deleting Old Notifications

The `delnotifs` command is useful for purging the notification history.

The default usage will delete everything from sent during today:

python manage.py delnotifs

However, you can also pass arguments for `start` or `end` dates. `end` is up to, but not including that date.

python manage.py delnotifs --start='2016-01-01' --end='2016-01-10'


## Asynchronous Email Sending

If you are sending slightly different emails to a large number of people, it might take quite a while to process. By default, Django will process this all synchronously. For asynchronous support, we recommend django-celery-email. It is very straightfoward to setup and integrate: https://github.com/pmclanahan/django-celery-email


## herald.contrib.auth

Django has built-in support for sending password reset emails. If you would like to send those emails using herald, you can use the notification class in herald.contrib.auth.

First, add `herald.contrib.auth` to `INSTALLED_APPS` (in addition to `herald`).

Second, use the `HeraldPasswordResetForm` in place of django's built in `PasswordResetForm`. This step is entirely dependant on your project structure, but it essentially just involves changing the form class on the password reset view in some way:

# you may simply just need to override the password reset url like so:
url(r'^password_reset/$', password_reset, name='password_reset', {'password_reset_form': HeraldPasswordResetForm}),

# of if you are using something like django-authtools:
url(r'^password_reset/$', PasswordResetView.as_view(form_class=HeraldPasswordResetForm), name='password_reset'),

# or you may have a customized version of the password reset view:
class MyPasswordResetView(FormView):
form_class = HeraldPasswordResetForm # change the form class here

# or, you may have a custom password reset form already. In that case, you will want to extend from the HeraldPasswordResetForm:
class MyPasswordResetForm(HeraldPasswordResetForm):
...

# alternatively, you could even just send the notification wherever you wish, seperate from the form:
PasswordResetEmail(some_user).send()

Third, you may want to customize the templates for the email. By default, herald will use the `registration/password_reset_email.html` that is provided by django for both the html and text versions of the email. But you can simply override `herald/html/password_reset.html` and/or `herald/text/password_reset.txt` to suit your needs.

## User Disabled Notifications

If you want to disable certain notifications per user, add a record to the UserNotification table and
add notifications to the disabled_notifications many to many table.

For example:

user = User.objects.get(id=user.id)

notification = Notification.objects.get(notification_class='MyNotification')

# disable the notification
user.usernotification.disabled_notifications.add(notification)

By default, notifications can be disabled. You can put can_disable = False in your notification class and the system will
populate the database with this default. Your Notification class can also override the verbose_name by setting it in your
inherited Notification class. Like this:

class MyNotification(EmailNotification):
can_disable = False
verbose_name = "My Required Notification"

## Email Attachments

To send attachments, assign a list of attachments to the attachments attribute of your EmailNotification instance, or override the get_attachments() method.

Each attachment in the list can be one of the following:

1. A tuple which consists of the filename, the raw attachment data, and the mimetype. It is up to you to get the attachment data. Like this:

raw_data = get_pdf_data()

email.attachments = [
('Report.pdf', raw_data, 'application/pdf'),
('report.txt', 'text version of report', 'text/plain')
]
email.send()

2. A MIMEBase object. See the documentation for attachments under EmailMessage Objects/attachments in the Django documentation.

3. A django `File` object.

### Inline Attachments

Sometimes you want to embed an image directly into the email content. Do that by using a MIMEImage assigning a content id header to a MIMEImage, like this:

email = WelcomeEmail(user)
im = get_thumbnail(image_file.name, '600x600', quality=95)
my_image = MIMEImage(im.read()) # MIMEImage inherits from MIMEBase
my_image.add_header('Content-ID', '<{}>'.format(image_file.name))

You can refer to these images in your html email templates using the Content ID (cid) like this:

<img src="cid:{{image_file.name}}" />

You would of course need to add the "image_file" to your template context in the example above. You can also accomplish this using file operations. In this example we overrode the get_attachments method of an EmailNotification.

class MyNotification(EmailNotification):
context = {'hello': 'world'}
template_name = 'welcome_email'
to_emails = ['somebody@example.com']
subject = "My email test"

def get_attachments(self):
fp = open('python.jpeg', 'rb')
img = MIMEImage(fp.read())
img.add_header('Content-ID', '<{}>'.format('python.jpeg'))
return [
img,
]

And in your template you would refer to it like this, and you would not need to add anything to the context:

<img src="cid:python.jpeg" />

### Other MIME attachments

You can also attach any MIMEBase objects as regular attachments, but you must add a content-disposition header, or they will be inaccessible:

my_image.add_header('Content-Disposition', 'attachment; filename="python.jpg"')

Attachments can cause your database to become quite large, so you should be sure to run the management commands to purge the database of old messages.

# Running Tests

python runtests.py


Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-herald-0.1.7.tar.gz (21.3 kB view details)

Uploaded Source

Built Distribution

django_herald-0.1.7-py2.py3-none-any.whl (30.6 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file django-herald-0.1.7.tar.gz.

File metadata

File hashes

Hashes for django-herald-0.1.7.tar.gz
Algorithm Hash digest
SHA256 cd6be532460fd08efaa1dbfb2229fa6e8bd4d5607d5b4c2048269fef9e228e68
MD5 36fe464920c76f3239c126bab7fb91a1
BLAKE2b-256 51eb436a195ad48de0e6ce7dfe7c65501b860b638ebec5901e58ac15cb317079

See more details on using hashes here.

Provenance

File details

Details for the file django_herald-0.1.7-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for django_herald-0.1.7-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 350e40487df620a5ff1b9fc9f8607b64da9eaeab93d47aace574f765944f4831
MD5 a37d3621cb3c8c4463acb70824b0949c
BLAKE2b-256 96d258dd8076ff57c47122ec5ecbaa427f78379fa32004ab0e7913aa148cde8e

See more details on using hashes here.

Provenance

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page