Skip to content

Commit

Permalink
Merge 8623c79 into 449e6c1
Browse files Browse the repository at this point in the history
  • Loading branch information
Richard Mathie committed Apr 24, 2017
2 parents 449e6c1 + 8623c79 commit e9954b7
Show file tree
Hide file tree
Showing 17 changed files with 58 additions and 35 deletions.
5 changes: 4 additions & 1 deletion .travis.yml
@@ -1,7 +1,10 @@
sudo: false
language: python
python:
- '2.7'
- "2.7"
#- "3.3"
#- "3.5"
- pypy-5.3.1
env:
global:
- MAILGUN_API_KEY=testtesttest
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -9,7 +9,7 @@
[![License](https://img.shields.io/pypi/l/Flask-MailGun3.svg)](https://pypi.python.org/pypi/Flask-MailGun3)
[![Downloads](https://img.shields.io/pypi/dm/flask-mailgun3.svg)](https://pypi.python.org/pypi/Flask-Mailgun3)

Flask MailGun extension to use the [MailGun](https://mailgun.com) email parsing service for sending and receiving emails.
Flask-MailGun Flask extension to use the [MailGun](https://mailgun.com) email parsing service for sending and receiving emails.

## What it does

Expand Down
5 changes: 3 additions & 2 deletions README.rst
Expand Up @@ -4,8 +4,9 @@ Flask-MailGun
|Latest Version| |Build Status| |Coverage Status| |Code Climate| |Python
Versions| |License| |Downloads|

Flask MailGun extension to use the `MailGun <https://mailgun.com>`__
email parsing service for sending and receiving emails.
Flask-MailGun Flask extension to use the
`MailGun <https://mailgun.com>`__ email parsing service for sending and
receiving emails.

What it does
------------
Expand Down
2 changes: 1 addition & 1 deletion Version
@@ -1 +1 @@
0.1.4
0.1.5
17 changes: 11 additions & 6 deletions flask_mailgun/api.py
Expand Up @@ -22,11 +22,12 @@
class MailGunAPI(object):
def __init__(self, config):
self.domain = config['MAILGUN_DOMAIN']
self.api_key = config['MAILGUN_API_KEY']
self.api_key = config['MAILGUN_API_KEY'].encode('utf-8')
self.api_url = config.get('MAILGUN_API_URL',
MAILGUN_API_URL)
self.route = config.get('MAILGUN_ROUTE', 'uploads')
self.host = config.get('MAILGUN_HOST', self.domain)
self.dest = '/messages/'
if self.api_key is None:
raise MailGunException("No mailgun key supplied.")

Expand Down Expand Up @@ -117,13 +118,16 @@ def get_route_id(self, route):
""" Get id of the route
Return: id of the route. None if not exist.
"""
def make_key(route):
return route["expression"].join(route["action"])
def make_key(_route):
return _route["expression"].join(_route["action"])

# TODO RPM YXI, not actually shure this is what we want...
routes = self.list_routes()
if routes:
id_table = dict((make_key(r), r["id"]) for r in routes)
return id_table.get(make_key(route)) if routes else None
return id_table.get(make_key(route))
else:
return None

def verify_email(self, email):
"""Check that the email post came from mailgun
Expand All @@ -137,8 +141,9 @@ def verify_email(self, email):
if timestamp is None or token is None or signature is None:
raise MailGunException("Mailbox Error: credential verification failed.", "Not enough parameters")

message = '{}{}'.format(timestamp, token).encode('utf-8')
signature_calc = hmac.new(key=self.api_key,
msg='{}{}'.format(timestamp, token),
msg=message,
digestmod=hashlib.sha256).hexdigest()
if signature != signature_calc:
raise MailGunException("Mailbox Error: credential verification failed.", "Signature doesn't match")
Expand All @@ -157,4 +162,4 @@ def routepoint(self):

@property
def auth(self):
return ('api', self.api_key)
return 'api', self.api_key
4 changes: 2 additions & 2 deletions flask_mailgun/attachment.py
Expand Up @@ -38,7 +38,7 @@ def attachment_decorator(f, email, filename):
"""Converts a file back into a FileStorage Object"""
with open(filename, 'r') as file:
attachment = FileStorage(stream=file,
filename=filename)
filename=filename.encode('utf-8'))
result = f(email, attachment)
return result

Expand Down Expand Up @@ -90,7 +90,7 @@ class Attachment(object):

def __init__(self, filename=None, content_type=None, data=None,
disposition=None, headers=None):
self.filename = filename
self.filename = filename.encode('utf-8')
self.content_type = content_type
self.data = data
self.disposition = disposition or 'attachment'
Expand Down
2 changes: 1 addition & 1 deletion flask_mailgun/message.py
Expand Up @@ -52,7 +52,7 @@ def __init__(self, subject='',
sender = sender or current_app.extensions['mail'].default_sender

if isinstance(sender, tuple):
sender = "%s <%s>" % sender
sender = "{0} <{1}>".format(*sender)

self.recipients = recipients or []
self.subject = subject
Expand Down
4 changes: 2 additions & 2 deletions flask_mailgun/processing.py
@@ -1,7 +1,7 @@
from threading import Thread
from functools import wraps
from multiprocessing import Pool

from decorator import decorator
from functools import wraps


def async_pool(pool_size):
Expand Down
4 changes: 0 additions & 4 deletions requirements_test.in

This file was deleted.

15 changes: 10 additions & 5 deletions setup.py
@@ -1,26 +1,30 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Flask-MailGun
Flask extension to use the Mailgun email parsing service
for sending and receving emails
"""
from pip.req import parse_requirements
from io import open
try:
from setuptools import setup
except ImportError:
from distutils.core import setup


with open('Version', 'r') as f:
version = next(f).strip().decode('utf-8')
with open('Version', encoding='utf-8') as f:
version = next(f).strip()

with open('README.rst') as f:
with open('README.rst', encoding='utf-8') as f:
readme = f.read()

# parse_requirements() returns generator of pip.req.InstallRequirement objects
requirements = parse_requirements('requirements.txt', session=False)
requirements = [str(ir.req) for ir in requirements]

__NAME__ = 'Flask-MailGun3'
__doc__ = readme
__author__ = 'Amey-SAM'
__license__ = 'MIT'
__copyright__ = '2016'
Expand All @@ -35,8 +39,8 @@
author_email='richard.mathie@amey.co.uk',
url='https://github.com/amey-sam/Flask-MailGun',
download_url='https://github.com/amey-sam/Flask-MailGun/tarball/master',
py_modules=['flask_mailgun'],
# packages=['flask_mailgun'],
# py_modules=['flask_mailgun'],
packages=['flask_mailgun'],
install_requires=requirements,
keywords=['flask', 'mailgun'],
zip_safe=False,
Expand All @@ -53,3 +57,4 @@
'Topic :: Software Development :: Libraries :: Python Modules'
]
)

1 change: 1 addition & 0 deletions tests/fixtures/__init__.py
Expand Up @@ -13,3 +13,4 @@ def get_attachment():
f_name = os.path.join(fixture_dir, filename)
file_stream = open(f_name, "r")
return (filename, file_stream)

6 changes: 4 additions & 2 deletions tests/fixtures/email.py
Expand Up @@ -13,7 +13,7 @@
from tests.fixtures import get_attachment
from flask_mailgun.message import Message

url_safe_chars = string.lowercase+string.digits+string.uppercase
url_safe_chars = string.ascii_lowercase + string.ascii_uppercase + string.digits


def random_string(length):
Expand All @@ -24,8 +24,10 @@ def sign_email(email, mailgun):
token = random_string(50)
timestamp = int(time())
api_key = mailgun.mailgun_api.api_key
message = '{}{}'.format(timestamp, token).encode('utf-8')

signature = hmac.new(key=api_key,
msg='{}{}'.format(timestamp, token),
msg=message,
digestmod=hashlib.sha256).hexdigest()
email.update(dict(token=token,
timestamp=timestamp,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_async.py
Expand Up @@ -6,7 +6,7 @@


def runner(fun):
results = [fun(i) for i in xrange(20)]
results = [fun(i) for i in range(20)]
for result in results:
result.wait()
result.get()
Expand Down
12 changes: 7 additions & 5 deletions tests/test_receve.py
Expand Up @@ -4,6 +4,7 @@
@author: richard
"""
from __future__ import print_function
import unittest
import time
from flask_mailgun.utils import MailGunException
Expand Down Expand Up @@ -56,7 +57,7 @@ def attachment_func(email, attachment):
responce = self.attachment_mock(email, attachment)
data = attachment.read()
len(data)
for i in xrange(10):
for i in range(10):
time.sleep(0.1)

return responce
Expand All @@ -70,7 +71,7 @@ def test_receive_message(self):
time.sleep(1)
self.assertEqual(self.receve_email_mock.call_count, 1)
self.assertEqual(self.attachment_mock.call_count, 1)
print "received email"
print ("received email")


class ReceiveMessageAsyncTest(ReceiveMessageCallbacksTest):
Expand All @@ -94,16 +95,17 @@ def test_receive_2_messages(self):
time.sleep(1)
# self.assertEqual(self.receve_email_mock.call_count, 2)
# self.assertEqual(self.attachment_mock.call_count, 2)
print "received 2 emails"
print ("received 2 emails")

def test_receive_100_messages(self):
for i in xrange(100):
for i in range(100):
email = make_email_request(self.mailgun)
response = self.appclient.post('/upload', data=email)
self.assertEqual(response.status_code, 200)
# self.assertEqual(self.receve_email_mock.call_count, 100)
# self.assertEqual(self.attachment_mock.call_count, 100)
print "received 100 emails"
print ("received 100 emails")


if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion tests/test_save_attachments.py
Expand Up @@ -8,7 +8,7 @@
import os
import shutil
import tempfile
from werkzeug import FileStorage
from werkzeug.datastructures import FileStorage
from flask_mailgun.attachment import save_attachments
from tests.fixtures import get_attachment
from tests import MailgunTestBase
Expand Down
2 changes: 1 addition & 1 deletion tests/test_send.py
Expand Up @@ -23,7 +23,7 @@ def test_send_simple_message(self):
data = self.mock_post.call_args[1]['data']
# files = self.mock_post.call_args[1]['files']
self.assertEqual(url, 'https://api.mailgun.net/v3/example.com/messages')
self.assertEqual(auth, ('api', 'testtesttest'))
self.assertEqual(auth, ('api', b'testtesttest'))
# self.assertEqual(files, [])
self.assertEqual(data['from'], message.sender)
self.assertEqual(data['to'], set(message.recipients))
Expand Down
8 changes: 8 additions & 0 deletions tox.ini
@@ -0,0 +1,8 @@
[tox]
envlist = python{2.7,3.3,3.4,3.5,3.6}

[testenv]
deps =
-r{toxinidir}/requirements_test.in
commands =
nosetests tests

0 comments on commit e9954b7

Please sign in to comment.