#[derive(Debug, Clone)]
pub struct SmtpResponse {
pub code: u16,
pub message: String,
}
impl std::fmt::Display for SmtpResponse {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} {}", self.code, self.message)
}
}
impl SmtpResponse {
#[must_use]
pub fn parse(data: &[u8]) -> Option<Self> {
let text = std::str::from_utf8(data).ok()?;
let mut code: Option<u16> = None;
let mut messages = Vec::new();
let mut found_final = false;
for line in text.lines() {
if line.len() < 3 {
continue;
}
let line_code = line[..3].parse::<u16>().ok()?;
if code.is_none() {
code = Some(line_code);
} else if code != Some(line_code) {
return None; }
if line.len() >= 4 {
let separator = line.as_bytes()[3];
let msg = if line.len() > 4 { &line[4..] } else { "" };
messages.push(msg.to_string());
if separator == b' ' {
found_final = true;
break;
}
} else {
found_final = true;
break;
}
}
if found_final {
Some(Self {
code: code?,
message: messages.join("\n"),
})
} else {
None
}
}
#[must_use]
pub const fn is_success(&self) -> bool {
self.code >= 200 && self.code < 300
}
#[must_use]
pub const fn is_intermediate(&self) -> bool {
self.code >= 300 && self.code < 400
}
}