1use crate::{http, parse_response, utils, Client, Error};
2
3#[derive(serde_derive::Deserialize)]
4pub struct SendEmailResponse {
5 pub id: String,
6}
7
8#[derive(serde_derive::Deserialize)]
9pub struct Email {
10 pub id: String,
11 pub object: String,
13 pub to: Vec<String>,
14 pub from: String,
15 pub created_at: String,
16 pub subject: String,
17 pub html: String,
18 pub text: String,
19 pub bcc: Vec<String>,
20 pub cc: Vec<String>,
21 pub reply_to: Vec<String>,
22 pub last_event: String,
23}
24
25#[derive(Debug, Clone, Default, serde_derive::Serialize)]
26pub struct Attachment {
27 content: Vec<u8>,
28 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
29 filename: String,
30 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
31 path: String,
32}
33
34#[derive(Debug, Clone, Default, serde_derive::Serialize)]
35pub struct Tag {
36 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "String::is_empty"))]
37 name: String,
38 value: String,
39}
40
41impl Tag {
42 pub fn new(name: &str, value: &str) -> Self {
43 Self {
44 name: name.to_owned(),
45 value: value.to_owned(),
46 }
47 }
48}
49
50#[derive(Debug, Clone, Default, serde_derive::Serialize)]
51pub struct SendEmailRequest {
52 #[serde(skip_serializing_if = "String::is_empty")]
53 from: String,
54 #[serde(skip_serializing_if = "Vec::is_empty")]
55 to: Vec<String>,
56 #[serde(skip_serializing_if = "String::is_empty")]
57 subject: String,
58
59 bcc: Vec<String>,
60 cc: Vec<String>,
61 reply_to: Vec<String>,
62
63 html: String,
64 text: String,
65
66 headers: hashbrown::HashMap<String, String>,
67 attachments: Vec<Attachment>,
68
69 tags: Vec<Tag>,
70}
71
72impl SendEmailRequest {
73 pub fn builder() -> SendEmailRequestBuilder {
74 SendEmailRequestBuilder::default()
75 }
76}
77
78#[derive(Debug, Clone, Default)]
79pub struct SendEmailRequestBuilder {
80 from: String,
81 to: Vec<String>,
82 subject: String,
83
84 bcc: Vec<String>,
85 cc: Vec<String>,
86 reply_to: Vec<String>,
87
88 html: String,
89 text: String,
90
91 headers: hashbrown::HashMap<String, String>,
92 attachments: Vec<Attachment>,
93
94 tags: Vec<Tag>,
95}
96
97impl SendEmailRequestBuilder {
98 pub fn build(self) -> SendEmailRequest {
99 SendEmailRequest {
100 from: self.from,
101 to: self.to,
102 subject: self.subject,
103 bcc: self.bcc,
104 cc: self.cc,
105 reply_to: self.reply_to,
106 html: self.html,
107 text: self.text,
108 headers: self.headers,
109 attachments: self.attachments,
110 tags: self.tags,
111 }
112 }
113
114 pub fn from(mut self, from: &str) -> Self {
115 self.from = from.to_owned();
116 self
117 }
118
119 pub fn to(mut self, to: &[String]) -> Self {
120 self.to = Vec::from(to);
121 self
122 }
123
124 pub fn subject(mut self, subject: &str) -> Self {
125 self.subject = subject.to_owned();
126 self
127 }
128
129 pub fn bcc(mut self, bcc: &[String]) -> Self {
130 self.bcc = Vec::from(bcc);
131 self
132 }
133
134 pub fn cc(mut self, cc: &[String]) -> Self {
135 self.cc = Vec::from(cc);
136 self
137 }
138
139 pub fn reply_to(mut self, reply_to: &[String]) -> Self {
140 self.reply_to = Vec::from(reply_to);
141 self
142 }
143
144 pub fn html(mut self, html: &str) -> Self {
145 self.html = html.to_owned();
146 self
147 }
148
149 pub fn text(mut self, text: &str) -> Self {
150 self.text = text.to_owned();
151 self
152 }
153
154 pub fn headers(mut self, headers: hashbrown::HashMap<String, String>) -> Self {
155 self.headers = headers;
156 self
157 }
158
159 pub fn add_header(mut self, key: &str, value: &str) -> Self {
160 self.headers.insert(key.to_owned(), value.to_owned());
161 self
162 }
163
164 pub fn attachments(mut self, attachments: &[Attachment]) -> Self {
165 self.attachments = Vec::from(attachments);
166 self
167 }
168
169 pub fn tags(mut self, tags: &[Tag]) -> Self {
170 self.tags = Vec::from(tags);
171 self
172 }
173}
174
175pub async fn send(client: &Client, r: SendEmailRequest) -> Result<SendEmailResponse, Error> {
176 let request_json = serde_json::to_string(&r).map_err(Error::JSON)?;
177
178 let url = utils::url::emails::base(&client.base_url);
179 let request = http::Request::new(http::Method::Post, &url, Some(request_json));
180
181 let response = parse_response(client.perform(request).await.map_err(Error::Client)?).await?;
182 serde_json::from_str(&response).map_err(Error::JSON)
183}
184
185pub async fn get(client: &Client, email_id: &str) -> Result<Email, Error> {
186 let url = utils::url::emails::with_id(&client.base_url, email_id);
187 let request = http::Request::new(http::Method::Get, &url, None);
188
189 let response = parse_response(client.perform(request).await.map_err(Error::Client)?).await?;
190 serde_json::from_str(&response).map_err(Error::JSON)
191}