SES: Implement GetIdentityMailFromDomainAttributes and SetIdentityMailFromDomain (#4842)
This commit is contained in:
parent
3d0bbd23ac
commit
5580b519e0
@ -4822,7 +4822,7 @@
|
|||||||
- [ ] get_account_sending_enabled
|
- [ ] get_account_sending_enabled
|
||||||
- [ ] get_custom_verification_email_template
|
- [ ] get_custom_verification_email_template
|
||||||
- [ ] get_identity_dkim_attributes
|
- [ ] get_identity_dkim_attributes
|
||||||
- [ ] get_identity_mail_from_domain_attributes
|
- [X] get_identity_mail_from_domain_attributes
|
||||||
- [X] get_identity_notification_attributes
|
- [X] get_identity_notification_attributes
|
||||||
- [ ] get_identity_policies
|
- [ ] get_identity_policies
|
||||||
- [ ] get_identity_verification_attributes
|
- [ ] get_identity_verification_attributes
|
||||||
@ -4850,7 +4850,7 @@
|
|||||||
- [ ] set_identity_dkim_enabled
|
- [ ] set_identity_dkim_enabled
|
||||||
- [X] set_identity_feedback_forwarding_enabled
|
- [X] set_identity_feedback_forwarding_enabled
|
||||||
- [ ] set_identity_headers_in_notifications_enabled
|
- [ ] set_identity_headers_in_notifications_enabled
|
||||||
- [ ] set_identity_mail_from_domain
|
- [X] set_identity_mail_from_domain
|
||||||
- [X] set_identity_notification_topic
|
- [X] set_identity_notification_topic
|
||||||
- [ ] set_receipt_rule_position
|
- [ ] set_receipt_rule_position
|
||||||
- [ ] test_render_template
|
- [ ] test_render_template
|
||||||
|
@ -117,6 +117,7 @@ class SESBackend(BaseBackend):
|
|||||||
self.config_set = {}
|
self.config_set = {}
|
||||||
self.config_set_event_destination = {}
|
self.config_set_event_destination = {}
|
||||||
self.event_destinations = {}
|
self.event_destinations = {}
|
||||||
|
self.identity_mail_from_domains = {}
|
||||||
self.templates = {}
|
self.templates = {}
|
||||||
self.receipt_rule_set = {}
|
self.receipt_rule_set = {}
|
||||||
|
|
||||||
@ -477,5 +478,49 @@ class SESBackend(BaseBackend):
|
|||||||
else:
|
else:
|
||||||
raise RuleDoesNotExist(f"Rule does not exist: {rule['name']}")
|
raise RuleDoesNotExist(f"Rule does not exist: {rule['name']}")
|
||||||
|
|
||||||
|
def set_identity_mail_from_domain(
|
||||||
|
self, identity, mail_from_domain=None, behavior_on_mx_failure=None
|
||||||
|
):
|
||||||
|
if identity not in (self.domains + self.addresses):
|
||||||
|
raise InvalidParameterValue(
|
||||||
|
"Identity '{0}' does not exist.".format(identity)
|
||||||
|
)
|
||||||
|
|
||||||
|
if mail_from_domain is None:
|
||||||
|
self.identity_mail_from_domains.pop(identity)
|
||||||
|
return
|
||||||
|
|
||||||
|
if not mail_from_domain.endswith(identity):
|
||||||
|
raise InvalidParameterValue(
|
||||||
|
"Provided MAIL-FROM domain '{0}' is not subdomain of "
|
||||||
|
"the domain of the identity '{1}'.".format(mail_from_domain, identity)
|
||||||
|
)
|
||||||
|
|
||||||
|
if behavior_on_mx_failure not in (None, "RejectMessage", "UseDefaultValue"):
|
||||||
|
raise ValidationError(
|
||||||
|
"1 validation error detected: "
|
||||||
|
"Value '{0}' at 'behaviorOnMXFailure'"
|
||||||
|
"failed to satisfy constraint: Member must satisfy enum value set: "
|
||||||
|
"[RejectMessage, UseDefaultValue]".format(behavior_on_mx_failure)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.identity_mail_from_domains[identity] = {
|
||||||
|
"mail_from_domain": mail_from_domain,
|
||||||
|
"behavior_on_mx_failure": behavior_on_mx_failure,
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_identity_mail_from_domain_attributes(self, identities=None):
|
||||||
|
if identities is None:
|
||||||
|
identities = []
|
||||||
|
|
||||||
|
attributes_by_identity = {}
|
||||||
|
for identity in identities:
|
||||||
|
if identity in (self.domains + self.addresses):
|
||||||
|
attributes_by_identity[identity] = self.identity_mail_from_domains.get(
|
||||||
|
identity
|
||||||
|
) or {"behavior_on_mx_failure": "UseDefaultValue"}
|
||||||
|
|
||||||
|
return attributes_by_identity
|
||||||
|
|
||||||
|
|
||||||
ses_backend = SESBackend()
|
ses_backend = SESBackend()
|
||||||
|
@ -279,6 +279,25 @@ class EmailResponse(BaseResponse):
|
|||||||
template = self.response_template(UPDATE_RECEIPT_RULE)
|
template = self.response_template(UPDATE_RECEIPT_RULE)
|
||||||
return template.render()
|
return template.render()
|
||||||
|
|
||||||
|
def set_identity_mail_from_domain(self):
|
||||||
|
identity = self._get_param("Identity")
|
||||||
|
mail_from_domain = self._get_param("MailFromDomain")
|
||||||
|
behavior_on_mx_failure = self._get_param("BehaviorOnMXFailure")
|
||||||
|
|
||||||
|
ses_backend.set_identity_mail_from_domain(
|
||||||
|
identity, mail_from_domain, behavior_on_mx_failure
|
||||||
|
)
|
||||||
|
|
||||||
|
template = self.response_template(SET_IDENTITY_MAIL_FROM_DOMAIN)
|
||||||
|
return template.render()
|
||||||
|
|
||||||
|
def get_identity_mail_from_domain_attributes(self):
|
||||||
|
identities = self._get_multi_param("Identities.member.")
|
||||||
|
identities = ses_backend.get_identity_mail_from_domain_attributes(identities)
|
||||||
|
template = self.response_template(GET_IDENTITY_MAIL_FROM_DOMAIN_ATTRIBUTES)
|
||||||
|
|
||||||
|
return template.render(identities=identities)
|
||||||
|
|
||||||
|
|
||||||
VERIFY_EMAIL_IDENTITY = """<VerifyEmailIdentityResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
|
VERIFY_EMAIL_IDENTITY = """<VerifyEmailIdentityResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
|
||||||
<VerifyEmailIdentityResult/>
|
<VerifyEmailIdentityResult/>
|
||||||
@ -633,3 +652,36 @@ UPDATE_RECEIPT_RULE = """<UpdateReceiptRuleResponse xmlns="http://ses.amazonaws.
|
|||||||
<RequestId>15e0ef1a-9bf2-11e1-9279-01ab88cf109a</RequestId>
|
<RequestId>15e0ef1a-9bf2-11e1-9279-01ab88cf109a</RequestId>
|
||||||
</ResponseMetadata>
|
</ResponseMetadata>
|
||||||
</UpdateReceiptRuleResponse>"""
|
</UpdateReceiptRuleResponse>"""
|
||||||
|
|
||||||
|
SET_IDENTITY_MAIL_FROM_DOMAIN = """<SetIdentityMailFromDomainResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
|
||||||
|
<SetIdentityMailFromDomainResult/>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>47e0ef1a-9bf2-11e1-9279-0100e8cf109a</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</SetIdentityMailFromDomainResponse>"""
|
||||||
|
|
||||||
|
GET_IDENTITY_MAIL_FROM_DOMAIN_ATTRIBUTES = """<GetIdentityMailFromDomainAttributesResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
|
||||||
|
<GetIdentityMailFromDomainAttributesResult>
|
||||||
|
{% if identities.items()|length > 0 %}
|
||||||
|
<MailFromDomainAttributes>
|
||||||
|
{% for name, value in identities.items() %}
|
||||||
|
<entry>
|
||||||
|
<key>{{ name }}</key>
|
||||||
|
<value>
|
||||||
|
{% if 'mail_from_domain' in value %}
|
||||||
|
<MailFromDomain>{{ value.get("mail_from_domain") }}</MailFromDomain>
|
||||||
|
<MailFromDomainStatus>Success</MailFromDomainStatus>
|
||||||
|
{% endif %}
|
||||||
|
<BehaviorOnMXFailure>{{ value.get("behavior_on_mx_failure") }}</BehaviorOnMXFailure>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
{% endfor %}
|
||||||
|
</MailFromDomainAttributes>
|
||||||
|
{% else %}
|
||||||
|
<MailFromDomainAttributes/>
|
||||||
|
{% endif %}
|
||||||
|
</GetIdentityMailFromDomainAttributesResult>
|
||||||
|
<ResponseMetadata>
|
||||||
|
<RequestId>47e0ef1a-9bf2-11e1-9279-0100e8cf109a</RequestId>
|
||||||
|
</ResponseMetadata>
|
||||||
|
</GetIdentityMailFromDomainAttributesResponse>"""
|
||||||
|
@ -1230,3 +1230,104 @@ def test_get_send_statistics():
|
|||||||
|
|
||||||
stats[0]["Rejects"].should.equal(1)
|
stats[0]["Rejects"].should.equal(1)
|
||||||
stats[0]["DeliveryAttempts"].should.equal(1)
|
stats[0]["DeliveryAttempts"].should.equal(1)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ses
|
||||||
|
def test_set_identity_mail_from_domain():
|
||||||
|
conn = boto3.client("ses", region_name="eu-central-1")
|
||||||
|
|
||||||
|
# Must raise if provided identity does not exist
|
||||||
|
with pytest.raises(ClientError) as exc:
|
||||||
|
conn.set_identity_mail_from_domain(Identity="foo.com")
|
||||||
|
err = exc.value.response["Error"]
|
||||||
|
err["Code"].should.equal("InvalidParameterValue")
|
||||||
|
err["Message"].should.equal("Identity 'foo.com' does not exist.")
|
||||||
|
|
||||||
|
conn.verify_domain_identity(Domain="foo.com")
|
||||||
|
|
||||||
|
# Must raise if MAILFROM is not a subdomain of identity
|
||||||
|
with pytest.raises(ClientError) as exc:
|
||||||
|
conn.set_identity_mail_from_domain(
|
||||||
|
Identity="foo.com", MailFromDomain="lorem.ipsum.com"
|
||||||
|
)
|
||||||
|
err = exc.value.response["Error"]
|
||||||
|
err["Code"].should.equal("InvalidParameterValue")
|
||||||
|
err["Message"].should.equal(
|
||||||
|
"Provided MAIL-FROM domain 'lorem.ipsum.com' is not subdomain of "
|
||||||
|
"the domain of the identity 'foo.com'."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Must raise if BehaviorOnMXFailure is not a valid choice
|
||||||
|
with pytest.raises(ClientError) as exc:
|
||||||
|
conn.set_identity_mail_from_domain(
|
||||||
|
Identity="foo.com",
|
||||||
|
MailFromDomain="lorem.foo.com",
|
||||||
|
BehaviorOnMXFailure="SelfDestruct",
|
||||||
|
)
|
||||||
|
err = exc.value.response["Error"]
|
||||||
|
err["Code"].should.equal("ValidationError")
|
||||||
|
err["Message"].should.equal(
|
||||||
|
"1 validation error detected: Value 'SelfDestruct' at "
|
||||||
|
"'behaviorOnMXFailure'failed to satisfy constraint: Member must "
|
||||||
|
"satisfy enum value set: [RejectMessage, UseDefaultValue]"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Must set config for valid input
|
||||||
|
behaviour_on_mx_failure = "RejectMessage"
|
||||||
|
mail_from_domain = "lorem.foo.com"
|
||||||
|
|
||||||
|
conn.set_identity_mail_from_domain(
|
||||||
|
Identity="foo.com",
|
||||||
|
MailFromDomain=mail_from_domain,
|
||||||
|
BehaviorOnMXFailure=behaviour_on_mx_failure,
|
||||||
|
)
|
||||||
|
|
||||||
|
attributes = conn.get_identity_mail_from_domain_attributes(Identities=["foo.com"])
|
||||||
|
actual_attributes = attributes["MailFromDomainAttributes"]["foo.com"]
|
||||||
|
actual_attributes.should.have.key("MailFromDomain").being.equal(mail_from_domain)
|
||||||
|
actual_attributes.should.have.key("BehaviorOnMXFailure").being.equal(
|
||||||
|
behaviour_on_mx_failure
|
||||||
|
)
|
||||||
|
actual_attributes.should.have.key("MailFromDomainStatus").being.equal("Success")
|
||||||
|
|
||||||
|
# Must unset config when MailFromDomain is null
|
||||||
|
conn.set_identity_mail_from_domain(Identity="foo.com")
|
||||||
|
|
||||||
|
attributes = conn.get_identity_mail_from_domain_attributes(Identities=["foo.com"])
|
||||||
|
actual_attributes = attributes["MailFromDomainAttributes"]["foo.com"]
|
||||||
|
actual_attributes.should.have.key("BehaviorOnMXFailure").being.equal(
|
||||||
|
"UseDefaultValue"
|
||||||
|
)
|
||||||
|
actual_attributes.should_not.have.key("MailFromDomain")
|
||||||
|
actual_attributes.should_not.have.key("MailFromDomainStatus")
|
||||||
|
|
||||||
|
|
||||||
|
@mock_ses
|
||||||
|
def test_get_identity_mail_from_domain_attributes():
|
||||||
|
conn = boto3.client("ses", region_name="eu-central-1")
|
||||||
|
|
||||||
|
# Must return empty for non-existent identities
|
||||||
|
attributes = conn.get_identity_mail_from_domain_attributes(
|
||||||
|
Identities=["bar@foo.com", "lorem.com"]
|
||||||
|
)
|
||||||
|
attributes["MailFromDomainAttributes"].should.have.length_of(0)
|
||||||
|
|
||||||
|
# Must return default options for non-configured identities
|
||||||
|
conn.verify_email_identity(EmailAddress="bar@foo.com")
|
||||||
|
attributes = conn.get_identity_mail_from_domain_attributes(
|
||||||
|
Identities=["bar@foo.com", "lorem.com"]
|
||||||
|
)
|
||||||
|
attributes["MailFromDomainAttributes"].should.have.length_of(1)
|
||||||
|
attributes["MailFromDomainAttributes"]["bar@foo.com"].should.have.length_of(1)
|
||||||
|
attributes["MailFromDomainAttributes"]["bar@foo.com"].should.have.key(
|
||||||
|
"BehaviorOnMXFailure"
|
||||||
|
).being.equal("UseDefaultValue")
|
||||||
|
|
||||||
|
# Must return multiple configured identities
|
||||||
|
conn.verify_domain_identity(Domain="lorem.com")
|
||||||
|
attributes = conn.get_identity_mail_from_domain_attributes(
|
||||||
|
Identities=["bar@foo.com", "lorem.com"]
|
||||||
|
)
|
||||||
|
attributes["MailFromDomainAttributes"].should.have.length_of(2)
|
||||||
|
attributes["MailFromDomainAttributes"]["bar@foo.com"].should.have.length_of(1)
|
||||||
|
attributes["MailFromDomainAttributes"]["lorem.com"].should.have.length_of(1)
|
||||||
|
Loading…
Reference in New Issue
Block a user