1#![feature(let_chains)]
2use xstr::cut255 as cut;
3
4pub fn user_host(mail: impl AsRef<str>) -> (String, String) {
5 let mail = mail.as_ref();
6 let user;
7
8 if let Some(p) = mail.find('@') {
9 user = cut(&mail[..p]).to_owned();
10 if mail.len() > p {
11 return (user, cut(&mail[p + 1..]).into());
12 }
13 } else {
14 user = "".to_owned();
15 }
16
17 (user, cut(mail).into())
18}
19
20pub fn norm_user_host(mail: impl AsRef<str>) -> (String, String) {
21 let mail = xstr::lowtrim(mail);
22 let (user, host) = user_host(mail);
23 let host = host
24 .split('.')
25 .map(|i| {
26 let i = i.trim();
27 if i.starts_with("xn--")
28 && let Ok(i) = punycode::decode(&i[3..])
29 {
30 i
31 } else {
32 i.to_owned()
33 }
34 })
35 .collect::<Vec<_>>()
36 .join(".");
37 (user, host)
38}
39
40pub fn norm(mail: impl AsRef<str>) -> String {
41 let (user, host) = norm_user_host(mail);
42 user + "@" + &host
43}
44
45pub fn norm_tld(mail: impl AsRef<str>) -> (String, String) {
46 let (user, host) = norm_user_host(mail);
47 (user + "@" + &host, xtld::tld(&host).into())
48}