Skip to main content

mailer/
lib.rs

1use reqwest::{
2    header::{HeaderMap, HeaderValue},
3    Client as HttpClient, StatusCode, Url,
4};
5use serde::Serialize;
6use std::time::Duration;
7
8mod builders;
9mod error;
10mod types;
11
12use builders::*;
13pub use error::Error;
14use error::Result;
15pub use types::Format;
16use types::{Request, Response};
17
18/// A client for the WaffleHacks mailer
19#[derive(Debug)]
20pub struct Client {
21    client: HttpClient,
22    base_url: Url,
23}
24
25impl Client {
26    /// Create a new mailer client
27    pub fn new(base_url: Url) -> Self {
28        // Create the default headers
29        let mut headers = HeaderMap::new();
30        headers.insert("Content-Type", HeaderValue::from_static("application/json"));
31
32        // This shouldn't ever return an error
33        let client = HttpClient::builder()
34            .default_headers(headers)
35            .timeout(Duration::from_secs(10))
36            .build()
37            .unwrap();
38
39        Client { client, base_url }
40    }
41
42    /// Send a request to the server
43    pub(crate) async fn dispatch<T>(&self, path: &str, req: Request<'_, T>) -> Result<()>
44    where
45        T: Serialize,
46    {
47        let resp = self
48            .client
49            .post(self.base_url.join(path).unwrap())
50            .json(&req)
51            .send()
52            .await?;
53
54        let status = resp.status();
55        if status == StatusCode::OK {
56            Ok(())
57        } else {
58            let body: Response = resp.json().await?;
59            if status == StatusCode::BAD_REQUEST {
60                Err(Error::InvalidArgument(body.message))
61            } else {
62                Err(Error::Unknown(body.message))
63            }
64        }
65    }
66
67    /// Send a single email
68    pub async fn send<'s>(
69        &'s self,
70        to: &'s str,
71        from: &'s str,
72        subject: &'s str,
73        body: &'s str,
74    ) -> SendBuilder<'s> {
75        SendBuilder::new(self, to, from, subject, body)
76    }
77
78    /// Send an email to many recipients
79    pub async fn send_batch<'s>(
80        &'s self,
81        from: &'s str,
82        subject: &'s str,
83        body: &'s str,
84    ) -> SendBatchBuilder<'s> {
85        SendBatchBuilder::new(self, from, subject, body)
86    }
87
88    /// Send a templated email to many recipients
89    pub async fn send_template<'s>(
90        &'s self,
91        from: &'s str,
92        subject: &'s str,
93        body: &'s str,
94    ) -> SendTemplateBuilder<'s> {
95        SendTemplateBuilder::new(self, from, subject, body)
96    }
97}