Skip to content

Commit

Permalink
SES
Browse files Browse the repository at this point in the history
  • Loading branch information
tpetr committed Feb 7, 2011
1 parent b807624 commit 2a083cf
Show file tree
Hide file tree
Showing 14 changed files with 285 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/django_ses
3 changes: 3 additions & 0 deletions src/hmarr-django-ses-f517de1/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.pyc
*.db
local_settings.py
2 changes: 2 additions & 0 deletions src/hmarr-django-ses-f517de1/AUTHORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Harry Marr <[email protected]>

22 changes: 22 additions & 0 deletions src/hmarr-django-ses-f517de1/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Copyright (c) 2011 Harry Marr

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
4 changes: 4 additions & 0 deletions src/hmarr-django-ses-f517de1/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
include AUTHORS
include LICENSE
recursive-include example *

32 changes: 32 additions & 0 deletions src/hmarr-django-ses-f517de1/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
==========
Django-SES
==========
:Info: A Django email backend for Amazon's Simple Email Service
:Author: Harry Marr (http://github.com/hmarr, http://twitter.com/harrymarr)

Getting going
=============
Assuming you've got Django installed, you'll need Boto, a Python library that
wraps the AWS API. At this stage there is no support for SES in the stable
version of Boto so you'll need to install my fork, which contains an
implementation::

pip install -e git://github.com/hmarr/boto@ses#egg=boto

Install django-ses the same way (it'll be coming to PyPI before too long)::

pip install -e git://github.com/hmarr/django-ses#egg=django_ses

Add the following to your settings.py::

EMAIL_BACKEND = 'django_ses.SESBackend'

# These are optional -- if they're set as environment variables they won't
# need to be set here as well
AWS_ACCESS_KEY_ID = 'YOUR-ACCESS-KEY-ID'
AWS_SECRET_ACCESS_KEY = 'YOUR-SECRET-ACCESS-KEY'

Now, when you use ``django.core.mail.send_mail``, Simple Email Service will
send the messages by default.

Check out the ``example`` directory for more information.
90 changes: 90 additions & 0 deletions src/hmarr-django-ses-f517de1/django_ses/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from django.core.mail.backends.base import BaseEmailBackend
from django.conf import settings

import threading

from boto.ses import SESConnection


__version__ = '0.1'
__author__ = 'Harry Marr'


class SESBackend(BaseEmailBackend):
"""A Django Email backend that uses Amazon's Simple Email Service.
"""

def __init__(self, fail_silently=False, *args, **kwargs):
super(SESBackend, self).__init__(fail_silently=fail_silently, *args,
**kwargs)

self._access_key_id = getattr(settings, 'AWS_ACCESS_KEY_ID', None)
self._access_key = getattr(settings, 'AWS_SECRET_ACCESS_KEY', None)
self._api_endpoint = getattr(settings, 'AWS_SES_API_HOST',
SESConnection.DefaultHost)

self.connection = None
self._lock = threading.RLock()

def open(self):
"""Create a connection to the AWS API server. This can be reused for
sending multiple emails.
"""
if self.connection:
return False

try:
self.connection = SESConnection(
aws_access_key_id=self._access_key_id,
aws_secret_access_key=self._access_key,
host=self._api_endpoint,
)
except:
if not self.fail_silently:
raise

def close(self):
"""Close any open HTTP connections to the API server.
"""
try:
self.connection.close()
self.connection = None
except:
if not self.fail_silently:
raise

def send_messages(self, email_messages):
"""Sends one or more EmailMessage objects and returns the number of
email messages sent.
"""
if not email_messages:
return

self._lock.acquire()
try:
new_conn_created = self.open()
if not self.connection:
# Failed silently
return

num_sent = 0
for message in email_messages:
try:
self.connection.send_raw_email(
source=message.from_email,
destinations=message.recipients(),
raw_message=message.message().as_string(),
)
num_sent += 1
except SESConnection.ResponseError:
if not self.fail_silently:
raise
pass

if new_conn_created:
self.close()

finally:
self._lock.release()
return num_sent

Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
AWS_ACCESS_KEY_ID = 'YOUR-ACCESS-KEY-ID'
AWS_SECRET_ACCESS_KEY = 'YOUR-SECRET-ACCESS-KEY'

14 changes: 14 additions & 0 deletions src/hmarr-django-ses-f517de1/example/manage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env python
from django.core.management import execute_manager
try:
import settings # Assumed to be in the same directory.
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
sys.exit(1)

import sys
sys.path.insert(0, '..')

if __name__ == "__main__":
execute_manager(settings)
21 changes: 21 additions & 0 deletions src/hmarr-django-ses-f517de1/example/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
DEBUG = True

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'example.db',
}
}

