1use std::str::from_utf8;
2
3use crate::errors::SMTPError;
4
5use super::headers::EmailHeaders;
6use hashbrown::HashMap;
7
8#[derive(Debug, PartialEq, Eq)]
26pub struct Mail<T> {
27 pub headers: HashMap<EmailHeaders, String>,
35 pub body: T,
39}
40
41impl<T> Mail<T> {
42 pub fn from_bytes(bytes: Vec<u8>) -> Result<Mail<T>, String>
55 where
56 T: From<Vec<u8>>,
57 {
58 let mut headers = HashMap::new();
59 let mut body = Vec::new();
60 let mut lines = bytes.split(|&b| b == b'\n').peekable();
61 let mut header_complete = false;
62
63 while let Some(line) = lines.next() {
64 if line.is_empty() || line == b"\r" {
65 header_complete = true;
66 break;
67 }
68
69 if let Some(&b' ') | Some(&b'\t') = line.first() {
70 if let Some(last_header) = headers.keys().last().cloned() {
71 let value: &mut String = headers.get_mut(&last_header).unwrap();
72 value.push_str(from_utf8(line).map_err(|_| "Invalid header value")?);
73 continue;
74 }
75 }
76
77 let mut parts = line.splitn(2, |&b| b == b':');
78 let key = parts.next().ok_or("Invalid header")?;
79 let value = parts.next().ok_or("Invalid header value not exist")?;
80 let value = from_utf8(value).map_err(|_| "Invalid header value")?.trim();
81 let value = value.split_whitespace().collect::<Vec<&str>>().join(" ");
82
83 headers.insert(EmailHeaders::from_bytes(key)?, value.to_owned());
84 }
85
86 if header_complete {
87 for line in lines {
88 body.extend_from_slice(line);
89 body.push(b'\n');
90 }
91 } else {
92 return Err("Invalid mail format".to_string());
93 }
94
95 Ok(Mail {
96 headers,
97 body: body.into(),
98 })
99 }
100}
101
102pub trait MailTrait: Send + Sync + 'static {
106 fn as_any(&self) -> &dyn std::any::Any;
110}
111
112impl<T: Send + Sync + 'static> MailTrait for Mail<T> {
113 fn as_any(&self) -> &dyn std::any::Any {
114 self
115 }
116}
117
118impl<T: Clone + Send + Sync + 'static> Clone for Mail<T> {
119 fn clone(&self) -> Self {
120 Mail {
121 headers: self.headers.clone(),
122 body: self.body.clone(),
123 }
124 }
125}
126
127#[derive(Debug, Clone, PartialEq, Eq, Hash)]
131pub struct EmailAddress {
132 pub username: String,
140 pub domain: String,
146}
147
148impl EmailAddress {
149 pub fn from_string(data: &str) -> Result<Self, SMTPError> {
153 let mut parts = data.split('@');
154 let username = parts
155 .next()
156 .ok_or(SMTPError::ParseError("Invalid email address".to_string()))?
157 .to_owned();
158 let domain = parts
159 .next()
160 .ok_or(SMTPError::ParseError("Invalid email address".to_string()))?
161 .to_owned();
162
163 if domain.is_empty() {
164 return Err(SMTPError::ParseError("Invalid email address".to_string()));
165 }
166
167 if domain.len() > 253 {
168 return Err(SMTPError::ParseError("Invalid email address".to_string()));
169 }
170
171 Ok(EmailAddress { username, domain })
172 }
173
174 pub fn to_string(&self) -> String {
178 format!("{}@{}", self.username, self.domain)
179 }
180}