aws_lambda_events/event/ses/
mod.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3
4/// `SimpleEmailEvent` is the outer structure of an event sent via SES.
5#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
6#[serde(rename_all = "camelCase")]
7pub struct SimpleEmailEvent {
8    #[serde(rename = "Records")]
9    pub records: Vec<SimpleEmailRecord>,
10}
11
12#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
13#[serde(rename_all = "camelCase")]
14pub struct SimpleEmailRecord {
15    #[serde(default)]
16    pub event_version: Option<String>,
17    #[serde(default)]
18    pub event_source: Option<String>,
19    pub ses: SimpleEmailService,
20}
21
22#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
23#[serde(rename_all = "camelCase")]
24pub struct SimpleEmailService {
25    pub mail: SimpleEmailMessage,
26    pub receipt: SimpleEmailReceipt,
27    pub content: Option<String>,
28}
29
30#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
31#[serde(rename_all = "camelCase")]
32pub struct SimpleEmailMessage {
33    pub common_headers: SimpleEmailCommonHeaders,
34    #[serde(default)]
35    pub source: Option<String>,
36    pub timestamp: DateTime<Utc>,
37    pub destination: Vec<String>,
38    pub headers: Vec<SimpleEmailHeader>,
39    pub headers_truncated: bool,
40    #[serde(default)]
41    pub message_id: Option<String>,
42}
43
44#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
45#[serde(rename_all = "camelCase")]
46pub struct SimpleEmailReceipt {
47    pub recipients: Vec<String>,
48    pub timestamp: DateTime<Utc>,
49    pub spam_verdict: SimpleEmailVerdict,
50    pub dkim_verdict: SimpleEmailVerdict,
51    pub dmarc_verdict: SimpleEmailVerdict,
52    #[serde(default)]
53    pub dmarc_policy: Option<String>,
54    pub spf_verdict: SimpleEmailVerdict,
55    pub virus_verdict: SimpleEmailVerdict,
56    pub action: SimpleEmailReceiptAction,
57    pub processing_time_millis: i64,
58}
59
60#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
61#[serde(rename_all = "camelCase")]
62pub struct SimpleEmailHeader {
63    #[serde(default)]
64    pub name: Option<String>,
65    #[serde(default)]
66    pub value: Option<String>,
67}
68
69#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
70#[serde(rename_all = "camelCase")]
71pub struct SimpleEmailCommonHeaders {
72    pub from: Vec<String>,
73    pub to: Vec<String>,
74    #[serde(default)]
75    pub return_path: Option<String>,
76    #[serde(default)]
77    pub message_id: Option<String>,
78    #[serde(default)]
79    pub date: Option<String>,
80    #[serde(default)]
81    pub subject: Option<String>,
82}
83
84/// `SimpleEmailReceiptAction` is a logical union of fields present in all action
85/// Types. For example, the FunctionARN and InvocationType fields are only
86/// present for the Lambda Type, and the BucketName and ObjectKey fields are only
87/// present for the S3 Type.
88#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
89#[serde(rename_all = "camelCase")]
90pub struct SimpleEmailReceiptAction {
91    #[serde(default)]
92    pub type_: Option<String>,
93    pub topic_arn: Option<String>,
94    pub bucket_name: Option<String>,
95    pub object_key: Option<String>,
96    pub smtp_reply_code: Option<String>,
97    pub status_code: Option<String>,
98    pub message: Option<String>,
99    pub sender: Option<String>,
100    pub invocation_type: Option<String>,
101    pub function_arn: Option<String>,
102    pub organization_arn: Option<String>,
103}
104
105#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
106#[serde(rename_all = "camelCase")]
107pub struct SimpleEmailVerdict {
108    #[serde(default)]
109    pub status: Option<String>,
110}
111
112pub type SimpleEmailDispositionValue = String;
113
114/// `SimpleEmailDisposition` disposition return for SES to control rule functions
115#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
116#[serde(rename_all = "camelCase")]
117pub struct SimpleEmailDisposition {
118    pub disposition: SimpleEmailDispositionValue,
119}
120
121#[cfg(test)]
122mod test {
123    use super::*;
124
125    #[test]
126    #[cfg(feature = "ses")]
127    fn example_ses_lambda_event() {
128        let data = include_bytes!("../../fixtures/example-ses-lambda-event.json");
129        let parsed: SimpleEmailEvent = serde_json::from_slice(data).unwrap();
130        let output: String = serde_json::to_string(&parsed).unwrap();
131        let reparsed: SimpleEmailEvent = serde_json::from_slice(output.as_bytes()).unwrap();
132        assert_eq!(parsed, reparsed);
133    }
134
135    #[test]
136    #[cfg(feature = "ses")]
137    fn example_ses_s3_event() {
138        let data = include_bytes!("../../fixtures/example-ses-s3-event.json");
139        let parsed: SimpleEmailEvent = serde_json::from_slice(data).unwrap();
140        let output: String = serde_json::to_string(&parsed).unwrap();
141        let reparsed: SimpleEmailEvent = serde_json::from_slice(output.as_bytes()).unwrap();
142        assert_eq!(parsed, reparsed);
143    }
144
145    #[test]
146    #[cfg(feature = "ses")]
147    fn example_ses_sns_event() {
148        let data = include_bytes!("../../fixtures/example-ses-sns-event.json");
149        let parsed: SimpleEmailEvent = serde_json::from_slice(data).unwrap();
150        let output: String = serde_json::to_string(&parsed).unwrap();
151        let reparsed: SimpleEmailEvent = serde_json::from_slice(output.as_bytes()).unwrap();
152        assert_eq!(parsed, reparsed);
153    }
154}