Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Clean up settings and add new configuration parameters #36

Merged
merged 3 commits into from

3 participants

@dlo

There are two commits in this pull request. The first just consolidates all the settings we're using from Django into a single file. The second creates two new settings values, AWS_SES_ACCESS_KEY_ID and AWS_SES_SECRET_ACCESS_KEY. We need this in production because we use different access keys for different AWS services (this makes key invalidation a bit easier in case anything is compromised, and lets us track usage much more granularly).

I updated the documentation as well. No new tests needed to be written because internally the library still uses AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

Enjoy!

django_ses/__init__.py
@@ -1,5 +1,5 @@
from django.core.mail.backends.base import BaseEmailBackend
-from django.conf import settings
+import settings
@tswicegood Owner

This should be from . import settings to avoid accidentally importing a root level settings module.

@tswicegood Owner

Alternatively, you could also do from django_ses import settings.

@dlo
dlo added a note

Good call, I'll fix this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
django_ses/settings.py
((1 lines not shown))
+from django.conf import settings
+from boto.ses import SESConnection
+
+DKIM_DOMAIN = getattr(settings, "DKIM_DOMAIN", None)
+DKIM_PRIVATE_KEY = getattr(settings, 'DKIM_PRIVATE_KEY', None)
+DKIM_SELECTOR = getattr(settings, 'DKIM_SELECTOR', 'ses')
+DKIM_HEADERS = getattr(settings, 'DKIM_HEADERS',
+ ('From', 'To', 'Cc', 'Subject'))
+
+AWS_ACCESS_KEY_ID = getattr(settings, 'AWS_SES_ACCESS_KEY_ID', None)
+if not AWS_ACCESS_KEY_ID:
+ AWS_ACCESS_KEY_ID = getattr(settings, 'AWS_ACCESS_KEY_ID', None)
+
+AWS_SECRET_ACCESS_KEY = getattr(settings, 'AWS_SES_SECRET_ACCESS_KEY', None)
+if not AWS_SECRET_ACCESS_KEY:
+ AWS_SECRET_ACCESS_KEY = getattr(settings, 'AWS_SECRET_ACCESS_KEY', None)
@tswicegood Owner

These lines here could be condensed a bit further:

AWS_SECRET_ACCESS_KEY = getattr(settings, "AWS_SES_SECRET_ACCESS_KEY",
    getattr(settings, "AWS_SECRET_ACCESS_KEY", None))

As a side note, shouldn't there be tests around this behavior to make sure that the correct keys are picked up and in the correct order?

@dlo
dlo added a note

I did that at first, but wasn't sure if it was more readable. Thoughts? I can change it.

@tswicegood Owner

I prefer the terser output, but that's 100% only the color of the bike shed that appeals most to me. :-)

One thing that's throwing me though, as I read it is that we put the AWS_SES_SECRET_ACCESS_KEY in the value AWS_SECRET_ACCESS_KEY. Any thoughts about dropping the AWS_ prefix on the internal variable so we only have SECRET_ACCESS_KEY and ACCESS_KEY_ID? Or maybe even shorter, SECRET_KEY and ACCESS_KEY?

@dlo
dlo added a note

Ok cool, I'll change that.

Agreed on the shorter settings version, it is kind of confusing when they're both the same name. I'll go with SECRET_KEY and ACCESS_KEY if that's alright.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@tswicegood
Owner

This looks good with the exception of tests. We should really make sure that the django_ses.settings module is doing what's expected of it. Think of it as an early warning system for future devs should forget and/or don't pay attention to the way it's documented and try to change it.

@dlo

Great, I'll add some tests to make sure that django_ses.settings is pulling in the correct values.

dlo added some commits
@tswicegood tswicegood merged commit 56f6e81 into django-ses:master
@tswicegood
Owner

I moved the tests.configuration to tests.settings, but otherwise we're set. Thanks!

@pcraciunoiu pcraciunoiu commented on the diff
django_ses/tests/utils.py
@@ -0,0 +1,5 @@
+import sys
+
+def unload_django_ses():
@pcraciunoiu Owner

Neat stuff. Thanks to both of you for contributing. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 21, 2012
  1. @dlo

    consolidate all SES settings to single file

    dlo authored
    This should make maintenance a bit easier.
  2. @dlo

    add AWS_SES_ACCESS_KEY_ID and AWS_SES_SECRET_ACCESS_KEY to settings file

    dlo authored
    Include updated documentation as well. No new tests are needed.
  3. @dlo

    add tests for new settings values

    dlo authored
