vi90
vi90

Reputation: 73

Masking the centre part of the email ID

I want to mask the email id as follows :

Input                   |   Output
[email protected]        : qw**[email protected]
[email protected]    : he******[email protected]
[email protected] : st*********[email protected]
[email protected]         : ab*[email protected]
[email protected]          : a**[email protected]
[email protected]           : a*[email protected]
[email protected]            : a*@gmail.com
  1. Max 2 characters at both the extremes if available, minimum 1 character at each end are to be displayed or just mask the last character.

  2. The string has to be atleast 2 characters in length ([email protected]).

I referred some of the solutions provided, but was not able to achieve the second and third scenario using those. Is there a possibility to find a fix ? I'm not well versed with regex, so I'm not sure which way to go ahead.

references : masking of email address in java

How to i mask all string characters except for the last 4 characters in Java using parameters?

Upvotes: 0

Views: 2441

Answers (3)

DigitShifter
DigitShifter

Reputation: 854

Alternative regex:

"(?:(\\w{2})(\\w+)(\\w{2}@.*)|(\\w)(\\w{1,2})(\\w@.*)|(\\w)(\\w)(@.*))"

Regex in context:

public static void main(String[] args) {
    String str = "[email protected]\n"
            + "[email protected]\n"
            + "[email protected]\n"
            + "[email protected]\n"
            + "[email protected]\n"
            + "[email protected]\n"
            + "[email protected]";

    // 9 matcher group in total
    Pattern pattern = Pattern.compile("(?:(\\w{2})(\\w+)(\\w{2}@.*)|(\\w)(\\w{1,2})(\\w@.*)|(\\w)(\\w)(@.*))");
    List<Integer> groupIndex = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
    for (String email : str.split("\n")) {
        Matcher matcher = pattern.matcher(email);
        if(matcher.find()) {
            List<Integer> activeGroupIndex = groupIndex.stream()
                    .filter(i -> matcher.group(i) != null)
                    .collect(Collectors.toList());
            String prefix = matcher.group(activeGroupIndex.get(0));
            String middle = matcher.group(activeGroupIndex.get(1));
            String suffix = matcher.group(activeGroupIndex.get(2));
            System.out.printf("%s%s%s%n", prefix, "*".repeat(middle.length()), suffix);
        }
    }
}

Output:

qw**[email protected]
he******[email protected]
st*********[email protected]
ab*[email protected]
a**[email protected]
a*[email protected]
a*@gmail.com

Note: "String repeat​(int count)" only works from Java 11 and up.

Upvotes: 0

DevilsHnd - 退した
DevilsHnd - 退した

Reputation: 9192

Interesting reads regarding what can, and what can not be in an E-Mail Address would be this SO Post and this SO Post especially if you want to utilize Regular Expressions.

Here is another method to accomplish the task at hand:

public static String maskEMailAddress(String emailAddy) {
    String id = emailAddy.substring(0, emailAddy.lastIndexOf("@"));
    String domain = emailAddy.substring(emailAddy.lastIndexOf("@"));
    if (id.length() <= 1) { 
        return emailAddy;
    }
    switch (id.length()) {
        case 2:
            id = id.substring(0,1) + "*";
            break;
        case 3:
            id = id.substring(0,1) + "*" + id.substring(2);
            break;
        case 4:
            id = id.substring(0,1) + "**" + id.substring(3);
            break;
        default:
            String masks = String.join("", java.util.Collections.nCopies(id.length() - 4, "*"));
            id = id.substring(0,2) + masks + id.substring(id.length() - 2);
            break;
    }

    String address = id + domain;
    return address;
}

Upvotes: 2

Michael Easter
Michael Easter

Reputation: 24468

Working code is located here

Consider a method that replaces a regex within an input string (credit to this answer):

String replace(String regex, String replacement, String input) {
    String result = "N/A";

    Matcher m = Pattern.compile(regex).matcher(input);
    if (m.find()) {
        int groupToReplace = 1;
        result = new StringBuilder(input).replace(m.start(groupToReplace),
                                                  m.end(groupToReplace),
                                                  replacement).toString();
    } else {
        throw new IllegalStateException("internal error");
    }

    return result;
}

then the various cases can be isolated into client code. Here, we assume that the "email id" has been stripped from the email address. (e.g. qwerty is input and not [email protected]). Code snippet:

// TODO: the regex strings can be compiled into proper Pattern objects
if (numChars == 2) {
    regex = ".(.)";
    replacement = ASTERISK;
} else if (numChars == 3) {
    regex = ".(.).";
    replacement = ASTERISK;
} else if (numChars == 4) {
    regex = ".(..).";
    replacement = ASTERISK + ASTERISK;
} else {
    regex = "..(.*)..";
    int numAsterisks = numChars - 4;

    // requires JDK 11+
    replacement = ASTERISK.repeat(numAsterisks);
}

String result = replace(regex, replacement, input);

Above, note that String.repeat was introduced in JDK 11.

This is neither efficient nor elegant but is somewhat readable (esp. if unit-tested thoroughly). It has a simplistic treatment of what constitutes an email address.

Another solution, which doesn't use regular expressions, is included here.

Upvotes: 0

Related Questions