(val: T)
| 20 | /// that are unfamiliar to most users. |
| 21 | #[must_use] |
| 22 | pub fn validate_email<T>(val: T) -> bool |
| 23 | where |
| 24 | T: AsRef<str>, |
| 25 | { |
| 26 | let val = val.as_ref(); |
| 27 | if val.is_empty() || !val.contains('@') { |
| 28 | return false; |
| 29 | } |
| 30 | let parts: Vec<&str> = val.rsplitn(2, '@').collect(); |
| 31 | let user_part = parts[1]; |
| 32 | let domain_part = parts[0]; |
| 33 | |
| 34 | // validate the length of each part of the email, BEFORE doing the regex |
| 35 | // according to RFC5321 the max length of the local part is 64 characters |
| 36 | // and the max length of the domain part is 255 characters |
| 37 | // https://datatracker.ietf.org/doc/html/rfc5321#section-4.5.3.1.1 |
| 38 | if user_part.len() > 64 || domain_part.len() > 255 { |
| 39 | return false; |
| 40 | } |
| 41 | |
| 42 | if !EMAIL_USER_RE.is_match(user_part) { |
| 43 | return false; |
| 44 | } |
| 45 | |
| 46 | if !validate_domain_part(domain_part) { |
| 47 | // Still the possibility of an [IDN](https://en.wikipedia.org/wiki/Internationalized_domain_name) |
| 48 | return match domain_to_ascii(domain_part) { |
| 49 | Ok(d) => validate_domain_part(&d), |
| 50 | Err(_) => false, |
| 51 | }; |
| 52 | } |
| 53 | |
| 54 | true |
| 55 | } |
| 56 | |
| 57 | /// Checks if the domain is a valid domain and if not, check whether it's an IP |
| 58 | #[must_use] |
nothing calls this directly
no test coverage detected