Merge pull request #2439 from Kerl1310/feature/send_templated_email

#2437 Implementing send_templated_email
This commit is contained in:
Mike Grima 2019-10-03 11:49:45 -07:00 committed by GitHub
commit 567a6da31d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 112 additions and 5 deletions

View File

@ -57,3 +57,4 @@ Moto is written by Steve Pulec with contributions from:
* [Bendeguz Acs](https://github.com/acsbendi) * [Bendeguz Acs](https://github.com/acsbendi)
* [Craig Anderson](https://github.com/craiga) * [Craig Anderson](https://github.com/craiga)
* [Robert Lewis](https://github.com/ralewis85) * [Robert Lewis](https://github.com/ralewis85)
* [Kyle Jones](https://github.com/Kerl1310)

View File

@ -5696,7 +5696,7 @@
- [ ] update_service - [ ] update_service
## ses ## ses
12% implemented 14% implemented
- [ ] clone_receipt_rule_set - [ ] clone_receipt_rule_set
- [ ] create_configuration_set - [ ] create_configuration_set
- [ ] create_configuration_set_event_destination - [ ] create_configuration_set_event_destination
@ -5747,7 +5747,7 @@
- [ ] send_custom_verification_email - [ ] send_custom_verification_email
- [X] send_email - [X] send_email
- [X] send_raw_email - [X] send_raw_email
- [ ] send_templated_email - [X] send_templated_email
- [ ] set_active_receipt_rule_set - [ ] set_active_receipt_rule_set
- [ ] set_identity_dkim_enabled - [ ] set_identity_dkim_enabled
- [ ] set_identity_feedback_forwarding_enabled - [ ] set_identity_feedback_forwarding_enabled

View File

@ -49,6 +49,21 @@ class Message(BaseModel):
self.destinations = destinations self.destinations = destinations
class TemplateMessage(BaseModel):
def __init__(self,
message_id,
source,
template,
template_data,
destinations):
self.id = message_id
self.source = source
self.template = template
self.template_data = template_data
self.destinations = destinations
class RawMessage(BaseModel): class RawMessage(BaseModel):
def __init__(self, message_id, source, destinations, raw_data): def __init__(self, message_id, source, destinations, raw_data):
@ -123,10 +138,34 @@ class SESBackend(BaseBackend):
self.sent_message_count += recipient_count self.sent_message_count += recipient_count
return message return message
def send_templated_email(self, source, template, template_data, destinations, region):
recipient_count = sum(map(len, destinations.values()))
if recipient_count > RECIPIENT_LIMIT:
raise MessageRejectedError('Too many recipients.')
if not self._is_verified_address(source):
raise MessageRejectedError(
"Email address not verified %s" % source
)
self.__process_sns_feedback__(source, destinations, region)
message_id = get_random_message_id()
message = TemplateMessage(message_id,
source,
template,
template_data,
destinations)
self.sent_messages.append(message)
self.sent_message_count += recipient_count
return message
def __type_of_message__(self, destinations): def __type_of_message__(self, destinations):
"""Checks the destination for any special address that could indicate delivery, complaint or bounce """Checks the destination for any special address that could indicate delivery,
like in SES simualtor""" complaint or bounce like in SES simualtor"""
alladdress = destinations.get("ToAddresses", []) + destinations.get("CcAddresses", []) + destinations.get("BccAddresses", []) alladdress = destinations.get(
"ToAddresses", []) + destinations.get(
"CcAddresses", []) + destinations.get(
"BccAddresses", [])
for addr in alladdress: for addr in alladdress:
if SESFeedback.SUCCESS_ADDR in addr: if SESFeedback.SUCCESS_ADDR in addr:
return SESFeedback.DELIVERY return SESFeedback.DELIVERY

View File

@ -74,6 +74,33 @@ class EmailResponse(BaseResponse):
template = self.response_template(SEND_EMAIL_RESPONSE) template = self.response_template(SEND_EMAIL_RESPONSE)
return template.render(message=message) return template.render(message=message)
def send_templated_email(self):
source = self.querystring.get('Source')[0]
template = self.querystring.get('Template')
template_data = self.querystring.get('TemplateData')
destinations = {
'ToAddresses': [],
'CcAddresses': [],
'BccAddresses': [],
}
for dest_type in destinations:
# consume up to 51 to allow exception
for i in six.moves.range(1, 52):
field = 'Destination.%s.member.%s' % (dest_type, i)
address = self.querystring.get(field)
if address is None:
break
destinations[dest_type].append(address[0])
message = ses_backend.send_templated_email(source,
template,
template_data,
destinations,
self.region)
template = self.response_template(SEND_TEMPLATED_EMAIL_RESPONSE)
return template.render(message=message)
def send_raw_email(self): def send_raw_email(self):
source = self.querystring.get('Source') source = self.querystring.get('Source')
if source is not None: if source is not None:
@ -193,6 +220,15 @@ SEND_EMAIL_RESPONSE = """<SendEmailResponse xmlns="http://ses.amazonaws.com/doc/
</ResponseMetadata> </ResponseMetadata>
</SendEmailResponse>""" </SendEmailResponse>"""
SEND_TEMPLATED_EMAIL_RESPONSE = """<SendTemplatedEmailResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
<SendTemplatedEmailResult>
<MessageId>{{ message.id }}</MessageId>
</SendTemplatedEmailResult>
<ResponseMetadata>
<RequestId>d5964849-c866-11e0-9beb-01a62d68c57f</RequestId>
</ResponseMetadata>
</SendTemplatedEmailResponse>"""
SEND_RAW_EMAIL_RESPONSE = """<SendRawEmailResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/"> SEND_RAW_EMAIL_RESPONSE = """<SendRawEmailResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
<SendRawEmailResult> <SendRawEmailResult>
<MessageId>{{ message.id }}</MessageId> <MessageId>{{ message.id }}</MessageId>

View File

@ -80,6 +80,37 @@ def test_send_email():
sent_count.should.equal(3) sent_count.should.equal(3)
@mock_ses
def test_send_templated_email():
conn = boto3.client('ses', region_name='us-east-1')
kwargs = dict(
Source="test@example.com",
Destination={
"ToAddresses": ["test_to@example.com"],
"CcAddresses": ["test_cc@example.com"],
"BccAddresses": ["test_bcc@example.com"],
},
Template="test_template",
TemplateData='{\"name\": \"test\"}'
)
conn.send_templated_email.when.called_with(
**kwargs).should.throw(ClientError)
conn.verify_domain_identity(Domain='example.com')
conn.send_templated_email(**kwargs)
too_many_addresses = list('to%s@example.com' % i for i in range(51))
conn.send_templated_email.when.called_with(
**dict(kwargs, Destination={'ToAddresses': too_many_addresses})
).should.throw(ClientError)
send_quota = conn.get_send_quota()
sent_count = int(send_quota['SentLast24Hours'])
sent_count.should.equal(3)
@mock_ses @mock_ses
def test_send_html_email(): def test_send_html_email():
conn = boto3.client('ses', region_name='us-east-1') conn = boto3.client('ses', region_name='us-east-1')