email_clients/clients/mailersend.rs
1use crate::configuration::EmailConfiguration;
2use crate::email::{EmailAddress, EmailObject};
3use crate::traits::EmailTrait;
4use crate::Result;
5use async_trait::async_trait;
6use reqwest::header::HeaderMap;
7use reqwest::{header, Client, Method};
8use secrecy::{ExposeSecret, Secret};
9
10static BASE_URL: &str = "https://api.mailersend.com/v1";
11
12fn default_base_url() -> String {
13 BASE_URL.to_string()
14}
15
16/// `MailerSendConfig` structure that includes sender, base_url, and api_token.
17///
18/// ```rust
19/// use email_clients::clients::mailersend::MailerSendConfig;
20///
21/// let mut mailer_send_config = MailerSendConfig::default()
22/// .sender("sender@example.com")
23/// .base_url("https://api.mailersend.com/v1")
24/// .api_token("test_api_token");
25/// assert_eq!(mailer_send_config.get_sender().to_string(), "sender@example.com");
26/// assert_eq!(mailer_send_config.get_base_url(), "https://api.mailersend.com/v1");
27/// ```
28#[derive(Debug, Clone, serde::Deserialize)]
29pub struct MailerSendConfig {
30 sender: EmailAddress,
31 #[serde(default = "default_base_url")]
32 base_url: String,
33 api_token: Secret<String>,
34}
35
36#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
37struct EmailPayload {
38 from: EmailAddress,
39 to: Vec<EmailAddress>,
40 subject: String,
41 text: String,
42 html: String,
43}
44
45impl From<EmailObject> for EmailPayload {
46 fn from(value: EmailObject) -> Self {
47 Self {
48 from: value.sender,
49 to: value.to,
50 subject: value.subject,
51 text: value.plain,
52 html: value.html,
53 }
54 }
55}
56
57impl Default for MailerSendConfig {
58 /// Constructs a `MailerSendConfig` with default values:
59 /// - sender: An empty string `""`
60 /// - base_url: `https://api.mailersend.com/v1`
61 /// - api_token: An empty string `""`
62 ///
63 /// # Examples
64 ///
65 /// Basic usage:
66 ///
67 /// ```rust
68 /// use email_clients::clients::mailersend::MailerSendConfig;
69 ///
70 /// let config = MailerSendConfig::default();
71 ///
72 /// assert_eq!(config.get_sender().to_string(), "");
73 /// assert_eq!(config.get_base_url(), "https://api.mailersend.com/v1");
74 /// ```
75 ///
76 fn default() -> Self {
77 Self {
78 sender: "".into(),
79 base_url: BASE_URL.to_string(),
80 api_token: Secret::from("".to_string()),
81 }
82 }
83}
84
85impl MailerSendConfig {
86 /// Sets the sender of the Mailersend config.
87 ///
88 /// ```rust
89 /// use email_clients::clients::mailersend::MailerSendConfig;
90 ///
91 /// let mut smtp_config = MailerSendConfig::default().sender("Test Sender");
92 /// assert_eq!(smtp_config.get_sender().to_string(), "Test Sender");
93 /// ```
94 pub fn sender(mut self, value: impl Into<EmailAddress>) -> Self {
95 self.sender = value.into();
96 self
97 }
98
99 /// Sets the base_url of the Mailersend config.
100 ///
101 /// ```rust
102 /// use email_clients::clients::mailersend::MailerSendConfig;
103 ///
104 /// let mut smtp_config = MailerSendConfig::default().base_url("Test URL");
105 /// assert_eq!(smtp_config.get_base_url(), "Test URL");
106 /// ```
107 pub fn base_url(mut self, value: impl AsRef<str>) -> Self {
108 self.base_url = value.as_ref().trim_end_matches('/').to_string();
109 self
110 }
111
112 /// Sets the api_token of the Mailersend config.
113 ///
114 /// ```rust
115 /// use email_clients::clients::mailersend::MailerSendConfig;
116 ///
117 /// let mut smtp_config = MailerSendConfig::default().api_token("Test Token");
118 /// ```
119 pub fn api_token(mut self, value: impl AsRef<str>) -> Self {
120 self.api_token = Secret::new(value.as_ref().to_string());
121 self
122 }
123
124 /// Returns the base url of the Mailersend config.
125 ///
126 /// # Example
127 ///
128 /// ```rust
129 /// use email_clients::clients::mailersend::MailerSendConfig;
130 ///
131 /// let smtp_config = MailerSendConfig::default().base_url("https://api.mailersend.com/v1");
132 /// assert_eq!(smtp_config.get_base_url(), "https://api.mailersend.com/v1");
133 /// ```
134 ///
135 pub fn get_base_url(&self) -> String {
136 self.base_url.to_string()
137 }
138
139 /// Returns the sender of the Mailersend config.
140 ///
141 /// # Example
142 ///
143 /// ```rust
144 /// use email_clients::clients::mailersend::MailerSendConfig;
145 ///
146 /// let mailer_send_config = MailerSendConfig::default().sender("test_sender@example.com");
147 /// assert_eq!(mailer_send_config.get_sender().to_string(), "test_sender@example.com");
148 /// ```
149 ///
150 pub fn get_sender(&self) -> EmailAddress {
151 self.sender.clone()
152 }
153}
154
155impl From<MailerSendConfig> for EmailConfiguration {
156 /// Converts a `MailerSendConfig` into an `EmailConfiguration`
157 ///
158 /// This conversion is mainly used when we are setting the configuration for our email client.
159 ///
160 /// # Example
161 ///
162 /// ```rust
163 /// use email_clients::clients::mailersend::MailerSendConfig;
164 /// use email_clients::configuration::EmailConfiguration;
165 ///
166 /// let mailer_config = MailerSendConfig::default()
167 /// .sender("sender@example.com")
168 /// .base_url("https://api.mailersend.com/v1")
169 /// .api_token("test_api_token");
170 ///
171 /// let email_config: EmailConfiguration = mailer_config.into();
172 /// ```
173 fn from(value: MailerSendConfig) -> Self {
174 EmailConfiguration::Mailersend(value)
175 }
176}
177
178/// `MailerSendClient` structure that includes 'config' and 'reqwest_client'.
179///
180/// ```rust
181/// use email_clients::clients::mailersend::MailerSendConfig;
182/// use email_clients::clients::mailersend::MailerSendClient;
183///
184/// let mailer_send_config = MailerSendConfig::default()
185/// .sender("sender@example.com")
186/// .base_url("https://api.mailersend.com/v1")
187/// .api_token("test_api_token");
188/// let mailer_send_client = MailerSendClient::new(mailer_send_config);
189/// ```
190#[derive(Clone, Debug, Default)]
191pub struct MailerSendClient {
192 config: MailerSendConfig,
193 reqwest_client: Client,
194}
195
196impl MailerSendClient {
197 pub fn new(config: MailerSendConfig) -> Self {
198 let reqwest_client = Client::new();
199
200 MailerSendClient {
201 config,
202 reqwest_client,
203 }
204 }
205
206 fn url(&self) -> String {
207 format!("{}/email", self.config.base_url.trim_end_matches('/'))
208 }
209
210 fn headers(&self) -> Result<HeaderMap> {
211 let mut headers = HeaderMap::new();
212 headers.insert(
213 header::AUTHORIZATION,
214 format!("Bearer {}", self.config.api_token.expose_secret()).parse()?,
215 );
216 Ok(headers)
217 }
218}
219
220#[async_trait]
221impl EmailTrait for MailerSendClient {
222 /// Returns the sender included in the `MailerSendClient`'s configuration.
223 ///
224 /// # Examples
225 ///
226 /// Basic usage:
227 ///
228 /// ```rust
229 /// use email_clients::clients::mailersend::MailerSendConfig;
230 /// use email_clients::clients::mailersend::MailerSendClient;
231 /// use email_clients::traits::EmailTrait;
232 ///
233 /// let mailer_send_config = MailerSendConfig::default()
234 /// .sender("sender@example.com")
235 /// .base_url("https://api.mailersend.com/v1")
236 /// .api_token("test_api_token");
237 ///
238 /// let mailer_send_client = MailerSendClient::new(mailer_send_config);
239 ///
240 /// assert_eq!(mailer_send_client.get_sender().to_string(), "sender@example.com");
241 /// ```
242 fn get_sender(&self) -> EmailAddress {
243 self.config.get_sender().clone()
244 }
245
246 async fn send_emails(&self, email: EmailObject) -> Result<()> {
247 let payload: EmailPayload = email.into();
248 self.reqwest_client
249 .request(Method::POST, self.url())
250 .headers(self.headers()?)
251 .json(&payload)
252 .send()
253 .await?
254 .error_for_status()?;
255 Ok(())
256 }
257}