1 use {
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)]
10 pub enum MailStatus {
11 #[default]
12 PendingDns = 0,
13 Active = 1,
14 Suspended = 2,
15 }
16
17 impl 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)]
29 pub enum MailMessageStatus {
30 #[default]
31 Received = 0,
32 Forwarded = 1,
33 ForwardFailed = 2,
34 }
35
36 impl 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)]
47 pub struct MailApp {
48 pub id: i32,
49 pub name: String,
50 pub domain: String,
51 pub aws_region: String,
52 pub project_id: i32,
53 pub tenant_id: i32,
54 pub created_at: DateTime<Utc>,
55 pub updated_at: DateTime<Utc>,
56 pub status: MailStatus,
57 pub ses_inbound_mx_value: String,
58 pub inbound_bucket_name: String,
59 pub inbound_email_key_prefix: String,
60 #[serde(default)]
61 pub lambda_config: HashMap<String, String>,
62 #[serde(default)]
63 pub inboxes: Vec<MailInbox>,
64 }
65
66 #[derive(Deserialize, Serialize, Debug, Clone)]
67 pub struct MailInbox {
68 pub id: i32,
69 pub local_part: String,
70 pub full_address: String,
71 pub inbox_email: String,
72 pub sender_email: String,
73 pub forward_to_email: String,
74 pub mail_app_id: i32,
75 pub project_id: i32,
76 pub tenant_id: i32,
77 pub last_test_email_sent_at: Option<DateTime<Utc>>,
78 pub created_at: DateTime<Utc>,
79 pub updated_at: DateTime<Utc>,
80 pub status: MailStatus,
81 pub email_key_prefix: String,
82 #[serde(default)]
83 pub lambda_config: HashMap<String, String>,
84 }
85
86 #[derive(Deserialize, Serialize, Debug, Clone)]
87 pub struct MailMessage {
88 pub id: i32,
89 pub mail_inbox_id: i32,
90 pub provider_message_id: String,
91 pub original_recipient_email: String,
92 pub from_email: String,
93 pub from_name: Option<String>,
94 pub subject: Option<String>,
95 pub text_preview: Option<String>,
96 pub size_bytes: Option<i64>,
97 pub forwarded_at: Option<DateTime<Utc>>,
98 pub forward_error: Option<String>,
99 pub received_at: DateTime<Utc>,
100 pub created_at: DateTime<Utc>,
101 pub updated_at: DateTime<Utc>,
102 pub status: MailMessageStatus,
103 pub text_body: Option<String>,
104 pub html_body: Option<String>,
105 #[serde(default)]
106 pub to_emails: Vec<String>,
107 #[serde(default)]
108 pub cc_emails: Vec<String>,
109 #[serde(default)]
110 pub forward_recipients: Vec<String>,
111 #[serde(default)]
112 pub headers_json: HashMap<String, String>,
113 pub s3_bucket: Option<String>,
114 pub s3_key: Option<String>,
115 }
116
117 #[derive(Serialize, Debug, Clone)]
118 pub struct MailAppCreate {
119 pub name: String,
120 pub project_id: String,
121 pub domain: String,
122 #[serde(skip_serializing_if = "Option::is_none")]
123 pub aws_region: Option<String>,
124 }
125
126 #[derive(Serialize, Debug, Clone, Default)]
127 pub struct MailAppUpdate {
128 #[serde(skip_serializing_if = "Option::is_none")]
129 pub name: Option<String>,
130 #[serde(skip_serializing_if = "Option::is_none")]
131 pub domain: Option<String>,
132 #[serde(skip_serializing_if = "Option::is_none")]
133 pub aws_region: Option<String>,
134 }
135
136 impl MailAppUpdate {
137 pub fn is_empty(&self) -> bool {
138 self.name.is_none() && self.domain.is_none() && self.aws_region.is_none()
139 }
140 }
141
142 #[derive(Serialize, Debug, Clone)]
143 pub struct MailInboxCreate {
144 pub local_part: String,
145 pub forward_to_email: String,
146 #[serde(skip_serializing_if = "Option::is_none")]
147 pub sender_email: Option<String>,
148 }
149
150 #[derive(Serialize, Debug, Clone, Default)]
151 pub struct MailInboxUpdate {
152 #[serde(skip_serializing_if = "Option::is_none")]
153 pub local_part: Option<String>,
154 #[serde(skip_serializing_if = "Option::is_none")]
155 pub forward_to_email: Option<String>,
156 #[serde(skip_serializing_if = "Option::is_none")]
157 pub sender_email: Option<String>,
158 }
159
160 impl MailInboxUpdate {
161 pub fn is_empty(&self) -> bool {
162 self.local_part.is_none() && self.forward_to_email.is_none() && self.sender_email.is_none()
163 }
164 }
165
166 #[derive(Serialize, Debug, Clone, Default)]
167 pub struct MailTestEmailRequest {
168 #[serde(skip_serializing_if = "Option::is_none")]
169 pub recipient_email: Option<String>,
170 #[serde(skip_serializing_if = "Option::is_none")]
171 pub subject: Option<String>,
172 #[serde(skip_serializing_if = "Option::is_none")]
173 pub body: Option<String>,
174 }
175
176 #[derive(Deserialize, Serialize, Debug, Clone)]
177 pub struct MailTestEmailDelivery {
178 pub message_id: String,
179 pub recipient_email: String,
180 pub delivery_method: String,
181 pub sent_at: String,
182 }