diff --git a/src/lib.rs b/src/lib.rs index e9f7377..381411a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -125,15 +125,15 @@ //! pub mod smtp; +use std::net::IpAddr; use std::{fmt::Display, hash::Hash, time::Duration}; -use tokio::io::{AsyncRead, AsyncWrite}; -use tokio_rustls::TlsConnector; - -#[cfg(feature = "builder")] -pub use mail_builder; #[cfg(feature = "dkim")] pub use mail_auth; +#[cfg(feature = "builder")] +pub use mail_builder; +use tokio::io::{AsyncRead, AsyncWrite}; +use tokio_rustls::TlsConnector; #[derive(Debug)] pub enum Error { @@ -201,10 +201,11 @@ pub struct SmtpClientBuilder + PartialEq + Eq + Hash> { pub tls_hostname: T, pub tls_implicit: bool, pub credentials: Option>, - pub addr: String, + pub addr: Option, pub is_lmtp: bool, pub say_ehlo: bool, pub local_host: String, + pub port: u16, } /// SMTP client builder diff --git a/src/smtp/builder.rs b/src/smtp/builder.rs index 56f1808..3f8f544 100644 --- a/src/smtp/builder.rs +++ b/src/smtp/builder.rs @@ -8,8 +8,10 @@ * except according to those terms. */ +use crate::{Credentials, SmtpClient, SmtpClientBuilder}; use smtp_proto::{EhloResponse, EXT_START_TLS}; use std::hash::Hash; +use std::net::IpAddr; use std::time::Duration; use tokio::{ io::{AsyncRead, AsyncWrite}, @@ -17,14 +19,21 @@ use tokio::{ }; use tokio_rustls::client::TlsStream; -use crate::{Credentials, SmtpClient, SmtpClientBuilder}; - use super::{tls::build_tls_connector, AssertReply}; impl + PartialEq + Eq + Hash> SmtpClientBuilder { pub fn new(hostname: T, port: u16) -> Self { + SmtpClientBuilder::_new(hostname, None, port) + } + + pub fn new_bind_ip(hostname: T, addr: IpAddr, port: u16) -> Self { + SmtpClientBuilder::_new(hostname, Some(addr), port) + } + + fn _new(hostname: T, addr: Option, port: u16) -> Self { SmtpClientBuilder { - addr: format!("{}:{}", hostname.as_ref(), port), + addr, + port, timeout: Duration::from_secs(60 * 60), tls_connector: build_tls_connector(false), tls_hostname: hostname, @@ -85,7 +94,7 @@ impl + PartialEq + Eq + Hash> SmtpClientBuilder { pub async fn connect(&self) -> crate::Result>> { tokio::time::timeout(self.timeout, async { let mut client = SmtpClient { - stream: TcpStream::connect(&self.addr).await?, + stream: self.tcp_connect().await?, timeout: self.timeout, }; @@ -130,14 +139,21 @@ impl + PartialEq + Eq + Hash> SmtpClientBuilder { .map_err(|_| crate::Error::Timeout)? } + pub async fn tcp_connect(&self) -> std::io::Result { + let port = self.port; + if let Some(addr) = self.addr { + TcpStream::connect((addr, port)).await + } else { + TcpStream::connect((self.tls_hostname.as_ref(), port)).await + } + } + /// Connect over clear text (should not be used) pub async fn connect_plain(&self) -> crate::Result> { let mut client = SmtpClient { - stream: tokio::time::timeout(self.timeout, async { - TcpStream::connect(&self.addr).await - }) - .await - .map_err(|_| crate::Error::Timeout)??, + stream: tokio::time::timeout(self.timeout, async { self.tcp_connect().await }) + .await + .map_err(|_| crate::Error::Timeout)??, timeout: self.timeout, };