1use {
2 chrono::{DateTime, Utc},
3 serde::{Deserialize, Serialize},
4 serde_repr::{Deserialize_repr, Serialize_repr},
5 std::{collections::HashMap, fmt::Display},
6};
7
8#[derive(Deserialize_repr, Serialize_repr, Debug, Clone, Copy, PartialEq, Eq, Default)]
9#[repr(u8)]
10pub enum MailStatus {
11 #[default]
12 PendingDns = 0,
13 Active = 1,
14 Suspended = 2,
15}
16
17impl Display for MailStatus {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 match self {
20 MailStatus::PendingDns => write!(f, "pending_dns"),
21 MailStatus::Active => write!(f, "active"),
22 MailStatus::Suspended => write!(f, "suspended"),
23 }
24 }
25}
26
27#[derive(Deserialize_repr, Serialize_repr, Debug, Clone, Copy, PartialEq, Eq, Default)]
28#[repr(u8)]
29pub enum MailMessageStatus {
30 #[default]
31 Received = 0,
32 Forwarded = 1,
33 ForwardFailed = 2,
34}
35
36impl Display for MailMessageStatus {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 match self {
39 MailMessageStatus::Received => write!(f, "received"),
40 MailMessageStatus::Forwarded => write!(f, "forwarded"),
41 MailMessageStatus::ForwardFailed => write!(f, "forward_failed"),
42 }
43 }
44}
45
46#[derive(Deserialize, Serialize, Debug, Clone)]
47pub struct MailApp {
48 pub id: String,
54 pub name: String,
55 pub domain: String,
56 pub aws_region: String,
57 pub project_id: i32,
58 pub tenant_id: i32,
59 pub created_at: DateTime<Utc>,
60 pub updated_at: DateTime<Utc>,
61 pub status: MailStatus,
62 pub ses_inbound_mx_value: String,
63 pub inbound_bucket_name: String,
64 pub inbound_email_key_prefix: String,
65 #[serde(default)]
66 pub lambda_config: HashMap<String, String>,
67 #[serde(default)]
68 pub inboxes: Vec<MailInbox>,
69}
70
71#[derive(Deserialize, Serialize, Debug, Clone)]
72pub struct MailInbox {
73 pub id: String,
74 pub local_part: String,
75 pub full_address: String,
76 pub inbox_email: String,
77 pub sender_email: String,
78 pub forward_to_email: String,
79 pub mail_app_id: String,
80 pub project_id: i32,
81 pub tenant_id: i32,
82 pub last_test_email_sent_at: Option<DateTime<Utc>>,
83 pub created_at: DateTime<Utc>,
84 pub updated_at: DateTime<Utc>,
85 pub status: MailStatus,
86 pub email_key_prefix: String,
87 #[serde(default)]
88 pub lambda_config: HashMap<String, String>,
89}
90
91#[derive(Deserialize, Serialize, Debug, Clone)]
92pub struct MailMessage {
93 pub id: String,
94 pub mail_inbox_id: String,
95 pub provider_message_id: String,
96 pub original_recipient_email: String,
97 pub from_email: String,
98 pub from_name: Option<String>,
99 pub subject: Option<String>,
100 pub text_preview: Option<String>,
101 pub size_bytes: Option<i64>,
102 pub forwarded_at: Option<DateTime<Utc>>,
103 pub forward_error: Option<String>,
104 pub received_at: DateTime<Utc>,
105 pub created_at: DateTime<Utc>,
106 pub updated_at: DateTime<Utc>,
107 pub status: MailMessageStatus,
108 pub text_body: Option<String>,
109 pub html_body: Option<String>,
110 #[serde(default)]
111 pub to_emails: Vec<String>,
112 #[serde(default)]
113 pub cc_emails: Vec<String>,
114 #[serde(default)]
115 pub forward_recipients: Vec<String>,
116 #[serde(default)]
117 pub headers_json: HashMap<String, String>,
118 pub s3_bucket: Option<String>,
119 pub s3_key: Option<String>,
120}
121
122#[derive(Serialize, Debug, Clone)]
123pub struct MailAppCreate {
124 pub name: String,
125 pub project_id: String,
126 pub domain: String,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub aws_region: Option<String>,
129}
130
131#[derive(Serialize, Debug, Clone, Default)]
132pub struct MailAppUpdate {
133 #[serde(skip_serializing_if = "Option::is_none")]
134 pub name: Option<String>,
135 #[serde(skip_serializing_if = "Option::is_none")]
136 pub domain: Option<String>,
137 #[serde(skip_serializing_if = "Option::is_none")]
138 pub aws_region: Option<String>,
139}
140
141impl MailAppUpdate {
142 pub fn is_empty(&self) -> bool {
143 self.name.is_none() && self.domain.is_none() && self.aws_region.is_none()
144 }
145}
146
147#[derive(Serialize, Debug, Clone)]
148pub struct MailInboxCreate {
149 pub local_part: String,
150 pub forward_to_email: String,
151 #[serde(skip_serializing_if = "Option::is_none")]
152 pub sender_email: Option<String>,
153}
154
155#[derive(Serialize, Debug, Clone, Default)]
156pub struct MailInboxUpdate {
157 #[serde(skip_serializing_if = "Option::is_none")]
158 pub local_part: Option<String>,
159 #[serde(skip_serializing_if = "Option::is_none")]
160 pub forward_to_email: Option<String>,
161 #[serde(skip_serializing_if = "Option::is_none")]
162 pub sender_email: Option<String>,
163}
164
165impl MailInboxUpdate {
166 pub fn is_empty(&self) -> bool {
167 self.local_part.is_none() && self.forward_to_email.is_none() && self.sender_email.is_none()
168 }
169}
170
171#[derive(Serialize, Debug, Clone, Default)]
172pub struct MailTestEmailRequest {
173 #[serde(skip_serializing_if = "Option::is_none")]
174 pub recipient_email: Option<String>,
175 #[serde(skip_serializing_if = "Option::is_none")]
176 pub subject: Option<String>,
177 #[serde(skip_serializing_if = "Option::is_none")]
178 pub body: Option<String>,
179}
180
181#[derive(Deserialize, Serialize, Debug, Clone)]
182pub struct MailTestEmailDelivery {
183 pub message_id: String,
184 pub recipient_email: String,
185 pub delivery_method: String,
186 pub sent_at: String,
187}