resend_rust/
emails.rs

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    // TODO: Type this - it's typed as 'object' in Resend's JSON
12    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}