Skip to content

Commit

Permalink
refactor: split out HTTP client
Browse files Browse the repository at this point in the history
move the `create_client` method to a separate file; have the `yahoo` and
`gmail` modules reference this.
  • Loading branch information
PsypherPunk committed Oct 5, 2022
1 parent 869232e commit b2d4c25
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 43 deletions.
27 changes: 6 additions & 21 deletions core/src/smtp/gmail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use super::SmtpDetails;
use crate::util::{
constants::LOG_TARGET, input_output::CheckEmailInput, ser_with_display::ser_with_display,
use crate::{
smtp::http_api::create_client,
util::{
constants::LOG_TARGET, input_output::CheckEmailInput, ser_with_display::ser_with_display,
},
};
use async_smtp::EmailAddress;
use reqwest::Error as ReqwestError;
Expand Down Expand Up @@ -45,31 +48,13 @@ impl From<ReqwestError> for GmailError {
}
}

/// Helper function to create a reqwest client, with optional proxy.
fn create_client(input: &CheckEmailInput) -> Result<reqwest::Client, ReqwestError> {
if let Some(proxy) = &input.proxy {
log::debug!(
target: LOG_TARGET,
"[email={}] Using proxy socks://{}:{} for gmail API",
input.to_email,
proxy.host,
proxy.port
);

let proxy = reqwest::Proxy::all(&format!("socks5://{}:{}", proxy.host, proxy.port))?;
reqwest::Client::builder().proxy(proxy).build()
} else {
Ok(reqwest::Client::new())
}
}

/// Use HTTP request to verify if a Gmail email address exists.
/// See: <https://blog.0day.rocks/abusing-gmail-to-get-previously-unlisted-e-mail-addresses-41544b62b2>
pub async fn check_gmail(
to_email: &EmailAddress,
input: &CheckEmailInput,
) -> Result<SmtpDetails, GmailError> {
let response = create_client(input)?
let response = create_client(input, "gmail")?
.head(GLXU_PAGE)
.query(&[("email", to_email)])
.send()
Expand Down
40 changes: 40 additions & 0 deletions core/src/smtp/http_api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// check-if-email-exists
// Copyright (C) 2018-2022 Reacher

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use crate::util::{constants::LOG_TARGET, input_output::CheckEmailInput};
use reqwest::Error as ReqwestError;

/// Helper function to create a reqwest client, with optional proxy.
pub fn create_client(
input: &CheckEmailInput,
api_name: &str,
) -> Result<reqwest::Client, ReqwestError> {
if let Some(proxy) = &input.proxy {
log::debug!(
target: LOG_TARGET,
"[email={}] Using proxy socks://{}:{} for {} API",
input.to_email,
proxy.host,
proxy.port,
api_name,
);

let proxy = reqwest::Proxy::all(&format!("socks5://{}:{}", proxy.host, proxy.port))?;
reqwest::Client::builder().proxy(proxy).build()
} else {
Ok(reqwest::Client::new())
}
}
1 change: 1 addition & 0 deletions core/src/smtp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ mod error;
mod gmail;
#[cfg(feature = "headless")]
mod hotmail;
mod http_api;
mod parser;
mod yahoo;

Expand Down
29 changes: 7 additions & 22 deletions core/src/smtp/yahoo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use super::SmtpDetails;
use crate::util::{
constants::LOG_TARGET, input_output::CheckEmailInput, ser_with_display::ser_with_display,
use crate::{
smtp::http_api::create_client,
util::{
constants::LOG_TARGET, input_output::CheckEmailInput, ser_with_display::ser_with_display,
},
};
use async_smtp::EmailAddress;
use regex::Regex;
Expand Down Expand Up @@ -105,31 +108,13 @@ impl From<SerdeError> for YahooError {
}
}

/// Helper function to create a reqwest client, with optional proxy.
fn create_client(input: &CheckEmailInput) -> Result<reqwest::Client, ReqwestError> {
if let Some(proxy) = &input.proxy {
log::debug!(
target: LOG_TARGET,
"[email={}] Using proxy socks://{}:{} for Yahoo API",
input.to_email,
proxy.host,
proxy.port
);

let proxy = reqwest::Proxy::all(&format!("socks5://{}:{}", proxy.host, proxy.port))?;
reqwest::Client::builder().proxy(proxy).build()
} else {
Ok(reqwest::Client::new())
}
}

/// Use well-crafted HTTP requests to verify if a Yahoo email address exists.
/// Inspired by https://github.com/hbattat/verifyEmail.
pub async fn check_yahoo(
to_email: &EmailAddress,
input: &CheckEmailInput,
) -> Result<SmtpDetails, YahooError> {
let response = create_client(input)?
let response = create_client(input, "yahoo")?
.get(SIGNUP_PAGE)
.header("User-Agent", USER_AGENT)
.send()
Expand Down Expand Up @@ -178,7 +163,7 @@ pub async fn check_yahoo(
};

// Mimic a real HTTP request.
let response = create_client(input)?
let response = create_client(input, "yahoo")?
.post(SIGNUP_API)
.header("Origin", "https://login.yahoo.com")
.header("X-Requested-With", "XMLHttpRequest")
Expand Down

0 comments on commit b2d4c25

Please sign in to comment.