mailjet_rs/client/
mailjet.rs1use 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
15pub 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 pub fn new(send_api_version: SendAPIVersion, public_key: &str, private_key: &str) -> Self {
38 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}