From 11c55b98cc214c175b74d4c5edb34be786138572 Mon Sep 17 00:00:00 2001 From: Michael Brewer Date: Thu, 28 Apr 2022 08:59:31 -0700 Subject: [PATCH] fix(data-classes): Add missing SES fields and (#1045) Changes: - Fix date type to be a str and not List[str] - Add missing fields from SESMailCommonHeaders (bcc, cc, sender and replyTo) - Add missing dkimVerdict field - Add missing dmarcPolicy field - Add missing topicArn field - Add missing docs for SESReceiptStatus status field related #1025 --- .../utilities/data_classes/ses_event.py | 45 ++++++++++++++++++- tests/events/sesEvent.json | 1 + tests/functional/test_data_classes.py | 7 +++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/aws_lambda_powertools/utilities/data_classes/ses_event.py b/aws_lambda_powertools/utilities/data_classes/ses_event.py index c270a85ddf7..2ebc02e22a0 100644 --- a/aws_lambda_powertools/utilities/data_classes/ses_event.py +++ b/aws_lambda_powertools/utilities/data_classes/ses_event.py @@ -1,4 +1,4 @@ -from typing import Iterator, List +from typing import Iterator, List, Optional from aws_lambda_powertools.utilities.data_classes.common import DictWrapper @@ -26,7 +26,7 @@ def get_from(self) -> List[str]: return self["from"] @property - def date(self) -> List[str]: + def date(self) -> str: """The date and time when Amazon SES received the message.""" return self["date"] @@ -45,6 +45,26 @@ def subject(self) -> str: """The value of the Subject header for the email.""" return str(self["subject"]) + @property + def cc(self) -> Optional[List[str]]: + """The values in the CC header of the email.""" + return self.get("cc") + + @property + def bcc(self) -> Optional[List[str]]: + """The values in the BCC header of the email.""" + return self.get("bcc") + + @property + def sender(self) -> Optional[List[str]]: + """The values in the Sender header of the email.""" + return self.get("sender") + + @property + def reply_to(self) -> Optional[List[str]]: + """The values in the replyTo header of the email.""" + return self.get("replyTo") + class SESMail(DictWrapper): @property @@ -94,6 +114,9 @@ def common_headers(self) -> SESMailCommonHeaders: class SESReceiptStatus(DictWrapper): @property def status(self) -> str: + """Receipt status + Possible values: 'PASS', 'FAIL', 'GRAY', 'PROCESSING_FAILED', 'DISABLED' + """ return str(self["status"]) @@ -107,6 +130,12 @@ def get_type(self) -> str: # Note: this name conflicts with existing python builtins return self["type"] + @property + def topic_arn(self) -> Optional[str]: + """String that contains the Amazon Resource Name (ARN) of the Amazon SNS topic to which the + notification was published.""" + return self.get("topicArn") + @property def function_arn(self) -> str: """String that contains the ARN of the Lambda function that was triggered. @@ -154,12 +183,24 @@ def spf_verdict(self) -> SESReceiptStatus: """Object that indicates whether the Sender Policy Framework (SPF) check passed.""" return SESReceiptStatus(self["spfVerdict"]) + @property + def dkim_verdict(self) -> SESReceiptStatus: + """Object that indicates whether the DomainKeys Identified Mail (DKIM) check passed""" + return SESReceiptStatus(self["dkimVerdict"]) + @property def dmarc_verdict(self) -> SESReceiptStatus: """Object that indicates whether the Domain-based Message Authentication, Reporting & Conformance (DMARC) check passed.""" return SESReceiptStatus(self["dmarcVerdict"]) + @property + def dmarc_policy(self) -> Optional[str]: + """Indicates the Domain-based Message Authentication, Reporting & Conformance (DMARC) settings for + the sending domain. This field only appears if the message fails DMARC authentication. + Possible values for this field are: none, quarantine, reject""" + return self.get("dmarcPolicy") + @property def action(self) -> SESReceiptAction: """Object that encapsulates information about the action that was executed.""" diff --git a/tests/events/sesEvent.json b/tests/events/sesEvent.json index 5a5afd5bab7..636ecad687f 100644 --- a/tests/events/sesEvent.json +++ b/tests/events/sesEvent.json @@ -77,6 +77,7 @@ "dkimVerdict": { "status": "PASS" }, + "dmarcPolicy": "reject", "processingTimeMillis": 574, "action": { "type": "Lambda", diff --git a/tests/functional/test_data_classes.py b/tests/functional/test_data_classes.py index d0d936ec2f8..8a87075d16c 100644 --- a/tests/functional/test_data_classes.py +++ b/tests/functional/test_data_classes.py @@ -691,6 +691,10 @@ def test_ses_trigger_event(): assert common_headers.to == [expected_address] assert common_headers.message_id == "<0123456789example.com>" assert common_headers.subject == "Test Subject" + assert common_headers.cc is None + assert common_headers.bcc is None + assert common_headers.sender is None + assert common_headers.reply_to is None receipt = record.ses.receipt assert receipt.timestamp == "1970-01-01T00:00:00.000Z" assert receipt.processing_time_millis == 574 @@ -699,10 +703,13 @@ def test_ses_trigger_event(): assert receipt.virus_verdict.status == "PASS" assert receipt.spf_verdict.status == "PASS" assert receipt.dmarc_verdict.status == "PASS" + assert receipt.dkim_verdict.status == "PASS" + assert receipt.dmarc_policy == "reject" action = receipt.action assert action.get_type == action.raw_event["type"] assert action.function_arn == action.raw_event["functionArn"] assert action.invocation_type == action.raw_event["invocationType"] + assert action.topic_arn is None assert event.record.raw_event == event["Records"][0] assert event.mail.raw_event == event["Records"][0]["ses"]["mail"] assert event.receipt.raw_event == event["Records"][0]["ses"]["receipt"]