smbcloud_email_sdk/
message.rs1use serde::{Deserialize, Serialize};
2use serde_repr::{Deserialize_repr, Serialize_repr};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize_repr, Deserialize_repr)]
8#[repr(u8)]
9pub enum EmailStatus {
10 Queued = 0,
11 Sent = 1,
12 Delivered = 2,
13 Bounced = 3,
14 Complained = 4,
15 Failed = 5,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct Attachment {
22 pub filename: String,
23 pub content_base64: String,
24}
25
26#[derive(Debug, Clone, Default, Serialize, Deserialize)]
32#[serde(default)]
33pub struct SendEmail {
34 pub from: String,
35 pub to: Vec<String>,
36 #[serde(skip_serializing_if = "Vec::is_empty")]
37 pub cc: Vec<String>,
38 #[serde(skip_serializing_if = "Vec::is_empty")]
39 pub bcc: Vec<String>,
40 #[serde(skip_serializing_if = "Vec::is_empty")]
41 pub reply_to: Vec<String>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub subject: Option<String>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub html: Option<String>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub text: Option<String>,
48 #[serde(skip_serializing_if = "Vec::is_empty")]
49 pub attachments: Vec<Attachment>,
50 #[serde(skip_serializing_if = "std::collections::HashMap::is_empty")]
51 pub headers: std::collections::HashMap<String, String>,
52 #[serde(skip_serializing_if = "std::collections::HashMap::is_empty")]
53 pub tags: std::collections::HashMap<String, String>,
54 #[serde(skip_serializing_if = "Option::is_none")]
55 pub idempotency_key: Option<String>,
56}
57
58impl SendEmail {
59 pub fn new(from: impl Into<String>, to: impl IntoIterator<Item = impl Into<String>>) -> Self {
61 SendEmail {
62 from: from.into(),
63 to: to.into_iter().map(Into::into).collect(),
64 ..Default::default()
65 }
66 }
67
68 pub fn subject(mut self, subject: impl Into<String>) -> Self {
69 self.subject = Some(subject.into());
70 self
71 }
72
73 pub fn html(mut self, html: impl Into<String>) -> Self {
74 self.html = Some(html.into());
75 self
76 }
77
78 pub fn text(mut self, text: impl Into<String>) -> Self {
79 self.text = Some(text.into());
80 self
81 }
82
83 pub fn cc(mut self, cc: impl IntoIterator<Item = impl Into<String>>) -> Self {
84 self.cc = cc.into_iter().map(Into::into).collect();
85 self
86 }
87
88 pub fn bcc(mut self, bcc: impl IntoIterator<Item = impl Into<String>>) -> Self {
89 self.bcc = bcc.into_iter().map(Into::into).collect();
90 self
91 }
92
93 pub fn reply_to(mut self, reply_to: impl IntoIterator<Item = impl Into<String>>) -> Self {
94 self.reply_to = reply_to.into_iter().map(Into::into).collect();
95 self
96 }
97
98 pub fn attachment(mut self, attachment: Attachment) -> Self {
99 self.attachments.push(attachment);
100 self
101 }
102
103 pub fn header(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
104 self.headers.insert(key.into(), value.into());
105 self
106 }
107
108 pub fn tag(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
109 self.tags.insert(key.into(), value.into());
110 self
111 }
112
113 pub fn idempotency_key(mut self, key: impl Into<String>) -> Self {
116 self.idempotency_key = Some(key.into());
117 self
118 }
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
125pub struct EmailEvent {
126 pub id: String,
127 pub event_type: u8,
128 #[serde(default)]
129 pub payload: serde_json::Value,
130 pub occurred_at: String,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
136pub struct EmailMessage {
137 pub id: String,
138 pub status: EmailStatus,
139 pub provider_message_id: Option<String>,
140 pub idempotency_key: Option<String>,
141 pub from_email: String,
142 #[serde(default)]
143 pub to_emails: Vec<String>,
144 pub subject: Option<String>,
145 pub sent_at: Option<String>,
146 pub created_at: Option<String>,
147 #[serde(default)]
149 pub events: Vec<EmailEvent>,
150}