diff --git a/src/configure.rs b/src/configure.rs index 63a4dec1a..63e85dcd6 100644 --- a/src/configure.rs +++ b/src/configure.rs @@ -17,12 +17,13 @@ use crate::context::Context; use crate::imap::Imap; use crate::job; use crate::log::LogExt; -use crate::login_param::{CertificateChecks, LoginParam, ServerLoginParam, Socks5Config}; +use crate::login_param::{CertificateChecks, LoginParam, ServerLoginParam}; use crate::message::{Message, Viewtype}; use crate::oauth2::get_oauth2_addr; use crate::provider::{Protocol, Socket, UsernamePattern}; use crate::scheduler::InterruptInfo; use crate::smtp::Smtp; +use crate::socks::Socks5Config; use crate::stock_str; use crate::tools::{time, EmailAddress}; use crate::{chat, e2ee, provider}; diff --git a/src/imap.rs b/src/imap.rs index 2f22fe4a0..7543c4dd2 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -27,9 +27,7 @@ use crate::context::Context; use crate::events::EventType; use crate::headerdef::{HeaderDef, HeaderDefMap}; use crate::job; -use crate::login_param::{ - CertificateChecks, LoginParam, ServerAddress, ServerLoginParam, Socks5Config, -}; +use crate::login_param::{CertificateChecks, LoginParam, ServerAddress, ServerLoginParam}; use crate::message::{self, Message, MessageState, MessengerMessage, MsgId, Viewtype}; use crate::mimeparser; use crate::oauth2::get_oauth2_access_token; @@ -39,6 +37,7 @@ use crate::receive_imf::{ }; use crate::scheduler::connectivity::ConnectivityStore; use crate::scheduler::InterruptInfo; +use crate::socks::Socks5Config; use crate::sql; use crate::stock_str; use crate::tools::create_id; diff --git a/src/imap/client.rs b/src/imap/client.rs index b6f4867ad..7ae0615b3 100644 --- a/src/imap/client.rs +++ b/src/imap/client.rs @@ -15,7 +15,8 @@ use tokio_io_timeout::TimeoutStream; use super::capabilities::Capabilities; use super::session::Session; -use crate::login_param::{build_tls, Socks5Config}; +use crate::login_param::build_tls; +use crate::socks::Socks5Config; use super::session::SessionStream; diff --git a/src/lib.rs b/src/lib.rs index af53d0839..f3925a306 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,6 +90,7 @@ pub mod quota; pub mod securejoin; mod simplify; mod smtp; +mod socks; pub mod stock_str; mod sync; mod token; diff --git a/src/login_param.rs b/src/login_param.rs index b6749f24f..feb2e4e73 100644 --- a/src/login_param.rs +++ b/src/login_param.rs @@ -2,17 +2,15 @@ use std::borrow::Cow; use std::fmt; -use std::time::Duration; use anyhow::{ensure, Result}; use async_native_tls::Certificate; pub use async_smtp::ServerAddress; -use fast_socks5::client::Socks5Stream; use once_cell::sync::Lazy; -use tokio::{io, net::TcpStream}; use crate::constants::{DC_LP_AUTH_FLAGS, DC_LP_AUTH_NORMAL, DC_LP_AUTH_OAUTH2}; use crate::provider::{get_provider_by_id, Provider}; +use crate::socks::Socks5Config; use crate::{context::Context, provider::Socket}; #[derive(Copy, Clone, Debug, Display, FromPrimitive, ToPrimitive, PartialEq, Eq)] @@ -53,81 +51,6 @@ pub struct ServerLoginParam { pub certificate_checks: CertificateChecks, } -#[derive(Default, Debug, Clone, PartialEq, Eq)] -pub struct Socks5Config { - pub host: String, - pub port: u16, - pub user_password: Option<(String, String)>, -} - -impl Socks5Config { - /// Reads SOCKS5 configuration from the database. - pub async fn from_database(context: &Context) -> Result> { - let sql = &context.sql; - - let enabled = sql.get_raw_config_bool("socks5_enabled").await?; - if enabled { - let host = sql.get_raw_config("socks5_host").await?.unwrap_or_default(); - let port: u16 = sql - .get_raw_config_int("socks5_port") - .await? - .unwrap_or_default() as u16; - let user = sql.get_raw_config("socks5_user").await?.unwrap_or_default(); - let password = sql - .get_raw_config("socks5_password") - .await? - .unwrap_or_default(); - - let socks5_config = Self { - host, - port, - user_password: if !user.is_empty() { - Some((user, password)) - } else { - None - }, - }; - Ok(Some(socks5_config)) - } else { - Ok(None) - } - } - - pub async fn connect( - &self, - target_addr: &ServerAddress, - timeout: Option, - ) -> io::Result> { - self.to_async_smtp_socks5_config() - .connect(target_addr, timeout) - .await - } - - pub fn to_async_smtp_socks5_config(&self) -> async_smtp::smtp::Socks5Config { - async_smtp::smtp::Socks5Config { - host: self.host.clone(), - port: self.port, - user_password: self.user_password.clone(), - } - } -} - -impl fmt::Display for Socks5Config { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "host:{},port:{},user_password:{}", - self.host, - self.port, - if let Some(user_password) = self.user_password.clone() { - format!("user: {}, password: ***", user_password.0) - } else { - "user: None".to_string() - } - ) - } -} - #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct LoginParam { pub addr: String, diff --git a/src/smtp.rs b/src/smtp.rs index a9fc3ec1a..b3669e690 100644 --- a/src/smtp.rs +++ b/src/smtp.rs @@ -13,14 +13,13 @@ use tokio::task; use crate::config::Config; use crate::contact::{Contact, ContactId}; use crate::events::EventType; -use crate::login_param::{ - build_tls, CertificateChecks, LoginParam, ServerLoginParam, Socks5Config, -}; +use crate::login_param::{build_tls, CertificateChecks, LoginParam, ServerLoginParam}; use crate::message::Message; use crate::message::{self, MsgId}; use crate::mimefactory::MimeFactory; use crate::oauth2::get_oauth2_access_token; use crate::provider::Socket; +use crate::socks::Socks5Config; use crate::sql; use crate::{context::Context, scheduler::connectivity::ConnectivityStore}; diff --git a/src/socks.rs b/src/socks.rs new file mode 100644 index 000000000..813d5933d --- /dev/null +++ b/src/socks.rs @@ -0,0 +1,86 @@ +//! # SOCKS5 support. + +use std::fmt; +use std::time::Duration; + +use anyhow::Result; +pub use async_smtp::ServerAddress; +use tokio::{io, net::TcpStream}; + +use crate::context::Context; +use fast_socks5::client::Socks5Stream; + +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub struct Socks5Config { + pub host: String, + pub port: u16, + pub user_password: Option<(String, String)>, +} + +impl Socks5Config { + /// Reads SOCKS5 configuration from the database. + pub async fn from_database(context: &Context) -> Result> { + let sql = &context.sql; + + let enabled = sql.get_raw_config_bool("socks5_enabled").await?; + if enabled { + let host = sql.get_raw_config("socks5_host").await?.unwrap_or_default(); + let port: u16 = sql + .get_raw_config_int("socks5_port") + .await? + .unwrap_or_default() as u16; + let user = sql.get_raw_config("socks5_user").await?.unwrap_or_default(); + let password = sql + .get_raw_config("socks5_password") + .await? + .unwrap_or_default(); + + let socks5_config = Self { + host, + port, + user_password: if !user.is_empty() { + Some((user, password)) + } else { + None + }, + }; + Ok(Some(socks5_config)) + } else { + Ok(None) + } + } + + pub async fn connect( + &self, + target_addr: &ServerAddress, + timeout: Option, + ) -> io::Result> { + self.to_async_smtp_socks5_config() + .connect(target_addr, timeout) + .await + } + + pub fn to_async_smtp_socks5_config(&self) -> async_smtp::smtp::Socks5Config { + async_smtp::smtp::Socks5Config { + host: self.host.clone(), + port: self.port, + user_password: self.user_password.clone(), + } + } +} + +impl fmt::Display for Socks5Config { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "host:{},port:{},user_password:{}", + self.host, + self.port, + if let Some(user_password) = self.user_password.clone() { + format!("user: {}, password: ***", user_password.0) + } else { + "user: None".to_string() + } + ) + } +}