Skip to content

Commit

Permalink
Compatibility with earlier Python 2.7 versions
Browse files Browse the repository at this point in the history
Compatibility with Python 2.7 versions older than 2.7.7

* Use Django's constant_time_compare method
* Include sparkpost in test requirements
* Don't use non-public `EnvironmentVarGuard` in tests

Fixes #41

(cherry picked from commit f0589e3)
  • Loading branch information
sebbacon authored and medmunds committed Nov 1, 2016
1 parent 5ea93ce commit 8c38b69
Show file tree
Hide file tree
Showing 4 changed files with 9 additions and 12 deletions.
3 changes: 2 additions & 1 deletion anymail/webhooks/mailgun.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import hashlib
import hmac
from django.utils.crypto import constant_time_compare
from django.utils.timezone import utc

from .base import AnymailBaseWebhookView
Expand Down Expand Up @@ -34,7 +35,7 @@ def validate_request(self, request):
raise AnymailWebhookValidationFailure("Mailgun webhook called without required security fields")
expected_signature = hmac.new(key=self.api_key, msg='{}{}'.format(timestamp, token).encode('ascii'),
digestmod=hashlib.sha256).hexdigest()
if not hmac.compare_digest(signature, expected_signature):
if not constant_time_compare(signature, expected_signature):
raise AnymailWebhookValidationFailure("Mailgun webhook called with incorrect signature")

def parse_events(self, request):
Expand Down
3 changes: 2 additions & 1 deletion anymail/webhooks/mandrill.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import hashlib
import hmac
from base64 import b64encode
from django.utils.crypto import constant_time_compare
from django.utils.timezone import utc

from .base import AnymailBaseWebhookView
Expand Down Expand Up @@ -44,7 +45,7 @@ def validate_request(self, request):

expected_signature = b64encode(hmac.new(key=self.webhook_key, msg=signed_data.encode('utf-8'),
digestmod=hashlib.sha1).digest())
if not hmac.compare_digest(signature, expected_signature):
if not constant_time_compare(signature, expected_signature):
raise AnymailWebhookValidationFailure("Mandrill webhook called with incorrect signature")


Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def long_description_from_readme(rst):
},
include_package_data=True,
test_suite="runtests.runtests",
tests_require=["mock"],
tests_require=["mock", "sparkpost"],
classifiers=[
"Development Status :: 2 - Pre-Alpha",
"Programming Language :: Python",
Expand Down
13 changes: 4 additions & 9 deletions tests/test_sparkpost_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from datetime import datetime, date
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
import os

import requests
import six
Expand All @@ -17,13 +18,6 @@
AnymailConfigurationError)
from anymail.message import attach_inline_image_file

try:
# noinspection PyUnresolvedReferences
from test.support import EnvironmentVarGuard # python3
except ImportError:
# noinspection PyUnresolvedReferences
from test.test_support import EnvironmentVarGuard # python2

from .utils import AnymailTestMixin, decode_att, SAMPLE_IMAGE_FILENAME, sample_image_path, sample_image_content


Expand Down Expand Up @@ -579,8 +573,9 @@ def test_missing_api_key(self):

def test_api_key_in_env(self):
"""SparkPost package allows API key in env var; make sure Anymail works with that"""
with EnvironmentVarGuard() as env:
env['SPARKPOST_API_KEY'] = 'key_from_environment'
with patch.dict(
os.environ,
{'SPARKPOST_API_KEY': 'key_from_environment'}):
conn = mail.get_connection()
# Poke into implementation details to verify:
self.assertIsNone(conn.api_key) # Anymail prop
Expand Down

0 comments on commit 8c38b69

Please sign in to comment.