Skip to main content

smbcloud_model/
mail.rs

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: 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)]
67pub 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)]
87pub 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)]
118pub 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)]
127pub 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
136impl 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)]
143pub 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)]
151pub 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
160impl 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)]
167pub 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)]
177pub struct MailTestEmailDelivery {
178    pub message_id: String,
179    pub recipient_email: String,
180    pub delivery_method: String,
181    pub sent_at: String,
182}