1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use hyper::client::{Client, Response};
use hyper::header::Headers;
use hyper::net::HttpsConnector;
use hyper_native_tls::NativeTlsClient;
use serde::Serialize;
use serde_json;
use std::env;
use std::io::Read;
use regex::Regex;
header! { (XSmtp2goApi, "X-Smtp2go-Api") => [String] }
header! { (XSmtp2goApiVersion, "X-Smtp2go-Api-Version") => [String] }
header! { (XSmtp2goApiKey, "X-Smtp2go-Api-Key") => [String] }
pub trait Smtp2goApiRequest: Serialize {}
#[derive(Debug, Deserialize)]
pub struct Smtp2goApiResponse {
request_id: String,
data: serde_json::Value,
}
#[derive(Debug)]
pub enum Smtp2goApiError {
MissingAPIKey(String),
IncorrectAPIKeyFormat(String),
MissingRequiredField(String),
RequestError(String),
EndpointError(String),
InvalidJSON(String),
}
pub type Smtp2goApiResult = Result<Smtp2goApiResponse, Smtp2goApiError>;
impl Smtp2goApiResponse {
pub fn new<T: Into<String>>(request_id: T, data: serde_json::Value) -> Smtp2goApiResponse {
Smtp2goApiResponse {
request_id: request_id.into(),
data: data,
}
}
}
fn parse_response(mut response: Response) -> Smtp2goApiResult {
let mut text: String = String::new();
response.read_to_string(&mut text).unwrap();
let response: Smtp2goApiResponse = match serde_json::from_str(&text) {
Ok(val) => val,
Err(_) => {
return Err(Smtp2goApiError::InvalidJSON("Unable to parse response JSON".to_string()))
}
};
Ok(response)
}
pub fn api_request<T: Into<String>, U: Smtp2goApiRequest>(endpoint: T, request: &mut U) -> Smtp2goApiResult {
let api_root: String = match env::var("SMTP2GO_API_ROOT") {
Ok(api_root) => api_root,
Err(_) => "https://api.smtp2go.com/v3".to_string(),
};
let api_key: String = match env::var("SMTP2GO_API_KEY") {
Ok(api_key) => api_key,
Err(_) => return Err(Smtp2goApiError::MissingAPIKey("Unable to find an api_key, please set the SMTP2GO_API_KEY environment variable".to_string())),
};
let re = Regex::new(r"^api-[a-zA-Z0-9]{32}$").unwrap();
if !re.is_match(&api_key){
return Err(Smtp2goApiError::IncorrectAPIKeyFormat(format!("The value of SMTP2GO_API_KEY '{}' does not match the api key format of ^api-[a-zA-Z0-9]{{32}}$, please correct it", api_key)))
}
let mut headers = Headers::new();
headers.set(XSmtp2goApi(String::from("smtp2go-rust")).to_owned());
headers.set(XSmtp2goApiVersion(String::from(::VERSION)).to_owned());
headers.set(XSmtp2goApiKey(String::from(api_key)).to_owned());
let ssl = NativeTlsClient::new().unwrap();
let connector = HttpsConnector::new(ssl);
let client = Client::with_connector(connector);
let rjson: String =
match serde_json::to_string(&request) {
Ok(val) => val,
Err(_) => return Err(Smtp2goApiError::InvalidJSON("Unable to serialise request into valid JSON".to_string())),
};
let url: String = format!("{}/{}", api_root, endpoint.into());
match client.post(&url)
.body(&rjson)
.headers(headers)
.send() {
Ok(res) => parse_response(res),
Err(err) => { Err(Smtp2goApiError::RequestError(format!("Somthing went wrong with the request: {}", err))) }
}
}