This page is out of date. Refresh to see the latest.
View
16 README.rst
@@ -52,6 +52,14 @@ Add the following to your settings.py::
AWS_SES_REGION_NAME = 'us-east-1'
AWS_SES_REGION_ENDPOINT = 'email.us-east-1.amazonaws.com'
+Alternatively, instead of `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`, you
+can include the following two settings values. This is useful in situations
+where you would like to use a separate access key to send emails via SES than
+you would to upload files via S3::
+
+ AWS_SES_ACCESS_KEY_ID = 'YOUR-ACCESS-KEY-ID'
+ AWS_SES_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.
@@ -209,7 +217,11 @@ Full List of Settings
=====================
``AWS_ACCESS_KEY_ID``, ``AWS_SECRET_ACCESS_KEY``
- *Required.* Your API keys from Amazon SES.
+ *Required.* Your API keys for Amazon SES.
+
+``AWS_SES_ACCESS_KEY_ID``, ``AWS_SES_SECRET_ACCESS_KEY``
+ *Required.* Alternative API keys for Amazon SES. This is useful in situations
+ where you would like to use separate access keys for different AWS services.
``AWS_SES_REGION_NAME``, ``AWS_SES_REGION_ENDPOINT``
Optionally specify what region your SES service is using. Details:
@@ -224,7 +236,7 @@ Full List of Settings
https://docs.djangoproject.com/en/dev/ref/settings/#time-zone
``DKIM_DOMAIN``, ``DKIM_PRIVATE_KEY``
- Optional. If these settings are defined and the pydkim_ module is installed
+ Optional. If these settings are defined and the pydkim_ module is installed
then email messages will be signed with the specified key. You will also
need to publish your public key on DNS; the selector is set to ``ses`` by
default. See http://dkim.org/ for further detail.
View
25 django_ses/__init__.py
@@ -1,5 +1,5 @@
from django.core.mail.backends.base import BaseEmailBackend
-from django.conf import settings
+from django_ses import settings
from boto.regioninfo import RegionInfo
from boto.ses import SESConnection
@@ -30,11 +30,10 @@ def dkim_sign(message):
except ImportError:
pass
else:
- dkim_domain = getattr(settings, 'DKIM_DOMAIN', None)
- dkim_key = getattr(settings, 'DKIM_PRIVATE_KEY', None)
- dkim_selector = getattr(settings, 'DKIM_SELECTOR', 'ses')
- dkim_headers = getattr(settings, 'DKIM_HEADERS',
- ('From', 'To', 'Cc', 'Subject'))
+ dkim_domain = settings.DKIM_DOMAIN
+ dkim_key = settings.DKIM_PRIVATE_KEY
+ dkim_selector = settings.DKIM_SELECTOR
+ dkim_headers = settings.DKIM_HEADERS
if dkim_domain and dkim_key:
sig = dkim.sign(message,
dkim_selector,
@@ -53,14 +52,12 @@ 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._access_key_id = settings.ACCESS_KEY
+ self._access_key = settings.SECRET_KEY
self._region = RegionInfo(
- name=getattr(settings, 'AWS_SES_REGION_NAME',
- SESConnection.DefaultRegionName),
- endpoint=getattr(settings, 'AWS_SES_REGION_ENDPOINT',
- SESConnection.DefaultRegionEndpoint))
- self._throttle = getattr(settings, 'AWS_SES_AUTO_THROTTLE', 0.5)
+ name=settings.AWS_SES_REGION_NAME,
+ endpoint=settings.AWS_SES_REGION_ENDPOINT)
+ self._throttle = settings.AWS_SES_AUTO_THROTTLE
self.connection = None
@@ -104,7 +101,7 @@ def send_messages(self, email_messages):
return
num_sent = 0
- source = getattr(settings, 'AWS_SES_RETURN_PATH', None)
+ source = settings.AWS_SES_RETURN_PATH
for message in email_messages:
# Automatic throttling. Assumes that this is the only SES client
# currently operating. The AWS_SES_AUTO_THROTTLE setting is a
View
20 django_ses/management/commands/get_ses_statistics.py
@@ -6,18 +6,18 @@
from boto.ses import SESConnection
-from django.conf import settings
from django.core.management.base import BaseCommand
from django_ses.models import SESStat
from django_ses.views import stats_to_list
+from django_ses import settings
def stat_factory():
return {
- 'delivery_attempts': 0,
+ 'delivery_attempts': 0,
'bounces': 0,
- 'complaints': 0,
+ 'complaints': 0,
'rejects': 0,
}
@@ -26,17 +26,17 @@ class Command(BaseCommand):
"""
Get SES sending statistic and store the result, grouped by date.
"""
-
+
def handle(self, *args, **options):
-
+
connection = SESConnection(
- aws_access_key_id=getattr(settings, 'AWS_ACCESS_KEY_ID', None),
- aws_secret_access_key=getattr(settings, 'AWS_SECRET_ACCESS_KEY', None),
+ aws_access_key_id=settings.ACCESS_KEY,
+ aws_secret_access_key=settings.SECRET_KEY,
)
stats = connection.get_send_statistics()
data_points = stats_to_list(stats, localize=False)
stats_dict = defaultdict(stat_factory)
-
+
for data in data_points:
attempts = int(data['DeliveryAttempts'])
bounces = int(data['Bounces'])
@@ -52,9 +52,9 @@ def handle(self, *args, **options):
stat, created = SESStat.objects.get_or_create(
date=k,
defaults={
- 'delivery_attempts': v['delivery_attempts'],
+ 'delivery_attempts': v['delivery_attempts'],
'bounces': v['bounces'],
- 'complaints': v['complaints'],
+ 'complaints': v['complaints'],
'rejects': v['rejects'],
})
View
13 django_ses/management/commands/ses_email_address.py
@@ -5,9 +5,10 @@
from boto.regioninfo import RegionInfo
from boto.ses import SESConnection
-from django.conf import settings
from django.core.management.base import BaseCommand
+from django_ses import settings
+
class Command(BaseCommand):
"""Verify, delete or list SES email addresses"""
@@ -31,13 +32,11 @@ def handle(self, *args, **options):
delete_email = options.get('delete', False)
list_emails = options.get('list', False)
- access_key_id = getattr(settings, 'AWS_ACCESS_KEY_ID', None)
- access_key = getattr(settings, 'AWS_SECRET_ACCESS_KEY', None)
+ access_key_id = settings.ACCESS_KEY
+ access_key = settings.SECRET_KEY
region = RegionInfo(
- name=getattr(settings, 'AWS_SES_REGION_NAME',
- SESConnection.DefaultRegionName),
- endpoint=getattr(settings, 'AWS_SES_REGION_ENDPOINT',
- SESConnection.DefaultRegionEndpoint))
+ name=settings.AWS_SES_REGION_NAME,
+ endpoint=settings.AWS_SES_REGION_ENDPOINT)
connection = SESConnection(
aws_access_key_id=access_key_id,
View
30 django_ses/settings.py
@@ -0,0 +1,30 @@
+from django.conf import settings
+from boto.ses import SESConnection
+
+__all__ = ('ACCESS_KEY', 'SECRET_KEY', 'AWS_SES_REGION_NAME',
+ 'AWS_SES_REGION_ENDPOINT', 'AWS_SES_AUTO_THROTTLE',
+ 'AWS_SES_RETURN_PATH', 'DKIM_DOMAIN', 'DKIM_PRIVATE_KEY',
+ 'DKIM_SELECTOR', 'DKIM_HEADERS', 'TIME_ZONE')
+
+ACCESS_KEY = getattr(settings, 'AWS_SES_ACCESS_KEY_ID',
+ getattr(settings, 'AWS_ACCESS_KEY_ID', None))
+
+SECRET_KEY = getattr(settings, 'AWS_SES_SECRET_ACCESS_KEY',
+ getattr(settings, 'AWS_SECRET_ACCESS_KEY', None))
+
+AWS_SES_REGION_NAME = getattr(settings, 'AWS_SES_REGION_NAME',
+ SESConnection.DefaultRegionName),
+AWS_SES_REGION_ENDPOINT = getattr(settings, 'AWS_SES_REGION_ENDPOINT',
+ SESConnection.DefaultRegionEndpoint)
+
+AWS_SES_AUTO_THROTTLE = getattr(settings, 'AWS_SES_AUTO_THROTTLE', 0.5)
+AWS_SES_RETURN_PATH = getattr(settings, 'AWS_SES_RETURN_PATH', None)
+
+DKIM_DOMAIN = getattr(settings, "DKIM_DOMAIN", None)
+DKIM_PRIVATE_KEY = getattr(settings, 'DKIM_PRIVATE_KEY', None)
+DKIM_SELECTOR = getattr(settings, 'DKIM_SELECTOR', 'ses')
+DKIM_HEADERS = getattr(settings, 'DKIM_HEADERS',
+ ('From', 'To', 'Cc', 'Subject'))
+
+TIME_ZONE = settings.TIME_ZONE
+
View
2  django_ses/tests/__init__.py
@@ -1,3 +1,5 @@
from backend import SESBackendTest
from commands import SESCommandTest
from stats import StatParsingTest
+from configuration import SettingsImportTest
+
View
18 django_ses/tests/backend.py
@@ -4,9 +4,10 @@
from django.core.mail import send_mail
from django.test import TestCase
-import django_ses
from boto.ses import SESConnection
+import django_ses
+from django_ses.tests.utils import unload_django_ses
# random key generated with `openssl genrsa 512`
DKIM_PRIVATE_KEY = '''
@@ -63,7 +64,6 @@ def get_rate_limit(self):
class SESBackendTest(TestCase):
-
def setUp(self):
settings.EMAIL_BACKEND = 'django_ses.tests.backend.FakeSESBackend'
django_ses.SESConnection = FakeSESConnection
@@ -118,6 +118,18 @@ def test_return_path(self):
send_mail('subject', 'body', 'from@example.com', ['to@example.com'])
self.assertEqual(self.outbox.pop()['source'], 'from@example.com')
- settings.AWS_SES_RETURN_PATH = 'return@example.com'
+class SESBackendTestReturn(TestCase):
+ def setUp(self):
+ settings.EMAIL_BACKEND = 'django_ses.tests.backend.FakeSESBackend'
+ django_ses.SESConnection = FakeSESConnection
+ self.outbox = FakeSESConnection.outbox
+
+ def tearDown(self):
+ # Empty outbox everytime test finishes
+ FakeSESConnection.outbox = []
+
+ def test_return_path(self):
+ settings.AWS_SES_RETURN_PATH = "return@example.com"
send_mail('subject', 'body', 'from@example.com', ['to@example.com'])
self.assertEqual(self.outbox.pop()['source'], 'return@example.com')
+
View
22 django_ses/tests/configuration.py
@@ -0,0 +1,22 @@
+from django.test import TestCase
+from django.conf import settings
+from django_ses.tests.utils import unload_django_ses
+
+class SettingsImportTest(TestCase):
+ def test_aws_access_key_given(self):
+ settings.AWS_ACCESS_KEY_ID = "Yjc4MzQ4MGYzMTBhOWY3ODJhODhmNTBkN2QwY2IyZTdhZmU1NDM1ZQo"
+ settings.AWS_SECRET_ACCESS_KEY = "NTBjYzAzNzVlMTA0N2FiMmFlODlhYjY5OTYwZjNkNjZmMWNhNzRhOQo"
+ unload_django_ses()
+ import django_ses
+ self.assertEqual(django_ses.settings.ACCESS_KEY, settings.AWS_ACCESS_KEY_ID)
+ self.assertEqual(django_ses.settings.SECRET_KEY, settings.AWS_SECRET_ACCESS_KEY)
+
+ def test_ses_access_key_given(self):
+ settings.AWS_SES_ACCESS_KEY_ID = "YmM2M2QwZTE3ODk3NTJmYzZlZDc1MDY0ZmJkMDZjZjhmOTU0MWQ4MAo"
+ settings.AWS_SES_SECRET_ACCESS_KEY = "NDNiMzRjNzlmZGU0ZDAzZTQxNTkwNzdkNWE5Y2JlNjk4OGFkM2UyZQo"
+ unload_django_ses()
+ import django_ses
+ self.assertEqual(django_ses.settings.ACCESS_KEY, settings.AWS_SES_ACCESS_KEY_ID)
+ self.assertEqual(django_ses.settings.SECRET_KEY, settings.AWS_SES_SECRET_ACCESS_KEY)
+
+
View
5 django_ses/tests/utils.py
@@ -0,0 +1,5 @@
+import sys
+
+def unload_django_ses():
@pcraciunoiu Owner

Neat stuff. Thanks to both of you for contributing. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ del sys.modules['django_ses.settings']
+ del sys.modules['django_ses']
View
12 django_ses/views.py
@@ -9,12 +9,12 @@
from boto.regioninfo import RegionInfo
from boto.ses import SESConnection
-from django.conf import settings
from django.core.cache import cache
from django.core.exceptions import PermissionDenied
from django.shortcuts import render_to_response
from django.template import RequestContext
+from django_ses import settings
def superuser_only(view_func):
"""
@@ -106,14 +106,12 @@ def dashboard(request):
return cached_view
region = RegionInfo(
- name=getattr(settings, 'AWS_SES_REGION_NAME',
- SESConnection.DefaultRegionName),
- endpoint=getattr(settings, 'AWS_SES_REGION_ENDPOINT',
- SESConnection.DefaultRegionEndpoint))
+ name=settings.AWS_SES_REGION_NAME,
+ endpoint=settings.AWS_SES_REGION_ENDPOINT)
ses_conn = SESConnection(
- aws_access_key_id=getattr(settings, 'AWS_ACCESS_KEY_ID', None),
- aws_secret_access_key=getattr(settings, 'AWS_SECRET_ACCESS_KEY', None),
+ aws_access_key_id=settings.ACCESS_KEY,
+ aws_secret_access_key=settings.SECRET_KEY,
region=region)
quota_dict = ses_conn.get_send_quota()
View
2  runtests.py
@@ -11,7 +11,9 @@
# run the test suite. Note that Django requires that the
# `DATABASES` value be present and configured in order to
# do anything.
+
from django.conf import settings
+
settings.configure(
INSTALLED_APPS=[
"django_ses",
Something went wrong with that request. Please try again.