validator_rs/
email.rs

1//! Email validation functions
2
3use regex::Regex;
4use std::sync::OnceLock;
5
6static EMAIL_REGEX: OnceLock<Regex> = OnceLock::new();
7
8fn get_email_regex() -> &'static Regex {
9    EMAIL_REGEX.get_or_init(|| {
10        Regex::new(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
11            .expect("Failed to compile email regex")
12    })
13}
14
15/// Validates if a string is a valid email address
16///
17/// # Examples
18///
19/// ```
20/// use validator_rs::email::is_valid_email;
21///
22/// assert!(is_valid_email("user@example.com"));
23/// assert!(is_valid_email("test.email+tag@domain.co.uk"));
24/// assert!(!is_valid_email("invalid.email"));
25/// assert!(!is_valid_email("@example.com"));
26/// ```
27pub fn is_valid_email(email: &str) -> bool {
28    if email.is_empty() || email.len() > 254 {
29        return false;
30    }
31
32    get_email_regex().is_match(email)
33}
34
35/// Validates if a string is a valid email address and checks domain
36pub fn is_valid_email_with_domain(email: &str, allowed_domains: &[&str]) -> bool {
37    if !is_valid_email(email) {
38        return false;
39    }
40
41    if let Some(domain) = email.split('@').nth(1) {
42        allowed_domains.iter().any(|&d| domain == d)
43    } else {
44        false
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use super::*;
51
52    #[test]
53    fn test_valid_emails() {
54        assert!(is_valid_email("user@example.com"));
55        assert!(is_valid_email("test.email@domain.com"));
56        assert!(is_valid_email("user+tag@example.co.uk"));
57        assert!(is_valid_email("a@b.c"));
58    }
59
60    #[test]
61    fn test_invalid_emails() {
62        assert!(!is_valid_email(""));
63        assert!(!is_valid_email("invalid"));
64        assert!(!is_valid_email("@example.com"));
65        assert!(!is_valid_email("user@"));
66        assert!(!is_valid_email("user @example.com"));
67        assert!(!is_valid_email("user@.com"));
68    }
69
70    #[test]
71    fn test_email_with_domain() {
72        assert!(is_valid_email_with_domain(
73            "user@example.com",
74            &["example.com", "test.com"]
75        ));
76        assert!(!is_valid_email_with_domain(
77            "user@other.com",
78            &["example.com", "test.com"]
79        ));
80    }
81}