use crate::config::TlsVerify;
use crate::transport::SmtpTransport;
use std::collections::VecDeque;
#[derive(Debug)]
pub struct MockTransport {
responses: VecDeque<Vec<u8>>,
current: Vec<u8>,
pos: usize,
pub written: Vec<String>,
pub tls_upgraded: bool,
pub tls_verify_used: Option<TlsVerify>,
pub fail_on_read: bool,
}
impl MockTransport {
pub fn new(responses: Vec<&str>) -> Self {
Self {
responses: responses
.into_iter()
.map(|s| s.as_bytes().to_vec())
.collect(),
current: Vec::new(),
pos: 0,
written: Vec::new(),
tls_upgraded: false,
tls_verify_used: None,
fail_on_read: false,
}
}
pub fn commands(&self) -> Vec<&str> {
self.written.iter().map(|s| s.as_str()).collect()
}
}
impl SmtpTransport for MockTransport {
type Error = std::io::Error;
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
if self.fail_on_read {
return Err(std::io::Error::new(
std::io::ErrorKind::ConnectionReset,
"mock connection reset",
));
}
if self.pos >= self.current.len() {
if let Some(next) = self.responses.pop_front() {
self.current = next;
self.pos = 0;
} else {
return Ok(0); }
}
let remaining = &self.current[self.pos..];
let n = buf.len().min(remaining.len());
buf[..n].copy_from_slice(&remaining[..n]);
self.pos += n;
Ok(n)
}
fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
if let Ok(s) = std::str::from_utf8(data) {
self.written.push(s.to_string());
}
Ok(())
}
fn upgrade_tls(&mut self, _host: &str, tls_verify: &TlsVerify) -> Result<(), Self::Error> {
self.tls_upgraded = true;
self.tls_verify_used = Some(tls_verify.clone());
Ok(())
}
}