1use chrono::{DateTime, Utc};
2use parking_lot::RwLock;
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::sync::Arc;
6
7#[derive(Debug, Clone, Serialize)]
8pub struct EmailIdentity {
9 pub identity_name: String,
10 pub identity_type: String,
11 pub verified: bool,
12 pub created_at: DateTime<Utc>,
13 pub dkim_signing_enabled: bool,
15 pub dkim_signing_attributes_origin: String,
16 pub dkim_domain_signing_private_key: Option<String>,
17 pub dkim_domain_signing_selector: Option<String>,
18 pub dkim_next_signing_key_length: Option<String>,
19 pub email_forwarding_enabled: bool,
21 pub mail_from_domain: Option<String>,
23 pub mail_from_behavior_on_mx_failure: String,
24 pub configuration_set_name: Option<String>,
26}
27
28#[derive(Debug, Clone, Serialize)]
29pub struct EmailTemplate {
30 pub template_name: String,
31 pub subject: Option<String>,
32 pub html_body: Option<String>,
33 pub text_body: Option<String>,
34 pub created_at: DateTime<Utc>,
35}
36
37#[derive(Debug, Clone, Serialize)]
38pub struct ConfigurationSet {
39 pub name: String,
40 pub sending_enabled: bool,
42 pub tls_policy: String,
44 pub sending_pool_name: Option<String>,
45 pub custom_redirect_domain: Option<String>,
47 pub https_policy: Option<String>,
48 pub suppressed_reasons: Vec<String>,
50 pub reputation_metrics_enabled: bool,
52 pub vdm_options: Option<serde_json::Value>,
54 pub archive_arn: Option<String>,
56}
57
58#[derive(Debug, Clone, Serialize)]
59pub struct CustomVerificationEmailTemplate {
60 pub template_name: String,
61 pub from_email_address: String,
62 pub template_subject: String,
63 pub template_content: String,
64 pub success_redirection_url: String,
65 pub failure_redirection_url: String,
66 pub created_at: DateTime<Utc>,
67}
68
69#[derive(Debug, Clone, Serialize)]
70pub struct SentEmail {
71 pub message_id: String,
72 pub from: String,
73 pub to: Vec<String>,
74 pub cc: Vec<String>,
75 pub bcc: Vec<String>,
76 pub subject: Option<String>,
77 pub html_body: Option<String>,
78 pub text_body: Option<String>,
79 pub raw_data: Option<String>,
80 pub template_name: Option<String>,
81 pub template_data: Option<String>,
82 pub timestamp: DateTime<Utc>,
83}
84
85#[derive(Debug, Clone, Serialize)]
86pub struct ContactList {
87 pub contact_list_name: String,
88 pub description: Option<String>,
89 pub topics: Vec<Topic>,
90 pub created_at: DateTime<Utc>,
91 pub last_updated_at: DateTime<Utc>,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct Topic {
96 pub topic_name: String,
97 pub display_name: String,
98 pub description: String,
99 pub default_subscription_status: String,
100}
101
102#[derive(Debug, Clone, Serialize)]
103pub struct Contact {
104 pub email_address: String,
105 pub topic_preferences: Vec<TopicPreference>,
106 pub unsubscribe_all: bool,
107 pub attributes_data: Option<String>,
108 pub created_at: DateTime<Utc>,
109 pub last_updated_at: DateTime<Utc>,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct TopicPreference {
114 pub topic_name: String,
115 pub subscription_status: String,
116}
117
118#[derive(Debug, Clone, Serialize)]
119pub struct SuppressedDestination {
120 pub email_address: String,
121 pub reason: String,
122 pub last_update_time: DateTime<Utc>,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct EventDestination {
127 pub name: String,
128 pub enabled: bool,
129 pub matching_event_types: Vec<String>,
130 #[serde(skip_serializing_if = "Option::is_none")]
131 pub kinesis_firehose_destination: Option<serde_json::Value>,
132 #[serde(skip_serializing_if = "Option::is_none")]
133 pub cloud_watch_destination: Option<serde_json::Value>,
134 #[serde(skip_serializing_if = "Option::is_none")]
135 pub sns_destination: Option<serde_json::Value>,
136 #[serde(skip_serializing_if = "Option::is_none")]
137 pub event_bridge_destination: Option<serde_json::Value>,
138 #[serde(skip_serializing_if = "Option::is_none")]
139 pub pinpoint_destination: Option<serde_json::Value>,
140}
141
142#[derive(Debug, Clone, Serialize)]
143pub struct DedicatedIpPool {
144 pub pool_name: String,
145 pub scaling_mode: String,
146}
147
148#[derive(Debug, Clone, Serialize)]
149pub struct DedicatedIp {
150 pub ip: String,
151 pub warmup_status: String,
152 pub warmup_percentage: i32,
153 pub pool_name: String,
154}
155
156#[derive(Debug, Clone, Serialize)]
157pub struct MultiRegionEndpoint {
158 pub endpoint_name: String,
159 pub endpoint_id: String,
160 pub status: String,
161 pub regions: Vec<String>,
162 pub created_at: DateTime<Utc>,
163 pub last_updated_at: DateTime<Utc>,
164}
165
166#[derive(Debug, Clone, Serialize, Default)]
167pub struct AccountDetails {
168 pub mail_type: Option<String>,
169 pub website_url: Option<String>,
170 pub contact_language: Option<String>,
171 pub use_case_description: Option<String>,
172 pub additional_contact_email_addresses: Vec<String>,
173 pub production_access_enabled: Option<bool>,
174}
175
176#[derive(Debug, Clone, Serialize, Default)]
177pub struct AccountSettings {
178 pub sending_enabled: bool,
179 pub dedicated_ip_auto_warmup_enabled: bool,
180 pub suppressed_reasons: Vec<String>,
181 pub vdm_attributes: Option<serde_json::Value>,
182 pub details: Option<AccountDetails>,
183}
184
185#[derive(Debug, Clone, Serialize)]
186pub struct ImportJob {
187 pub job_id: String,
188 pub import_destination: serde_json::Value,
189 pub import_data_source: serde_json::Value,
190 pub job_status: String,
191 pub created_timestamp: DateTime<Utc>,
192 pub completed_timestamp: Option<DateTime<Utc>>,
193 pub processed_records_count: i32,
194 pub failed_records_count: i32,
195}
196
197#[derive(Debug, Clone, Serialize)]
198pub struct ExportJob {
199 pub job_id: String,
200 pub export_source_type: String,
201 pub export_destination: serde_json::Value,
202 pub export_data_source: serde_json::Value,
203 pub job_status: String,
204 pub created_timestamp: DateTime<Utc>,
205 pub completed_timestamp: Option<DateTime<Utc>>,
206}
207
208#[derive(Debug, Clone, Serialize)]
209pub struct Tenant {
210 pub tenant_name: String,
211 pub tenant_id: String,
212 pub tenant_arn: String,
213 pub created_timestamp: DateTime<Utc>,
214 pub sending_status: String,
215 pub tags: Vec<serde_json::Value>,
216}
217
218#[derive(Debug, Clone, Serialize)]
219pub struct TenantResourceAssociation {
220 pub resource_arn: String,
221 pub associated_timestamp: DateTime<Utc>,
222}
223
224#[derive(Debug, Clone, Serialize)]
225pub struct ReputationEntityState {
226 pub reputation_entity_reference: String,
227 pub reputation_entity_type: String,
228 pub reputation_management_policy: Option<String>,
229 pub customer_managed_status: String,
230 pub sending_status_aggregate: String,
231}
232
233#[derive(Debug, Clone, Serialize, Deserialize)]
236pub struct ReceiptRuleSet {
237 pub name: String,
238 pub rules: Vec<ReceiptRule>,
239 pub created_at: DateTime<Utc>,
240}
241
242#[derive(Debug, Clone, Serialize, Deserialize)]
243pub struct ReceiptRule {
244 pub name: String,
245 pub enabled: bool,
246 pub scan_enabled: bool,
247 pub tls_policy: String,
248 pub recipients: Vec<String>,
249 pub actions: Vec<ReceiptAction>,
250}
251
252#[derive(Debug, Clone, Serialize, Deserialize)]
253pub enum ReceiptAction {
254 S3 {
255 bucket_name: String,
256 object_key_prefix: Option<String>,
257 topic_arn: Option<String>,
258 kms_key_arn: Option<String>,
259 },
260 Sns {
261 topic_arn: String,
262 encoding: Option<String>,
263 },
264 Lambda {
265 function_arn: String,
266 invocation_type: Option<String>,
267 topic_arn: Option<String>,
268 },
269 Bounce {
270 smtp_reply_code: String,
271 message: String,
272 sender: String,
273 status_code: Option<String>,
274 topic_arn: Option<String>,
275 },
276 AddHeader {
277 header_name: String,
278 header_value: String,
279 },
280 Stop {
281 scope: String,
282 topic_arn: Option<String>,
283 },
284}
285
286#[derive(Debug, Clone, Serialize, Deserialize)]
287pub struct ReceiptFilter {
288 pub name: String,
289 pub ip_filter: IpFilter,
290}
291
292#[derive(Debug, Clone, Serialize, Deserialize)]
293pub struct IpFilter {
294 pub cidr: String,
295 pub policy: String, }
297
298#[derive(Debug, Clone, Serialize, Deserialize)]
299pub struct InboundEmail {
300 pub message_id: String,
301 pub from: String,
302 pub to: Vec<String>,
303 pub subject: String,
304 pub body: String,
305 pub matched_rules: Vec<String>,
306 pub actions_executed: Vec<String>,
307 pub timestamp: DateTime<Utc>,
308}
309
310pub struct SesState {
311 pub account_id: String,
312 pub region: String,
313 pub identities: HashMap<String, EmailIdentity>,
314 pub configuration_sets: HashMap<String, ConfigurationSet>,
315 pub templates: HashMap<String, EmailTemplate>,
316 pub sent_emails: Vec<SentEmail>,
317 pub contact_lists: HashMap<String, ContactList>,
318 pub contacts: HashMap<String, HashMap<String, Contact>>,
319 pub tags: HashMap<String, HashMap<String, String>>,
321 pub suppressed_destinations: HashMap<String, SuppressedDestination>,
323 pub event_destinations: HashMap<String, Vec<EventDestination>>,
325 pub identity_policies: HashMap<String, HashMap<String, String>>,
327 pub custom_verification_email_templates: HashMap<String, CustomVerificationEmailTemplate>,
329 pub dedicated_ip_pools: HashMap<String, DedicatedIpPool>,
331 pub dedicated_ips: HashMap<String, DedicatedIp>,
333 pub multi_region_endpoints: HashMap<String, MultiRegionEndpoint>,
335 pub account_settings: AccountSettings,
337 pub import_jobs: HashMap<String, ImportJob>,
339 pub export_jobs: HashMap<String, ExportJob>,
341 pub tenants: HashMap<String, Tenant>,
343 pub tenant_resource_associations: HashMap<String, Vec<TenantResourceAssociation>>,
345 pub reputation_entities: HashMap<String, ReputationEntityState>,
347 pub receipt_rule_sets: HashMap<String, ReceiptRuleSet>,
350 pub active_receipt_rule_set: Option<String>,
352 pub receipt_filters: HashMap<String, ReceiptFilter>,
354 pub inbound_emails: Vec<InboundEmail>,
356}
357
358impl SesState {
359 pub fn new(account_id: &str, region: &str) -> Self {
360 Self {
361 account_id: account_id.to_string(),
362 region: region.to_string(),
363 identities: HashMap::new(),
364 configuration_sets: HashMap::new(),
365 templates: HashMap::new(),
366 sent_emails: Vec::new(),
367 contact_lists: HashMap::new(),
368 contacts: HashMap::new(),
369 tags: HashMap::new(),
370 suppressed_destinations: HashMap::new(),
371 event_destinations: HashMap::new(),
372 identity_policies: HashMap::new(),
373 custom_verification_email_templates: HashMap::new(),
374 dedicated_ip_pools: HashMap::new(),
375 dedicated_ips: HashMap::new(),
376 multi_region_endpoints: HashMap::new(),
377 account_settings: AccountSettings {
378 sending_enabled: true,
379 dedicated_ip_auto_warmup_enabled: false,
380 suppressed_reasons: Vec::new(),
381 vdm_attributes: None,
382 details: None,
383 },
384 import_jobs: HashMap::new(),
385 export_jobs: HashMap::new(),
386 tenants: HashMap::new(),
387 tenant_resource_associations: HashMap::new(),
388 reputation_entities: HashMap::new(),
389 receipt_rule_sets: HashMap::new(),
390 active_receipt_rule_set: None,
391 receipt_filters: HashMap::new(),
392 inbound_emails: Vec::new(),
393 }
394 }
395
396 pub fn reset(&mut self) {
397 self.identities.clear();
398 self.configuration_sets.clear();
399 self.templates.clear();
400 self.sent_emails.clear();
401 self.contact_lists.clear();
402 self.contacts.clear();
403 self.tags.clear();
404 self.suppressed_destinations.clear();
405 self.event_destinations.clear();
406 self.identity_policies.clear();
407 self.custom_verification_email_templates.clear();
408 self.dedicated_ip_pools.clear();
409 self.dedicated_ips.clear();
410 self.multi_region_endpoints.clear();
411 self.account_settings = AccountSettings {
412 sending_enabled: true,
413 dedicated_ip_auto_warmup_enabled: false,
414 suppressed_reasons: Vec::new(),
415 vdm_attributes: None,
416 details: None,
417 };
418 self.import_jobs.clear();
419 self.export_jobs.clear();
420 self.tenants.clear();
421 self.tenant_resource_associations.clear();
422 self.reputation_entities.clear();
423 self.receipt_rule_sets.clear();
424 self.active_receipt_rule_set = None;
425 self.receipt_filters.clear();
426 self.inbound_emails.clear();
427 }
428}
429
430pub type SharedSesState = Arc<RwLock<SesState>>;