zero_bounce/api/
validation.rs1use std::collections::HashMap;
2
3use serde::Serialize;
4use serde_json::from_str;
5use serde_json::{Map as SerdeMap, Value};
6
7use crate::{ZeroBounce, ZBResult};
8use crate::utility::{ENDPOINT_VALIDATE, ZBError, ENDPOINT_BATCH_VALIDATE, CONTENT_TYPE_JSON};
9use crate::utility::structures::validation::{ZBValidation, ZBBatchValidation};
10
11
12impl ZeroBounce {
13
14 pub fn validate_email_and_ip(&self, email: &str, ip_address: &str) -> ZBResult<ZBValidation> {
15 let mut query_args = HashMap::from([
16 ("email", email),
17 ]);
18
19 if !ip_address.is_empty() {
20 query_args.insert("ip_address", ip_address);
21 }
22
23 let response_content = self.generic_get_request(
24 self.url_provider.url_of(ENDPOINT_VALIDATE), query_args
25 )?;
26
27 let validation = from_str::<ZBValidation>(&response_content)?;
28 Ok(validation)
29 }
30
31 pub fn validate_email(&self, email: &str) -> ZBResult<ZBValidation> {
32 self.validate_email_and_ip(email, "")
33 }
34
35 fn batch_validate_prepare_body(&self, emails_and_ip_addresses: Vec<(String, String)>) -> ZBResult<String> {
51 let email_batch = emails_and_ip_addresses
52 .into_iter()
53 .map(|(email, ip_address)|
54 [
55 ("email_address".to_string(), Value::String(email)),
56 ("ip_address".to_string(), Value::String(ip_address)),
57 ]
58 )
59 .map(SerdeMap::<String, Value>::from_iter)
60 .map(Value::Object)
61 .collect::<Vec<Value>>();
62
63 let request_body_map = SerdeMap::from_iter([
64 ("api_key".to_string(), Value::String(self.api_key.clone())),
65 ("email_batch".to_string(), Value::Array(email_batch)),
66 ]);
67
68 let mut serializer = serde_json::Serializer::new(Vec::new());
70 Value::Object(request_body_map)
71 .serialize(&mut serializer)
72 .map_err(ZBError::JsonError)?;
73
74 let final_string = String::from_utf8(serializer.into_inner())
75 .map_err(|error| ZBError::ExplicitError(error.to_string()))?;
76
77 Ok(final_string)
78 }
79
80 pub fn batch_validate(&self, emails_and_ip_addresses: Vec<(String, String)>) -> ZBResult<ZBBatchValidation> {
81 let body_content = self.batch_validate_prepare_body(emails_and_ip_addresses)?;
82 let url = self.url_provider.url_of(ENDPOINT_BATCH_VALIDATE);
83
84 let response = self.client.post(url)
85 .body(body_content)
86 .header("content-type", CONTENT_TYPE_JSON)
87 .send()?;
88
89 let response_ok = response.status().is_success();
90 let response_content = response.text()?;
91
92 #[cfg(debug_assertions)]
94 {
95 eprintln!("Raw API response: {}", response_content);
96 }
97
98 if !response_ok {
99 return Err(ZBError::ExplicitError(response_content));
100 }
101
102 let validation = from_str::<ZBBatchValidation>(response_content.as_str())?;
103 Ok(validation)
104 }
105
106}
107
108#[cfg(test)]
109mod test {
110 use crate::ZeroBounce;
111
112 #[test]
113 fn test_serializing_example() {
114 let emails_and_ip_addresses = vec![
115 ("valid@example.com".to_string(), "123.123.123.123".to_string()),
116 ("invalid@example.com".to_string(), "".to_string()),
117 ];
118
119 let body_result = ZeroBounce::new("some_api_key")
120 .batch_validate_prepare_body(emails_and_ip_addresses);
121
122 assert!(body_result.is_ok())
123 }
124
125}