diff --git a/moto/ses/models.py b/moto/ses/models.py index 0544ac278..22af15427 100644 --- a/moto/ses/models.py +++ b/moto/ses/models.py @@ -49,6 +49,21 @@ class Message(BaseModel): 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): def __init__(self, message_id, source, destinations, raw_data): @@ -123,10 +138,34 @@ class SESBackend(BaseBackend): self.sent_message_count += recipient_count 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): - """Checks the destination for any special address that could indicate delivery, complaint or bounce - like in SES simualtor""" - alladdress = destinations.get("ToAddresses", []) + destinations.get("CcAddresses", []) + destinations.get("BccAddresses", []) + """Checks the destination for any special address that could indicate delivery, + complaint or bounce like in SES simualtor""" + alladdress = destinations.get( + "ToAddresses", []) + destinations.get( + "CcAddresses", []) + destinations.get( + "BccAddresses", []) for addr in alladdress: if SESFeedback.SUCCESS_ADDR in addr: return SESFeedback.DELIVERY diff --git a/moto/ses/responses.py b/moto/ses/responses.py index d2dda55f1..d49e47d84 100644 --- a/moto/ses/responses.py +++ b/moto/ses/responses.py @@ -74,6 +74,33 @@ class EmailResponse(BaseResponse): template = self.response_template(SEND_EMAIL_RESPONSE) 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): source = self.querystring.get('Source') if source is not None: @@ -193,6 +220,15 @@ SEND_EMAIL_RESPONSE = """ + + {{ message.id }} + + + d5964849-c866-11e0-9beb-01a62d68c57f + +""" + SEND_RAW_EMAIL_RESPONSE = """ {{ message.id }} diff --git a/tests/test_ses/test_ses_boto3.py b/tests/test_ses/test_ses_boto3.py index e800b8035..fa042164d 100644 --- a/tests/test_ses/test_ses_boto3.py +++ b/tests/test_ses/test_ses_boto3.py @@ -80,6 +80,37 @@ def test_send_email(): 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 def test_send_html_email(): conn = boto3.client('ses', region_name='us-east-1')