diff --git a/appengine/mailjet/.gitignore b/appengine/mailjet/.gitignore new file mode 100644 index 00000000000..a65b41774ad --- /dev/null +++ b/appengine/mailjet/.gitignore @@ -0,0 +1 @@ +lib diff --git a/appengine/mailjet/README.md b/appengine/mailjet/README.md new file mode 100644 index 00000000000..3880c174d4d --- /dev/null +++ b/appengine/mailjet/README.md @@ -0,0 +1,11 @@ +# Python Mailjet email sample for Google App Engine Standard + +This sample demonstrates how to use [Mailjet](https://www.mailgun.com) on [Google App Engine Standard](https://cloud.google.com/appengine/docs/). + +## Setup + +Before you can run or deploy the sample, you will need to do the following: + +1. [Create a Mailjet Account](http://www.mailjet.com/google). + +2. Configure your Mailjet settings in the environment variables section in ``app.yaml``. diff --git a/appengine/mailjet/app.yaml b/appengine/mailjet/app.yaml new file mode 100644 index 00000000000..467dd8e55be --- /dev/null +++ b/appengine/mailjet/app.yaml @@ -0,0 +1,14 @@ +runtime: python27 +threadsafe: yes +api_version: 1 + +handlers: +- url: .* + script: main.app + +# [START env_variables] +env_variables: + MAILJET_API_KEY: your-mailjet-api-key + MAILJET_API_SECRET: your-mailjet-api-secret + MAILJET_SENDER: your-mailjet-sender-address +# [END env_variables] diff --git a/appengine/mailjet/appengine_config.py b/appengine/mailjet/appengine_config.py new file mode 100644 index 00000000000..c903d9a0ac5 --- /dev/null +++ b/appengine/mailjet/appengine_config.py @@ -0,0 +1,18 @@ +# Copyright 2016 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. + +from google.appengine.ext import vendor + +# Add any libraries installed in the "lib" folder. +vendor.add('lib') diff --git a/appengine/mailjet/main.py b/appengine/mailjet/main.py new file mode 100644 index 00000000000..cd7c584e751 --- /dev/null +++ b/appengine/mailjet/main.py @@ -0,0 +1,77 @@ +# Copyright 2016 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. + +# [START app] +import logging +import os + +from flask import Flask, render_template, request +# [start config] +import mailjet_rest +import requests_toolbelt.adapters.appengine + +# Use the App Engine requests adapter to allow the requests library to be +# used on App Engine. +requests_toolbelt.adapters.appengine.monkeypatch() + +MAILJET_API_KEY = os.environ['MAILJET_API_KEY'] +MAILJET_API_SECRET = os.environ['MAILJET_API_SECRET'] +MAILJET_SENDER = os.environ['MAILJET_SENDER'] +# [END config] + +app = Flask(__name__) + + +# [START send_message] +def send_message(to): + client = mailjet_rest.Client( + auth=(MAILJET_API_KEY, MAILJET_API_SECRET)) + + data = { + 'FromEmail': MAILJET_SENDER, + 'FromName': 'App Engine Flex Mailjet Sample', + 'Subject': 'Example email.', + 'Text-part': 'This is an example email.', + 'Html-part': 'This is an example email.', + 'Recipients': [{'Email': to}] + } + + result = client.send.create(data=data) + + return result.json() +# [END send_message] + + +@app.route('/') +def index(): + return render_template('index.html') + + +@app.route('/send/email', methods=['POST']) +def send_email(): + to = request.form.get('to') + + result = send_message(to) + + return 'Email sent, response:
{}'.format(result) + + +@app.errorhandler(500) +def server_error(e): + logging.exception('An error ocurred during a request.') + return """ + An internal error occurred:
{}+ See logs for full stacktrace. + """.format(e), 500 +# [END app] diff --git a/appengine/mailjet/main_test.py b/appengine/mailjet/main_test.py new file mode 100644 index 00000000000..c910f48c544 --- /dev/null +++ b/appengine/mailjet/main_test.py @@ -0,0 +1,53 @@ +# Copyright 2016 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. + +import re + +import pytest +import responses + + +@pytest.fixture +def app(monkeypatch): + monkeypatch.setenv('MAILJET_API_KEY', 'apikey') + monkeypatch.setenv('MAILJET_API_SECRET', 'apisecret') + monkeypatch.setenv('MAILJET_SENDER', 'sender') + + import main + + main.app.testing = True + return main.app.test_client() + + +def test_index(app): + r = app.get('/') + assert r.status_code == 200 + + +@responses.activate +def test_send_email(app): + responses.add( + responses.POST, + re.compile(r'.*'), + body='{"test": "message"}', + content_type='application/json') + + r = app.post('/send/email', data={'to': 'user@example.com'}) + + assert r.status_code == 200 + assert 'test' in r.data.decode('utf-8') + + assert len(responses.calls) == 1 + request_body = responses.calls[0].request.body + assert 'user@example.com' in request_body diff --git a/appengine/mailjet/requirements.txt b/appengine/mailjet/requirements.txt new file mode 100644 index 00000000000..62ae53b1605 --- /dev/null +++ b/appengine/mailjet/requirements.txt @@ -0,0 +1,4 @@ +Flask==0.10.1 +requests==2.10.0 +requests-toolbelt==0.6.0 +mailjet_rest==1.1.1 diff --git a/appengine/mailjet/templates/index.html b/appengine/mailjet/templates/index.html new file mode 100644 index 00000000000..cd1c93ff5b3 --- /dev/null +++ b/appengine/mailjet/templates/index.html @@ -0,0 +1,29 @@ +{# +# Copyright 2016 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. +#} + + + +
{}'.format(result) + + +@app.errorhandler(500) +def server_error(e): + logging.exception('An error ocurred during a request.') + return """ + An internal error occurred:
{}+ See logs for full stacktrace. + """.format(e), 500 + + +if __name__ == '__main__': + # This is used when running locally. Gunicorn is used to run the + # application on Google App Engine. See entrypoint in app.yaml. + app.run(host='127.0.0.1', port=8080, debug=True) +# [END app] diff --git a/managed_vms/mailjet/main_test.py b/managed_vms/mailjet/main_test.py new file mode 100644 index 00000000000..c910f48c544 --- /dev/null +++ b/managed_vms/mailjet/main_test.py @@ -0,0 +1,53 @@ +# Copyright 2016 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. + +import re + +import pytest +import responses + + +@pytest.fixture +def app(monkeypatch): + monkeypatch.setenv('MAILJET_API_KEY', 'apikey') + monkeypatch.setenv('MAILJET_API_SECRET', 'apisecret') + monkeypatch.setenv('MAILJET_SENDER', 'sender') + + import main + + main.app.testing = True + return main.app.test_client() + + +def test_index(app): + r = app.get('/') + assert r.status_code == 200 + + +@responses.activate +def test_send_email(app): + responses.add( + responses.POST, + re.compile(r'.*'), + body='{"test": "message"}', + content_type='application/json') + + r = app.post('/send/email', data={'to': 'user@example.com'}) + + assert r.status_code == 200 + assert 'test' in r.data.decode('utf-8') + + assert len(responses.calls) == 1 + request_body = responses.calls[0].request.body + assert 'user@example.com' in request_body diff --git a/managed_vms/mailjet/requirements.txt b/managed_vms/mailjet/requirements.txt new file mode 100644 index 00000000000..e4b43f039f0 --- /dev/null +++ b/managed_vms/mailjet/requirements.txt @@ -0,0 +1,4 @@ +Flask==0.10.1 +gunicorn==19.4.5 +requests[security]==2.9.1 +mailjet_rest==1.1.1 diff --git a/managed_vms/mailjet/templates/index.html b/managed_vms/mailjet/templates/index.html new file mode 100644 index 00000000000..19993c3547d --- /dev/null +++ b/managed_vms/mailjet/templates/index.html @@ -0,0 +1,29 @@ +{# +# Copyright 2016 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. +#} + + + +