1use error::RestmailClientError;
6use error_support::{info, warn};
7use serde_json::Value as EmailJson;
8use url::Url;
9use viaduct::Request;
10
11mod error;
12
13type Result<T> = std::result::Result<T, RestmailClientError>;
14
15pub fn find_email<F>(email: &str, predicate: F, max_tries: u8) -> Result<EmailJson>
19where
20 F: Fn(&EmailJson) -> bool,
21{
22 let mail_url = url_for_email(email)?;
23 info!("Checking {} up to {} times.", email, max_tries);
24 for i in 0..max_tries {
25 let resp: Vec<serde_json::Value> = Request::get(mail_url.clone()).send()?.json()?;
26 let mut matching_emails: Vec<serde_json::Value> =
27 resp.into_iter().filter(|email| predicate(email)).collect();
28
29 if matching_emails.is_empty() {
30 info!(
31 "Failed to find matching email. Waiting {} seconds and retrying.",
32 i + 1
33 );
34 std::thread::sleep(std::time::Duration::from_secs((i + 1).into()));
35 continue;
36 }
37
38 if matching_emails.len() > 1 {
39 info!(
40 "Found {} emails that applies (taking latest)",
41 matching_emails.len()
42 );
43 matching_emails.sort_by(|a, b| {
44 let a_time = a["receivedAt"].as_u64();
45 let b_time = b["receivedAt"].as_u64();
46 match (a_time, b_time) {
47 (Some(a_time), Some(b_time)) => b_time.cmp(&a_time),
48 _ => {
49 warn!("Could not de-serialize receivedAt for at least one of the emails.");
50 std::cmp::Ordering::Equal
51 }
52 }
53 })
54 }
55 return Ok(matching_emails[0].clone());
56 }
57 info!("Error: Failed to find email after {} tries!", max_tries);
58 Err(RestmailClientError::HitRetryMax)
59}
60
61pub fn clear_mailbox(email: &str) -> Result<()> {
62 let mail_url = url_for_email(email)?;
63 info!("Clearing restmail for {}.", email);
64 Request::delete(mail_url).send()?;
65 Ok(())
66}
67
68fn username_from_email(email: &str) -> Result<String> {
69 let user = email.replace("@restmail.net", "");
70 if user.len() == email.len() {
71 return Err(RestmailClientError::NotARestmailEmail);
72 }
73 Ok(user)
74}
75
76fn url_for_email(email: &str) -> Result<Url> {
77 let restmail_user = username_from_email(email)?;
78 let path = format!("/mail/{}", restmail_user);
79 Ok(Url::parse("https://restmail.net")?.join(&path)?)
80}