use std::net::SocketAddr;
use std::sync::Arc;
use serde::{Deserialize, Serialize};
use tokio::{io::BufStream, net::TcpStream, sync::Mutex};
use tokio_native_tls::TlsStream;
use tokio::io::AsyncWriteExt;
use tokio::io::AsyncReadExt;
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub enum SMTPConnectionStatus {
StartTLS,
WaitingCommand,
WaitingData,
Closed,
}
#[derive(Debug, Clone)]
pub struct SMTPConnection<T> {
pub use_tls: bool,
pub tls_buff_socket: Option<Arc<Mutex<BufStream<TlsStream<TcpStream>>>>>,
pub tcp_buff_socket: Option<Arc<Mutex<BufStream<TcpStream>>>>,
pub buffer: Vec<u8>,
pub mail_buffer: Vec<u8>,
pub status: SMTPConnectionStatus,
pub state: Arc<Mutex<T>>,
}
impl<T> SMTPConnection<T> {
pub async fn write_socket(&self, data: &[u8]) -> std::io::Result<()> {
if self.use_tls {
log::trace!("Writing to TLS socket");
if let Some(tls_buff_socket) = &self.tls_buff_socket {
let mut tls_buff_socket = tls_buff_socket.lock().await;
tls_buff_socket.write_all(data).await?;
tls_buff_socket.flush().await?;
}
} else {
log::trace!("Writing to TCP socket");
if let Some(tcp_buff_socket) = &self.tcp_buff_socket {
let mut tcp_buff_socket = tcp_buff_socket.lock().await;
tcp_buff_socket.write_all(data).await?;
tcp_buff_socket.flush().await?;
}
}
Ok(())
}
pub async fn read_socket(&self, data: &mut [u8]) -> std::io::Result<usize> {
if self.use_tls {
if let Some(tls_buff_socket) = &self.tls_buff_socket {
let mut tls_buff_socket = tls_buff_socket.lock().await;
tls_buff_socket.read(data).await
} else {
log::error!("No socket to read from");
Ok(0)
}
} else {
if let Some(tcp_buff_socket) = &self.tcp_buff_socket {
let mut tcp_buff_socket = tcp_buff_socket.lock().await;
tcp_buff_socket.read(data).await
} else {
log::error!("No socket to read from");
Ok(0)
}
}
}
pub async fn get_peer_addr(&self) -> std::io::Result<SocketAddr>
{
if self.use_tls {
if let Some(tls_buff_socket) = &self.tls_buff_socket {
let tls_buff_socket = tls_buff_socket.lock().await;
Ok(tls_buff_socket.get_ref().get_ref().get_ref().get_ref().peer_addr()?)
} else {
log::error!("No socket to read from");
Err(std::io::Error::new(std::io::ErrorKind::Other, "No socket to read from"))
}
} else {
if let Some(tcp_buff_socket) = &self.tcp_buff_socket {
let tcp_buff_socket = tcp_buff_socket.lock().await;
Ok(tcp_buff_socket.get_ref().peer_addr()?)
} else {
log::error!("No socket to read from");
Err(std::io::Error::new(std::io::ErrorKind::Other, "No socket to read from"))
}
}
}
pub async fn get_tls_buffer(&self) -> Option<Arc<Mutex<BufStream<TlsStream<TcpStream>>>>> {
if self.use_tls {
self.tls_buff_socket.clone()
} else {
None
}
}
pub async fn get_tcp_buffer(&self) -> Option<Arc<Mutex<BufStream<TcpStream>>>>
{
if !self.use_tls {
self.tcp_buff_socket.clone()
} else {
None
}
}
pub async fn close(&self) -> std::io::Result<()> {
if self.use_tls {
if let Some(tls_buff_socket) = &self.tls_buff_socket {
let mut tls_buff_socket = tls_buff_socket.lock().await;
tls_buff_socket.shutdown().await?;
}
} else {
if let Some(tcp_buff_socket) = &self.tcp_buff_socket {
let mut tcp_buff_socket = tcp_buff_socket.lock().await;
tcp_buff_socket.shutdown().await?;
}
}
Ok(())
}
}