Skip to content

Commit

Permalink
Adding mailgun sample
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Wayne Parrott committed Oct 21, 2015
1 parent f2e19a5 commit bc5fe6a
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 0 deletions.
1 change: 1 addition & 0 deletions appengine/mailgun/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
lib
Empty file added appengine/mailgun/README.md
Empty file.
Empty file added appengine/mailgun/__init__.py
Empty file.
7 changes: 7 additions & 0 deletions appengine/mailgun/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: .*
script: main.app
4 changes: 4 additions & 0 deletions appengine/mailgun/appengine_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from google.appengine.ext import vendor

# Add any libraries installed in the "lib" folder.
vendor.add('lib')
103 changes: 103 additions & 0 deletions appengine/mailgun/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env python

# Copyright 2015 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Sample Google App Engine application that sends mail using Mailgun.
"""
from urllib import urlencode

import httplib2
import webapp2


# Your Mailgun Domain Name
MAILGUN_DOMAIN_NAME = 'your-mailgun-domain-name'
# Your Mailgun API key
MAILGUN_API_KEY = 'your-mailgun-api-key'


# [START simple_message]
def send_simple_message(recipient):
http = httplib2.Http()
http.add_credentials('api', MAILGUN_API_KEY)

url = 'https://api.mailgun.net/v3/{}/messages'.format(MAILGUN_DOMAIN_NAME)
data = {
'from': 'Example Sender <mailgun@{}>'.format(MAILGUN_DOMAIN_NAME),
'to': recipient,
'subject': 'This is an example email from Mailgun',
'text': 'Test message from Mailgun'
}

resp, content = http.request(url, 'POST', urlencode(data))

if resp.status != 200:
raise RuntimeError(
'Mailgun API error: {} {}'.format(resp.status, content))
# [END simple_message]


# [START complex_message]
def send_complex_message(recipient):
http = httplib2.Http()
http.add_credentials('api', MAILGUN_API_KEY)

url = 'https://api.mailgun.net/v3/{}/messages'.format(MAILGUN_DOMAIN_NAME)
data = {
'from': 'Example Sender <mailgun@{}>'.format(MAILGUN_DOMAIN_NAME),
'to': recipient,
'subject': 'This is an example email from Mailgun',
'text': 'Test message from Mailgun',
'html': '<html>HTML <strong>version</strong> of the body</html>'
}

resp, content = http.request(url, 'POST', urlencode(data))

if resp.status != 200:
raise RuntimeError(
'Mailgun API error: {} {}'.format(resp.status, content))
# [END complex_message]


class MainPage(webapp2.RequestHandler):
def get(self):
self.response.content_type = 'text/html'
self.response.write("""
<!doctype html>
<html><body>
<form method="POST">
<input type="text" name="recipient" placeholder="Enter recipient email">
<input type="submit" name="submit" value="Send simple email">
<input type="submit" name="submit" value="Send complex email">
</form>
</body></html>
""")

def post(self):
recipient = self.request.get('recipient')
action = self.request.get('submit')

if action == 'Send simple email':
send_simple_message(recipient)
else:
send_complex_message(recipient)

self.response.write('Mail sent')


app = webapp2.WSGIApplication([
('/', MainPage)
], debug=True)
55 changes: 55 additions & 0 deletions appengine/mailgun/main_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from tests import AppEngineTestbedCase, Http2Mock
import webtest

from . import main


class TestMailgunHandlers(AppEngineTestbedCase):
def setUp(self):
super(TestMailgunHandlers, self).setUp()

self.app = webtest.TestApp(main.app)

def test_get(self):
response = self.app.get('/')
self.assertEqual(response.status_int, 200)

def test_post(self):
http = Http2Mock(responses=[{}])

with http:
response = self.app.post('/', {
'recipient': 'jonwayne@google.com',
'submit': 'Send simple email'})

self.assertEqual(response.status_int, 200)

http = Http2Mock(responses=[{}])

with http:
response = self.app.post('/', {
'recipient': 'jonwayne@google.com',
'submit': 'Send complex email'})

self.assertEqual(response.status_int, 200)

http = Http2Mock(responses=[{'status': 500, 'body': 'Test error'}])

with http, self.assertRaises(Exception):
self.app.post('/', {
'recipient': 'jonwayne@google.com',
'submit': 'Send simple email'})
1 change: 1 addition & 0 deletions appengine/mailgun/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
httplib2
2 changes: 2 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
AppEngineTestbedCase,
capture_stdout,
CloudBaseTest,
Http2Mock,
RESOURCE_PATH)


__all__ = [
'AppEngineTestbedCase',
'capture_stdout',
'CloudBaseTest',
'Http2Mock',
'RESOURCE_PATH'
]
29 changes: 29 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import tempfile
import unittest

import httplib2
from nose.plugins.skip import SkipTest
from six.moves import cStringIO

Expand Down Expand Up @@ -135,3 +136,31 @@ def capture_stdout():
yield fake_stdout
finally:
sys.stdout = old_stdout


class Http2Mock(object):
"""Mock httplib2.Http"""

def __init__(self, responses):
self.responses = responses

def add_credentials(self, user, pwd):
self.credentials = (user, pwd)

def request(self, token_uri, method, body, headers=None, *args, **kwargs):
response = self.responses.pop(0)
self.status = response.get('status', 200)
self.body = response.get('body', '')
self.headers = response.get('headers', '')
return (self, self.body)

def __enter__(self):
self.httplib2_orig = httplib2.Http
httplib2.Http = self
return self

def __exit__(self, exc_type, exc_value, traceback):
httplib2.Http = self.httplib2_orig

def __call__(self, *args, **kwargs):
return self

0 comments on commit bc5fe6a

Please sign in to comment.