From 102f134cf7824a586ff015c0535fa7b1b7b254d2 Mon Sep 17 00:00:00 2001 From: Richard Kiss Date: Wed, 16 Mar 2011 19:47:57 -0700 Subject: [PATCH 1/2] Allow contents of EmailMessage to be set in constructor. --- amazon_ses.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/amazon_ses.py b/amazon_ses.py index 046ed48..4f5e31d 100644 --- a/amazon_ses.py +++ b/amazon_ses.py @@ -103,11 +103,11 @@ def sendEmail(self, source, toAddresses, message, replyToAddresses=None, returnP class EmailMessage: - def __init__(self): + def __init__(self, subject=None, bodyHtml=None, bodyText=None): self.charset = 'UTF-8' - self.subject = None - self.bodyHtml = None - self.bodyText = None + self.subject = subject + self.bodyHtml = bodyHtml + self.bodyText = bodyText From adba04057a0e5bea060083c5307ff552924267df Mon Sep 17 00:00:00 2001 From: Richard Kiss Date: Wed, 16 Mar 2011 19:53:10 -0700 Subject: [PATCH 2/2] Remove end of line whitespace. --- README.txt | 8 ++--- amazon_ses.py | 98 +++++++++++++++++++++++++-------------------------- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/README.txt b/README.txt index d7241ab..f235f11 100644 --- a/README.txt +++ b/README.txt @@ -18,18 +18,18 @@ message = EmailMessage() message.subject = 'Hello from Amazon SES! Test subject' message.bodyText = 'This is body text of test message.' -result = amazonSes.sendEmail('username@yourdomaintest.com', 'testmail@yourdomaintest.com', message) +result = amazonSes.sendEmail('username@yourdomaintest.com', 'testmail@yourdomaintest.com', message) print result.requestId print result.messageId -I want you to notice that in case Amazon returns some error, the API will raise an exception AmazonError which will contain errorType, code and message. +I want you to notice that in case Amazon returns some error, the API will raise an exception AmazonError which will contain errorType, code and message. If your Amazon SES account is not switched to production use, you can send a message only from/to verified email addresses. Here is an example of how to verify the email using the API: result = amazonSes.verifyEmailAddress('username@yourdomaintest.com') print result.requestId -You will receive the confirmation with a link which you should click to verify your email. +You will receive the confirmation with a link which you should click to verify your email. An example of how to receive information about SendQuota: @@ -44,7 +44,7 @@ VerifyEmailAddress DeleteVerifiedEmailAddress GetSendQuota ListVerifiedEmailAddresses -Methods return instances of AmazonResult or derived class (for example, method amazonSes.getSendQuota() returns the instance of AmazonSendQuota). +Methods return instances of AmazonResult or derived class (for example, method amazonSes.getSendQuota() returns the instance of AmazonSendQuota). Author =============== diff --git a/amazon_ses.py b/amazon_ses.py index 4f5e31d..53b5118 100644 --- a/amazon_ses.py +++ b/amazon_ses.py @@ -1,4 +1,4 @@ -#Copyright (c) 2011 Vladimir Pankratiev http://tagmask.com +#Copyright (c) 2011 Vladimir Pankratiev http://tagmask.com # #Permission is hereby granted, free of charge, to any person obtaining a copy #of this software and associated documentation files (the "Software"), to deal @@ -38,7 +38,7 @@ def __init__(self, accessKeyID, secretAccessKey): def _getSignature(self, dateValue): h = hmac.new(key=self._secretAccessKey, msg=dateValue, digestmod=hashlib.sha256) return base64.b64encode(h.digest()).decode() - + def _getHeaders(self): headers = { 'Content-type': 'application/x-www-form-urlencoded' } d = datetime.utcnow() @@ -47,11 +47,11 @@ def _getHeaders(self): signature = self._getSignature(dateValue) headers['X-Amzn-Authorization'] = 'AWS3-HTTPS AWSAccessKeyId=%s, Algorithm=HMACSHA256, Signature=%s' % (self._accessKeyID, signature) return headers - + def _performAction(self, actionName, params=None): if not params: params = {} - params['Action'] = actionName + params['Action'] = actionName #https://email.us-east-1.amazonaws.com/ conn = httplib.HTTPSConnection('email.us-east-1.amazonaws.com') params = urllib.urlencode(params) @@ -60,24 +60,24 @@ def _performAction(self, actionName, params=None): responseResult = response.read() conn.close() return self._responseParser.parse(actionName, response.status, response.reason, responseResult) - + def verifyEmailAddress(self, emailAddress): params = { 'EmailAddress': emailAddress } return self._performAction('VerifyEmailAddress', params) - + def deleteVerifiedEmailAddress(self, emailAddress): params = { 'EmailAddress': emailAddress } return self._performAction('DeleteVerifiedEmailAddress', params) - + def getSendQuota(self): return self._performAction('GetSendQuota') - + def getSendStatistics(self): return self._performAction('GetSendStatistics') - + def listVerifiedEmailAddresses(self): return self._performAction('ListVerifiedEmailAddresses') - + def sendEmail(self, source, toAddresses, message, replyToAddresses=None, returnPath=None, ccAddresses=None, bccAddresses=None): params = { 'Source': source } for objName, addresses in zip(["ToAddresses", "CcAddresses", "BccAddresses"], [toAddresses, ccAddresses, bccAddresses]): @@ -86,10 +86,10 @@ def sendEmail(self, source, toAddresses, message, replyToAddresses=None, returnP for i, address in enumerate(addresses, 1): params['Destination.%s.member.%d' % (objName, i)] = address else: - params['Destination.%s.member.1' % objName] = addresses + params['Destination.%s.member.1' % objName] = addresses if not returnPath: returnPath = source - params['ReturnPath'] = returnPath + params['ReturnPath'] = returnPath params['Message.Subject.Charset'] = message.charset params['Message.Subject.Data'] = message.subject if message.bodyText: @@ -116,29 +116,29 @@ def __init__(self, errorType, code, message): self.errorType = errorType self.code = code self.message = message - + class AmazonAPIError(Exception): def __init__(self, message): self.message = message - - - + + + class AmazonResult: def __init__(self, requestId): self.requestId = requestId - + class AmazonSendEmailResult(AmazonResult): def __init__(self, requestId, messageId): self.requestId = requestId self.messageId = messageId - + class AmazonSendQuota(AmazonResult): def __init__(self, requestId, max24HourSend, maxSendRate, sentLast24Hours): self.requestId = requestId self.max24HourSend = max24HourSend self.maxSendRate = maxSendRate self.sentLast24Hours = sentLast24Hours - + class AmazonSendDataPoint: def __init__(self, bounces, complaints, deliveryAttempts, rejects, timestamp): self.bounces = bounces @@ -146,105 +146,105 @@ def __init__(self, bounces, complaints, deliveryAttempts, rejects, timestamp): self.deliveryAttempts = deliveryAttempts self.rejects = rejects self.timestamp = timestamp - + class AmazonSendStatistics(AmazonResult): def __init__(self, requestId): self.requestId = requestId - self.members = [] - + self.members = [] + class AmazonVerifiedEmails(AmazonSendStatistics): pass - + class AmazonResponseParser: class XmlResponse: def __init__(self, str): self._rootElement = XML(str) self._namespace = self._rootElement.tag[1:].split("}")[0] - + def checkResponseName(self, name): if self._rootElement.tag == self._fixTag(self._namespace, name): return True else: - raise AmazonAPIError('ErrorResponse is invalid.') - + raise AmazonAPIError('ErrorResponse is invalid.') + def checkActionName(self, actionName): if self._rootElement.tag == self._fixTag(self._namespace, ('%sResponse' % actionName)): return True else: raise AmazonAPIError('Response of action "%s" is invalid.' % actionName) - + def getChild(self, *itemPath): node = self._findNode(self._rootElement, self._namespace, *itemPath) if node != None: return node else: raise AmazonAPIError('Node with the specified path was not found.') - - def getChildText(self, *itemPath): - node = self.getChild(*itemPath) + + def getChildText(self, *itemPath): + node = self.getChild(*itemPath) return node.text - + def _fixTag(self, namespace, tag): return '{%s}%s' % (namespace, tag) def _findNode(self, rootElement, namespace, *args): match = '.' for s in args: - match += '/{%s}%s' % (namespace, s) - return rootElement.find(match) - - + match += '/{%s}%s' % (namespace, s) + return rootElement.find(match) + + def __init__(self): self._simpleResultActions = ['DeleteVerifiedEmailAddress', 'VerifyEmailAddress'] - - def _parseSimpleResult(self, actionName, xmlResponse): + + def _parseSimpleResult(self, actionName, xmlResponse): if xmlResponse.checkActionName(actionName): requestId = xmlResponse.getChildText('ResponseMetadata', 'RequestId') return AmazonResult(requestId) - + def _parseSendQuota(self, actionName, xmlResponse): if xmlResponse.checkActionName(actionName): requestId = xmlResponse.getChildText('ResponseMetadata', 'RequestId') - value = xmlResponse.getChildText('GetSendQuotaResult', 'Max24HourSend') + value = xmlResponse.getChildText('GetSendQuotaResult', 'Max24HourSend') max24HourSend = float(value) value = xmlResponse.getChildText('GetSendQuotaResult', 'MaxSendRate') maxSendRate = float(value) value = xmlResponse.getChildText('GetSendQuotaResult', 'SentLast24Hours') sentLast24Hours = float(value) return AmazonSendQuota(requestId, max24HourSend, maxSendRate, sentLast24Hours) - + #def _parseSendStatistics(self, actionName, xmlResponse): # if xmlResponse.checkActionName(actionName): # requestId = xmlResponse.getChildText('ResponseMetadata', 'RequestId') - + def _parseListVerifiedEmails(self, actionName, xmlResponse): if xmlResponse.checkActionName(actionName): requestId = xmlResponse.getChildText('ResponseMetadata', 'RequestId') node = xmlResponse.getChild('ListVerifiedEmailAddressesResult', 'VerifiedEmailAddresses') result = AmazonVerifiedEmails(requestId) - for addr in node: + for addr in node: result.members.append(addr.text) return result - + def _parseSendEmail(self, actionName, xmlResponse): if xmlResponse.checkActionName(actionName): requestId = xmlResponse.getChildText('ResponseMetadata', 'RequestId') messageId = xmlResponse.getChildText('SendEmailResult', 'MessageId') return AmazonSendEmailResult(requestId, messageId) - + def _raiseError(self, xmlResponse): if xmlResponse.checkResponseName('ErrorResponse'): errorType = xmlResponse.getChildText('Error', 'Type') code = xmlResponse.getChildText('Error', 'Code') message = xmlResponse.getChildText('Error', 'Message') raise AmazonError(errorType, code, message) - - def parse(self, actionName, statusCode, reason, responseResult): + + def parse(self, actionName, statusCode, reason, responseResult): xmlResponse = self.XmlResponse(responseResult) log.info('Response status code: %s, reason: %s', statusCode, reason) log.debug(responseResult) - - result = None + + result = None if statusCode != 200: self._raiseError(xmlResponse) else: @@ -257,7 +257,7 @@ def parse(self, actionName, statusCode, reason, responseResult): #elif actionName == 'GetSendStatistics': # result = self._parseSendStatistics(actionName, xmlResponse) elif actionName == 'ListVerifiedEmailAddresses': - result = self._parseListVerifiedEmails(actionName, xmlResponse) + result = self._parseListVerifiedEmails(actionName, xmlResponse) else: raise AmazonAPIError('Action %s is not supported. Please contact: vladimir@tagmask.com' % (actionName,)) return result