mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
Resolve IP addresses explicitly
This commit is contained in:
17
src/imap.rs
17
src/imap.rs
@@ -308,6 +308,7 @@ impl Imap {
|
||||
if let Some(socks5_config) = &config.socks5_config {
|
||||
if config.lp.security == Socket::Starttls {
|
||||
Client::connect_starttls_socks5(
|
||||
context,
|
||||
imap_server,
|
||||
imap_port,
|
||||
socks5_config.clone(),
|
||||
@@ -315,13 +316,18 @@ impl Imap {
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
Client::connect_insecure_socks5(imap_server, imap_port, socks5_config.clone())
|
||||
.await
|
||||
Client::connect_insecure_socks5(
|
||||
context,
|
||||
imap_server,
|
||||
imap_port,
|
||||
socks5_config.clone(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
} else if config.lp.security == Socket::Starttls {
|
||||
Client::connect_starttls(imap_server, imap_port, config.strict_tls).await
|
||||
Client::connect_starttls(context, imap_server, imap_port, config.strict_tls).await
|
||||
} else {
|
||||
Client::connect_insecure((imap_server, imap_port)).await
|
||||
Client::connect_insecure(context, imap_server, imap_port).await
|
||||
}
|
||||
} else {
|
||||
let config = &self.config;
|
||||
@@ -330,6 +336,7 @@ impl Imap {
|
||||
|
||||
if let Some(socks5_config) = &config.socks5_config {
|
||||
Client::connect_secure_socks5(
|
||||
context,
|
||||
imap_server,
|
||||
imap_port,
|
||||
config.strict_tls,
|
||||
@@ -337,7 +344,7 @@ impl Imap {
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
Client::connect_secure(imap_server, imap_port, config.strict_tls).await
|
||||
Client::connect_secure(context, imap_server, imap_port, config.strict_tls).await
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ use anyhow::{Context as _, Result};
|
||||
use async_imap::Client as ImapClient;
|
||||
use async_imap::Session as ImapSession;
|
||||
use tokio::io::BufWriter;
|
||||
use tokio::net::ToSocketAddrs;
|
||||
|
||||
use super::capabilities::Capabilities;
|
||||
use super::session::Session;
|
||||
use super::session::SessionStream;
|
||||
use crate::context::Context;
|
||||
use crate::login_param::build_tls;
|
||||
use crate::net::connect_tcp;
|
||||
use crate::socks::Socks5Config;
|
||||
@@ -88,8 +88,13 @@ impl Client {
|
||||
Ok(Session::new(session, capabilities))
|
||||
}
|
||||
|
||||
pub async fn connect_secure(hostname: &str, port: u16, strict_tls: bool) -> Result<Self> {
|
||||
let tcp_stream = connect_tcp((hostname, port), IMAP_TIMEOUT).await?;
|
||||
pub async fn connect_secure(
|
||||
context: &Context,
|
||||
hostname: &str,
|
||||
port: u16,
|
||||
strict_tls: bool,
|
||||
) -> Result<Self> {
|
||||
let tcp_stream = connect_tcp(context, hostname, port, IMAP_TIMEOUT).await?;
|
||||
let tls = build_tls(strict_tls);
|
||||
let tls_stream = tls.connect(hostname, tcp_stream).await?;
|
||||
let buffered_stream = BufWriter::new(tls_stream);
|
||||
@@ -104,8 +109,8 @@ impl Client {
|
||||
Ok(Client { inner: client })
|
||||
}
|
||||
|
||||
pub async fn connect_insecure(addr: impl ToSocketAddrs) -> Result<Self> {
|
||||
let tcp_stream = connect_tcp(addr, IMAP_TIMEOUT).await?;
|
||||
pub async fn connect_insecure(context: &Context, hostname: &str, port: u16) -> Result<Self> {
|
||||
let tcp_stream = connect_tcp(context, hostname, port, IMAP_TIMEOUT).await?;
|
||||
let buffered_stream = BufWriter::new(tcp_stream);
|
||||
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
||||
let mut client = ImapClient::new(session_stream);
|
||||
@@ -117,8 +122,13 @@ impl Client {
|
||||
Ok(Client { inner: client })
|
||||
}
|
||||
|
||||
pub async fn connect_starttls(hostname: &str, port: u16, strict_tls: bool) -> Result<Self> {
|
||||
let tcp_stream = connect_tcp((hostname, port), IMAP_TIMEOUT).await?;
|
||||
pub async fn connect_starttls(
|
||||
context: &Context,
|
||||
hostname: &str,
|
||||
port: u16,
|
||||
strict_tls: bool,
|
||||
) -> Result<Self> {
|
||||
let tcp_stream = connect_tcp(context, hostname, port, IMAP_TIMEOUT).await?;
|
||||
|
||||
// Run STARTTLS command and convert the client back into a stream.
|
||||
let mut client = ImapClient::new(tcp_stream);
|
||||
@@ -146,12 +156,15 @@ impl Client {
|
||||
}
|
||||
|
||||
pub async fn connect_secure_socks5(
|
||||
context: &Context,
|
||||
domain: &str,
|
||||
port: u16,
|
||||
strict_tls: bool,
|
||||
socks5_config: Socks5Config,
|
||||
) -> Result<Self> {
|
||||
let socks5_stream = socks5_config.connect(domain, port, IMAP_TIMEOUT).await?;
|
||||
let socks5_stream = socks5_config
|
||||
.connect(context, domain, port, IMAP_TIMEOUT)
|
||||
.await?;
|
||||
let tls = build_tls(strict_tls);
|
||||
let tls_stream = tls.connect(domain, socks5_stream).await?;
|
||||
let buffered_stream = BufWriter::new(tls_stream);
|
||||
@@ -166,11 +179,14 @@ impl Client {
|
||||
}
|
||||
|
||||
pub async fn connect_insecure_socks5(
|
||||
context: &Context,
|
||||
domain: &str,
|
||||
port: u16,
|
||||
socks5_config: Socks5Config,
|
||||
) -> Result<Self> {
|
||||
let socks5_stream = socks5_config.connect(domain, port, IMAP_TIMEOUT).await?;
|
||||
let socks5_stream = socks5_config
|
||||
.connect(context, domain, port, IMAP_TIMEOUT)
|
||||
.await?;
|
||||
let buffered_stream = BufWriter::new(socks5_stream);
|
||||
let session_stream: Box<dyn SessionStream> = Box::new(buffered_stream);
|
||||
let mut client = ImapClient::new(session_stream);
|
||||
@@ -183,12 +199,15 @@ impl Client {
|
||||
}
|
||||
|
||||
pub async fn connect_starttls_socks5(
|
||||
context: &Context,
|
||||
hostname: &str,
|
||||
port: u16,
|
||||
socks5_config: Socks5Config,
|
||||
strict_tls: bool,
|
||||
) -> Result<Self> {
|
||||
let socks5_stream = socks5_config.connect(hostname, port, IMAP_TIMEOUT).await?;
|
||||
let socks5_stream = socks5_config
|
||||
.connect(context, hostname, port, IMAP_TIMEOUT)
|
||||
.await?;
|
||||
|
||||
// Run STARTTLS command and convert the client back into a stream.
|
||||
let mut client = ImapClient::new(socks5_stream);
|
||||
|
||||
42
src/net.rs
42
src/net.rs
@@ -1,25 +1,55 @@
|
||||
///! # Common network utilities.
|
||||
use std::net::SocketAddr;
|
||||
use std::pin::Pin;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as _, Result};
|
||||
use tokio::net::{TcpStream, ToSocketAddrs};
|
||||
use tokio::net::{lookup_host, TcpStream};
|
||||
use tokio::time::timeout;
|
||||
use tokio_io_timeout::TimeoutStream;
|
||||
|
||||
use crate::context::Context;
|
||||
|
||||
async fn connect_tcp_inner(addr: SocketAddr, timeout_val: Duration) -> Result<TcpStream> {
|
||||
let tcp_stream = timeout(timeout_val, TcpStream::connect(addr))
|
||||
.await
|
||||
.context("connection timeout")?
|
||||
.context("connection failure")?;
|
||||
Ok(tcp_stream)
|
||||
}
|
||||
|
||||
/// Returns a TCP connection stream with read/write timeouts set
|
||||
/// and Nagle's algorithm disabled with `TCP_NODELAY`.
|
||||
///
|
||||
/// `TCP_NODELAY` ensures writing to the stream always results in immediate sending of the packet
|
||||
/// to the network, which is important to reduce the latency of interactive protocols such as IMAP.
|
||||
pub(crate) async fn connect_tcp(
|
||||
addr: impl ToSocketAddrs,
|
||||
context: &Context,
|
||||
host: &str,
|
||||
port: u16,
|
||||
timeout_val: Duration,
|
||||
) -> Result<Pin<Box<TimeoutStream<TcpStream>>>> {
|
||||
let tcp_stream = timeout(timeout_val, TcpStream::connect(addr))
|
||||
.await
|
||||
.context("connection timeout")?
|
||||
.context("connection failure")?;
|
||||
let mut tcp_stream = None;
|
||||
for resolved_addr in lookup_host((host, port)).await? {
|
||||
info!(
|
||||
context,
|
||||
"Resolved {}:{} into {}.", host, port, &resolved_addr
|
||||
);
|
||||
match connect_tcp_inner(resolved_addr, timeout_val).await {
|
||||
Ok(stream) => {
|
||||
tcp_stream = Some(stream);
|
||||
break;
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(
|
||||
context,
|
||||
"Failed to connect to {}: {:#}.", resolved_addr, err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
let tcp_stream =
|
||||
tcp_stream.with_context(|| format!("failed to connect to {}:{}", host, port))?;
|
||||
|
||||
// Disable Nagle's algorithm.
|
||||
tcp_stream.set_nodelay(true)?;
|
||||
|
||||
@@ -58,11 +58,12 @@ impl Socks5Config {
|
||||
|
||||
pub async fn connect(
|
||||
&self,
|
||||
context: &Context,
|
||||
target_host: &str,
|
||||
target_port: u16,
|
||||
timeout_val: Duration,
|
||||
) -> Result<Socks5Stream<Pin<Box<TimeoutStream<TcpStream>>>>> {
|
||||
let tcp_stream = connect_tcp((self.host.clone(), self.port), timeout_val).await?;
|
||||
let tcp_stream = connect_tcp(context, &self.host, self.port, timeout_val).await?;
|
||||
|
||||
let authentication_method = if let Some((username, password)) = self.user_password.as_ref()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user