mailjet_rs/client/
mailjet.rs

1use crate::api::common::Payload;
2use crate::client::error::Error as MailjetError;
3use crate::client::response::Response as MailjetResponse;
4use crate::client::status_code::StatusCode as MailjetStatusCode;
5use crate::client::version::SendAPIVersion;
6use http_auth_basic::Credentials;
7use hyper::client::{Client as HyperClient, HttpConnector};
8use hyper::Error as HyperError;
9use hyper::{Body, Request, Response};
10#[cfg(feature = "rustls")]
11use hyper_rustls::HttpsConnector;
12#[cfg(not(feature = "rustls"))]
13use hyper_tls::HttpsConnector;
14
15/// Mailjet's Email API uses the API keys provided by Mailjet for your account [here](https://app.mailjet.com/account/api_keys).
16///
17/// These are used to create an instance of the `Client` as follows:
18///
19/// ```ignore
20/// let client = Client::new(
21///     SendAPIVersion::V3,
22///     "public_key",
23///     "private_key",
24/// );
25/// ```
26///
27pub struct Client {
28    pub keys: Credentials,
29    pub encoded_credentials: String,
30    http_client: HyperClient<HttpsConnector<HttpConnector>>,
31    api_base: String,
32}
33
34impl Client {
35    /// Creates an authenticated Mailjet client by using the provided
36    /// `public_key` and `private_key`
37    pub fn new(send_api_version: SendAPIVersion, public_key: &str, private_key: &str) -> Self {
38        // Creates a basic authentication `Credentials` struct used to authenticate to the
39        // Email API.
40        //
41        // The `user_id` is represented by the `public_key` and the `password` by the `private_key`.
42        //
43        // Reference: https://dev.mailjet.com/email/guides/
44        //
45
46        if public_key.is_empty() || private_key.is_empty() {
47            panic!("Invalid `public_key` or `private_key` provided");
48        }
49
50        let keys = Credentials::new(public_key, private_key);
51        let encoded_credentials = keys.as_http_header();
52        #[cfg(feature = "rustls")]
53        let https = hyper_rustls::HttpsConnectorBuilder::new()
54            .with_webpki_roots()
55            .https_only()
56            .enable_http2()
57            .build();
58        #[cfg(not(feature = "rustls"))]
59        let https = HttpsConnector::new();
60        let http_client = HyperClient::builder().build::<_, hyper::Body>(https);
61
62        Self {
63            api_base: send_api_version.get_api_url(),
64            encoded_credentials,
65            http_client,
66            keys,
67        }
68    }
69
70    pub async fn send(&self, messages: impl Payload) -> Result<MailjetResponse, MailjetError> {
71        let as_json = messages.to_json();
72
73        println!("{}", as_json);
74
75        let response = self.post(Body::from(as_json), "/send").await.unwrap();
76        let (parts, body) = response.into_parts();
77
78        if parts.status.is_client_error() || parts.status.is_server_error() {
79            let mailjet_error =
80                MailjetError::from_api_response(MailjetStatusCode::from(parts.status), body).await;
81
82            return Err(mailjet_error);
83        }
84
85        Ok(MailjetResponse::from_api_response(body).await)
86    }
87
88    async fn post(&self, body: Body, uri: &str) -> Result<Response<Body>, HyperError> {
89        let uri = format!("{}{}", self.api_base, uri);
90
91        let req = Request::builder()
92            .method("POST")
93            .header("Content-Type", "application/json")
94            .header("Authorization", self.encoded_credentials.as_str())
95            .uri(uri)
96            .body(body)
97            .expect("Failed to build POST request");
98
99        self.http_client.request(req).await
100    }
101}
102
103#[cfg(test)]
104mod tests {
105    use super::*;
106
107    #[test]
108    fn it_creates_a_client_instance_send_api_v3() {
109        let have = Client::new(SendAPIVersion::V3, "public_key", "private_key");
110
111        assert_eq!(have.api_base, "https://api.mailjet.com/v3");
112        assert_eq!(have.keys.user_id, "public_key");
113        assert_eq!(have.keys.password, "private_key");
114    }
115
116    #[test]
117    fn it_creates_a_client_instance_send_api_v3_1() {
118        let have = Client::new(SendAPIVersion::V3_1, "public_key", "private_key");
119
120        assert_eq!(have.api_base, "https://api.mailjet.com/v3.1");
121        assert_eq!(have.keys.user_id, "public_key");
122        assert_eq!(have.keys.password, "private_key");
123    }
124
125    #[test]
126    #[should_panic(expected = "Invalid `public_key` or `private_key` provided")]
127    fn it_panics_if_invalid_keys_are_provided() {
128        Client::new(SendAPIVersion::V3_1, "", "");
129    }
130}