use crate::prelude::{Host, Mailbox}; use std::{fmt, str::FromStr}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; mod error; pub use error::Error; #[derive(Clone, Debug, PartialEq)] pub struct Recipients { pub boxes: Vec, } impl fmt::Display for Recipients { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, ":")?; self.boxes.iter().try_for_each(|b| write!(f, " {b}")) } } #[derive(Clone, Debug, PartialEq)] pub enum Lines { Sender(Mailbox), Recipients(Recipients), Timestamp(String), Text(String), Heading1(String), Heading2(String), Heading3(String), Quote(String), Preformatted(String), } impl fmt::Display for Lines { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Sender(m) => writeln!(f, "< {m}"), Self::Recipients(r) => writeln!(f, "{r}"), Self::Timestamp(t) => writeln!(f, "@ {t}"), Self::Text(t) => writeln!(f, "{t}"), Self::Heading1(h) => writeln!(f, "# {h}"), Self::Heading2(h) => writeln!(f, "## {h}"), Self::Heading3(h) => writeln!(f, "### {h}"), Self::Quote(q) => { for l in q.lines() { writeln!(f, "> {l}")?; } Ok(()) } Self::Preformatted(p) => writeln!(f, "```\n{p}\n```"), } } } #[derive(Debug, Clone, PartialEq)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] pub struct Message { pub id: String, pub senders: Vec, pub recipients: Vec, pub timstamp: Option, pub title: Option, pub body: String, } impl fmt::Display for Message { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if !self.senders.is_empty() { write!(f, "< ")?; self.senders.iter().try_for_each(|s| write!(f, "{s}\n"))?; } if !self.recipients.is_empty() { write!(f, ": ")?; self.recipients.iter().try_for_each(|r| write!(f, " {r}"))?; write!(f, "\n")?; } write!(f, "{}\r\n", self.body) } }