Skip to content

Instantly share code, notes, and snippets.

@alejandrobernardis
Last active August 29, 2015 14:08
Show Gist options
  • Save alejandrobernardis/957fe8b4ad45902ae8d2 to your computer and use it in GitHub Desktop.
Save alejandrobernardis/957fe8b4ad45902ae8d2 to your computer and use it in GitHub Desktop.
(Tornado Async) A little hack for boto.SESConnections
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
# Copyright (c) 2014 Asumi Kamikaze Inc.
# Licensed under the MIT License.
# Author: Alejandro M. Bernardis
# Email: alejandro (dot) bernardis (at) asumikamikaze (dot) com
# Created: 06/Nov/2014 19:27
import boto
from boto import jsonresponse
from boto.connection import AWSAuthConnection
from boto.ses import SESConnection
from tornado import gen
from tornado.httpclient import AsyncHTTPClient, HTTPRequest, HTTPResponse
from urllib import urlencode
__all__ = (
'AsyncSESConnection',
'AWS_SES_ENDPOINTS',
'AWS_SES_SUPPORTED_ARGS'
)
class SESHTTPResponse(object):
def __init__(self, status, reason):
self.status = status
self.reason = reason
class AsyncAWSAuthConnection(AWSAuthConnection):
@gen.coroutine
def _mexe(self, request, sender=None, *args, **kwargs):
if not isinstance(request.body, bytes) \
and hasattr(request.body, 'encode'):
request.body = request.body.encode('utf-8')
request.authorize(connection=self)
boto.log.debug('Method: %s' % request.method)
boto.log.debug('Path: %s' % request.path)
boto.log.debug('Data: %s' % request.body)
boto.log.debug('Headers: %s' % request.headers)
boto.log.debug('Host: %s' % request.host)
boto.log.debug('Port: %s' % request.port)
boto.log.debug('Params: %s' % request.params)
url = '{protocol}://{host}:{port}{path}'\
.format(protocol=request.protocol, host=request.host,
port=request.port, path=request.path)
async_request = HTTPRequest(url)
async_request.method = request.method
async_request.headers = request.headers
if request.body:
async_request.body = request.body
if callable(sender):
async_response = yield sender(async_request)
else:
async_response = yield AsyncHTTPClient().fetch(async_request)
raise gen.Return(async_response)
AWS_SES_ENDPOINTS = {
"eu-west-1": "email.eu-west-1.amazonaws.com",
"us-east-1": "email.us-east-1.amazonaws.com",
"us-west-2": "email.us-west-2.amazonaws.com",
"eu-central-1": "email.eu-central-1.amazonaws.com"
}
AWS_SES_SUPPORTED_ARGS = (
'aws_access_key_id', 'aws_secret_access_key', 'is_secure', 'port',
'proxy', 'proxy_port', 'proxy_user', 'proxy_pass', 'debug',
'https_connection_factory', 'region', 'path', 'security_token',
'validate_certs', 'profile_name'
)
class AsyncSESConnection(AsyncAWSAuthConnection, SESConnection):
_content_type = 'application/x-www-form-urlencoded; charset=UTF-8'
@gen.coroutine
def _make_request(self, action, params=None):
headers = {'Content-Type': self._content_type}
try:
if not params:
params = {}
params['Action'] = action
for key, value in params.items():
if not isinstance(value, unicode):
continue
params[key] = value.encode()
response = yield self.make_request(
'POST', '/', headers=headers, data=urlencode(params))
if isinstance(response, HTTPResponse):
body = response.body.decode('utf-8')
if response.code == 200:
response = jsonresponse.Element(
list_marker=('VerifiedEmailAddresses', 'Identities',
'DkimTokens', 'VerificationAttributes',
'SendDataPoints'),
item_marker=('member', 'item', 'entry')
)
json_response = jsonresponse.XmlHandler(response, None)
json_response.parse(body)
else:
response = SESHTTPResponse(response.code, response.reason)
self._handle_error(response, body)
else:
response = ValueError('Bad response')
except Exception, e:
response = ValueError(str(e))
raise gen.Return(response)
# --- test ---
@gen.coroutine
def run():
from boto.regioninfo import RegionInfo
AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient")
keys = ['key', 'secret_key']
region = RegionInfo(None, 'us-west-2', 'email.us-west-2.amazonaws.com')
ses = AsyncSESConnection(region=region, *keys)
try:
res = yield ses.list_verified_email_addresses()
print res
except Exception, e:
print e
ioloop.IOLoop.instance().stop()
run()
from tornado import ioloop
ioloop.IOLoop.instance().start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment