1use crate::error::Error;
2use serde::{Deserialize, Serialize};
3
4const API_URL: &str = "https://api.resend.com/emails";
5
6#[derive(Debug, Deserialize)]
7pub struct Email {
8 pub id: String,
9}
10pub struct ResendClient<'a> {
11 auth_token: &'a str,
12}
13
14impl<'a> ResendClient<'a> {
15 pub fn new(auth_token: &'a str) -> Self {
16 ResendClient { auth_token }
17 }
18
19 pub async fn send(&self, mail: &impl Serialize) -> Result<Email, Error> {
20 let resp = reqwest::Client::new()
21 .post(API_URL)
22 .bearer_auth(self.auth_token)
23 .header(reqwest::header::CONTENT_TYPE, "application/json")
24 .json(mail)
25 .send()
26 .await
27 .unwrap();
28
29 match resp.status().is_success() {
30 true => {
31 let email: Email = resp.json().await.unwrap();
32 Ok(email)
33 }
34 false => Err(Error::ResendError(resp.text().await.unwrap())),
35 }
36 }
37}
38
39#[cfg(test)]
40mod tests {
41 use super::super::mail::{Attachment, MailHtml, MailText};
42 use super::ResendClient;
43 use dotenv::dotenv;
44 use std::env;
45 use tokio;
46
47 struct Credentials {
48 auth_token: String,
49 test_email: String,
50 }
51
52 fn get_credentials() -> Credentials {
53 dotenv().ok();
54 let auth_token = env::var("AUTH_TOKEN").unwrap();
55 let test_email = env::var("TEST_EMAIL").unwrap();
56
57 Credentials {
58 auth_token,
59 test_email,
60 }
61 }
62
63 #[tokio::test]
64 async fn send_mail_text() {
65 let credentials = get_credentials();
66 let mail = MailText {
67 from: "Acme <onboarding@resend.dev>",
68 to: vec![&credentials.test_email],
69 subject: "a",
70 text: "a",
71 attachments: None,
72 };
73
74 let client = ResendClient::new(&credentials.auth_token);
75 let resp = client.send(&mail).await.unwrap();
76 println!("{:?}", resp);
77 }
78
79 #[tokio::test]
80 async fn send_mail_html() {
81 let credentials = get_credentials();
82 let mail = MailHtml {
83 from: "Acme <onboarding@resend.dev>",
84 to: vec![&credentials.test_email],
85 subject: "a",
86 html: "<p>hola</p>",
87 attachments: None,
88 };
89
90 let client = ResendClient::new(&credentials.auth_token);
91 let resp = client.send(&mail).await.unwrap();
92 println!("{:?}", resp);
93 }
94
95 #[test]
96 fn format() {
97 let mail = MailText {
98 from: "a",
99 to: vec!["a"],
100 subject: "a",
101 text: "a",
102 attachments: None,
103 };
104
105 assert_eq!(
106 serde_json::to_string(&mail).unwrap(),
107 r#"{"from":"a","to":["a"],"subject":"a","text":"a","attachments":null}"#
108 );
109 }
110
111 #[test]
112 fn format_attachment() {
113 let image = Attachment {
114 content: vec![],
115 filename: "image.png",
116 };
117
118 let mail = MailText {
119 from: "a",
120 to: vec!["a"],
121 subject: "a",
122 text: "a",
123 attachments: Some(vec![image]),
124 };
125
126 assert_eq!(
127 serde_json::to_string(&mail).unwrap(),
128 r#"{"from":"a","to":["a"],"subject":"a","text":"a","attachments":[{"content":[],"filename":"image.png"}]}"#
129 );
130 }
131}