SECRET_KEY = 'u=0tir)ob&3%uw3h4&&$%!!kffw$h*!_ia46f)qz%2rxnkhak&'

MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
)

ROOT_URLCONF = 'example.urls'

EMAIL_BACKEND = 'django_ses.SESBackend'

from local_settings import *

6 changes: 6 additions & 0 deletions src/hmarr-django-ses-f517de1/example/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.conf.urls.defaults import *

urlpatterns = patterns('',
url(r'^$', 'views.email_form', name='email-form'),
url(r'^send-email/$', 'views.send_email', name='send-email'),
)
44 changes: 44 additions & 0 deletions src/hmarr-django-ses-f517de1/example/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from django.http import HttpResponse
from django.core.urlresolvers import reverse
from django.core.mail import send_mail, EmailMessage

def email_form(request):
return HttpResponse("""
<h1>Django-SES Test</h1>
<form method="post" action="{send_email_url}">
<label for="from">From:</label>
<input type="text" name="from" id="from" />
<br />
<label for="to">To:</label>
<input type="text" name="to" id="to" />
<br />
<label for="subject">Subject:</label>
<input type="text" name="subject" id="subject" />
<br />
<label for="message">Message:</label>
<textarea name="message" id="message"></textarea>
<br />
<label for="message">HTML:</label>
<input type="checkbox" name="html-message" id="html-message" />
<br />
<input type="submit" value="Send Email" />
</form>
""".format(send_email_url=reverse('send-email')))

def send_email(request):
try:
subject = request.POST['subject']
message = request.POST['message']
from_email = request.POST['from']
html_message = bool(request.POST.get('html-message', False))
recipient_list = [request.POST['to']]

email = EmailMessage(subject, message, from_email, recipient_list)
if html_message:
email.content_subtype = 'html'
email.send()
except KeyError:
return HttpResponse('Please fill in all fields')

return HttpResponse('Email sent :)')

43 changes: 43 additions & 0 deletions src/hmarr-django-ses-f517de1/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from setuptools import setup, find_packages
import os

DESCRIPTION = "A Django email backend for Amazon's Simple Email Service"

LONG_DESCRIPTION = None
try:
LONG_DESCRIPTION = open('README.rst').read()
except:
pass

# Dirty hack to get version number from django_ses/__init__.py - we can't
# import it as it depends on boto and boto isn't installed until this
# file is read
init = os.path.join(os.path.dirname(__file__), 'django_ses', '__init__.py')
version_line = filter(lambda l: l.startswith('__version__'), open(init))[0]
version = version_line.split('=')[-1].strip().strip("'")
print version

CLASSIFIERS = [
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Topic :: Software Development :: Libraries :: Python Modules',
'Framework :: Django',
]

setup(
name='django-ses',
version=version,
packages=['django_ses'],
author='Harry Marr',
author_email='[email protected]',
url='http://github.com/hmarr/django-ses/',
license='MIT',
description=DESCRIPTION,
long_description=LONG_DESCRIPTION,
platforms=['any'],
classifiers=CLASSIFIERS,
install_requires=['django', 'boto'],
)

0 comments on commit 2a083cf

Please sign in to comment.