Skip to main content

apollo_redaction/strategy/
email.rs

1use crate::RedactionStrategy;
2use std::fmt;
3
4/// Redact email addresses.
5///
6/// ```rust
7/// use apollo_redaction::Redacted;
8/// use apollo_redaction::strategy::EmailRedactor;
9///
10/// fn email(input: &str) -> String {
11///     Redacted::<_, EmailRedactor>::new(input).to_string()
12/// }
13///
14/// assert_eq!(email("user@example.com"), "u***r@example.com");
15/// assert_eq!(email("ab@example.com"), "***@example.com");
16/// ```
17#[derive(Default, Clone)]
18pub struct EmailRedactor;
19
20impl<T: AsRef<str>> RedactionStrategy<T> for EmailRedactor {
21    fn display(&self, value: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22        redact_email(value.as_ref(), f)
23    }
24}
25
26fn redact_email(email: &str, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27    // For emails: show first/last char of local part, full domain
28    if let Some((local, domain)) = email.split_once('@') {
29        let mut chars = local.chars();
30        let first = chars.next();
31        let last = chars.next_back();
32        // Just to check that there are actually more than 2 characters
33        let more = chars.next();
34        if let (Some(first), Some(last), Some(_)) = (first, last, more) {
35            write!(f, "{first}***{last}@{domain}")
36        } else {
37            write!(f, "***@{domain}")
38        }
39    } else {
40        // Fallback for malformed input
41        write!(f, "[REDACTED: invalid email]")
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use crate::Redacted;
48    use crate::strategy::EmailRedactor;
49
50    fn email(input: &str) -> String {
51        Redacted::<_, EmailRedactor>::new(input).to_string()
52    }
53
54    #[test]
55    fn special_inputs() {
56        assert_eq!(email("not an email"), "[REDACTED: invalid email]");
57        assert_eq!(email("@nolocal.com"), "***@nolocal.com");
58        assert_eq!(email("nodomain@"), "n***n@");
59        assert_eq!(email("a@onechar.com"), "***@onechar.com");
60        assert_eq!(email("ab@twochar.com"), "***@twochar.com");
61        assert_eq!(email("abc@threechar.com"), "a***c@threechar.com");
62        assert_eq!(email("안녕하세요@unicode.com"), "안***요@unicode.com");
63        assert_eq!(email("안녕@unicode.com"), "***@unicode.com");
64    }
65}