1#![warn(missing_docs)]
25
26use avila_error::{Error, ErrorKind, Result};
27
28pub mod smtp;
29pub mod pop3;
30pub mod imap;
31pub mod message;
32pub mod mime;
33pub mod encoding;
34pub mod auth;
35pub mod queue;
36pub mod template;
37pub mod dkim;
38pub mod pool;
39pub mod classifier;
40pub mod calendar;
41
42pub const VERSION: &str = env!("CARGO_PKG_VERSION");
44
45#[derive(Debug, Clone, PartialEq, Eq, Hash)]
47pub struct EmailAddress {
48 pub local: String,
50 pub domain: String,
52 pub display_name: Option<String>,
54}
55
56impl EmailAddress {
57 pub fn new(email: impl AsRef<str>) -> Result<Self> {
59 let email = email.as_ref();
60 let parts: Vec<&str> = email.split('@').collect();
61
62 if parts.len() != 2 {
63 return Err(Error::new(
64 ErrorKind::InvalidInput,
65 format!("Email inválido: {}", email),
66 ));
67 }
68
69 Ok(Self {
70 local: parts[0].to_string(),
71 domain: parts[1].to_string(),
72 display_name: None,
73 })
74 }
75
76 pub fn to_string(&self) -> String {
78 format!("{}@{}", self.local, self.domain)
79 }
80
81 pub fn is_valid(&self) -> bool {
83 !self.local.is_empty() && !self.domain.is_empty() && self.domain.contains('.')
84 }
85
86 pub fn with_name(mut self, name: impl Into<String>) -> Self {
88 self.display_name = Some(name.into());
89 self
90 }
91
92 pub fn to_rfc5322(&self) -> String {
94 match &self.display_name {
95 Some(name) => format!("\"{}\" <{}@{}>", name, self.local, self.domain),
96 None => format!("{}@{}", self.local, self.domain),
97 }
98 }
99}
100
101impl std::fmt::Display for EmailAddress {
102 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103 write!(f, "{}@{}", self.local, self.domain)
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn test_email_address() {
113 let email = EmailAddress::new("test@example.com").unwrap();
114 assert_eq!(email.local, "test");
115 assert_eq!(email.domain, "example.com");
116 assert!(email.is_valid());
117 }
118
119 #[test]
120 fn test_invalid_email() {
121 assert!(EmailAddress::new("invalid").is_err());
122 assert!(EmailAddress::new("no@domain").is_ok()); }
124}