dator/mail.rs
1// Validate the local part of the email (the part before the '@').
2fn email_local(s: &str) -> bool {
3 let s = s.as_bytes();
4
5 if s.len() == 0 || s.len() > 64 {
6 return false;
7 }
8
9 let mut last: u8 = 46;
10
11 for c in s.iter() {
12 match c {
13 // Special chars
14 b'#' | b'$' | b'%' | b'&' | b'\'' | b'*' | b'+' | b'-' | b'/' | b'=' | b'?' => {
15 last = *c;
16 }
17 b'^' | b'_' | b'`' | b'{' | b'|' | b'}' | b'~' => {
18 last = *c;
19 }
20 b'0'..=b'9' => {
21 last = *c;
22 }
23 b'A'..=b'Z' => {
24 last = *c;
25 }
26 b'a'..=b'z' => {
27 last = *c;
28 }
29 b'.' => {
30 // local part cant start with dot,
31 // or contains two in a row.
32 if last == b'.' {
33 return false;
34 }
35 last = *c;
36 }
37 // Any invalid character
38 _ => {
39 return false;
40 }
41 }
42 }
43
44 // Last character cant be dot.
45 last != b'.'
46}
47
48/// Checks whether the given string is a valid email.
49///
50/// This function not allows IP addresses in the domain part (eg.: `bob@[127.0.0.1]`).
51///
52/// # Example
53///
54/// ```
55/// if dator::email("bob@example.com") {
56/// // bob@example.com is a valid email address
57/// }
58/// ```
59/// ```
60/// if !dator::email("bob@[0.0.0.0]") {
61/// // bob@[0.0.0.0] is a valid email address
62/// }
63/// ```
64pub fn email(s: &str) -> bool {
65 let parts: Vec<&str> = s.split('@').collect();
66
67 if parts.len() != 2 {
68 return false;
69 }
70
71 // Check local part
72 match parts.get(0) {
73 Some(part) => {
74 if !email_local(part) {
75 return false;
76 }
77 }
78 None => {
79 return false;
80 }
81 }
82
83 // Check domain part
84 match parts.get(1) {
85 Some(part) => {
86 if !crate::domain(part) {
87 return false;
88 }
89 }
90 None => {
91 return false;
92 }
93 }
94
95 true
96}