Ocultar certos caracteres de e-mail

Sep 05 2020

Ocultar caracteres de e-mail:

  1. Quando o e-mail tem apenas uma letra, apenas cubra essa letra com o *símbolo, por exemplo*@gmail.com

  2. Quando o e-mail tem duas letras, coloque a segunda letra com o símbolo *, por exemplo t*@gmail.com

  3. Quando o e-mail tem três letras, cubra a segunda e a terceira com o símbolo, *por exemplot**gmail.com

  4. Quando o e-mail tiver quatro ou mais letras, mostre as primeiras três letras e adicione 4 estrelas nas extremidades - por exemplo,

    tim****@gmail.com
    tom****@gmail.com
    

Meu código funciona, mas acho que ele codifica demais e pode ser feito de maneira muito mais limpa

public static String hideSomeOfEmailValue(String privateEmail) {
StringBuilder stringBuilder = new StringBuilder(privateEmail);
int atSignIndex = privateEmail.indexOf("@");
String emailName = privateEmail.substring(0, atSignIndex);

if (emailName.length() == 1) {
    return stringBuilder.replace(0, emailName.length(), "*").toString();
}
if (emailName.length() > 1 && emailName.length() < 4) {
    return stringBuilder.replace(1, atSignIndex, StringUtils.repeat("*", emailName.length() - 1)).toString();
} else {
    stringBuilder = new StringBuilder(privateEmail.substring(0, 2));
    String emailProvider = privateEmail.substring(atSignIndex);
    stringBuilder.append("****").append(emailProvider);
    return stringBuilder.toString();
}
  1. localize em qual índice no sinal está localizado
  2. apare tudo até um sinal que nos dá o nome do e-mail apenas para que possamos facilmente.

Respostas

5 MarioIshac Sep 05 2020 at 11:19

Insetos:

  1. privateEmail.substring(0, 2)precisa mudar para privateEmail.substring(0, 3)no else, uma vez que o índice final é exclusivo e queremos incluir 3 caracteres, não 2.

  2. O método assume que privateEmailcontém um "@" e não verifica se atSignIndexresulta em -1, resultando em um StringIndexOutOfBoundsExceptionse não houver "@". Retorno privateEmail(sem esconder aplicada) cedo se você espera que este método ser entregue a qualquer cadeia genérica que poderia ser potencialmente um e-mail, ou throwum IllegalArgumentExceptioncaso privateEmailé sempre esperado para ser um e-mail. Considero este último um design melhor. Observe que ambas as situações também tratam de strings vazias.

Melhorias:

  1. Use varpara inferência de tipo onde o tipo é óbvio do lado direito, como new StringBuilder(...), ou String#substring. Isso é a partir do Java 10.

  2. 1 < emailName.length() é redundante porque o comprimento de 0 e 1 são tratados por casos anteriores.

  3. StringUtils.repeatpode ser substituído por a String#repeatpartir do Java 11. Livre-se da necessidade de dependência externa aqui.

  4. Instanciar um novo StringBuilderno else pode ser substituído pela mutação do atual, ou seja, com os métodos de instância deletee insert.

  5. Mova a stringBuilderdeclaração para baixo, para apenas quando for necessário.

  6. Substitua "*" por uma static finalvariável, de forma que possamos alterá-la para "-" ou "_" no futuro e permanecer consistente em todos os se ifo else. Este, apesar de ser um personagem, terá que ser um Stringpara permanecer compatível com o tipo String#repeate StringBuilder#replace. Código final:

private static final String HIDE_CHAR = "*";

public static String asHiddenEmail(String privateEmail) {
    int atSignIndex = privateEmail.indexOf("@");

    if (atSignIndex == -1) {
        throw new IllegalArgumentException("`privateEmail` must be an email.");
    }

    var stringBuilder = new StringBuilder(privateEmail);
    var emailName = privateEmail.substring(0, atSignIndex);

    if (emailName.length() == 1) {
        return stringBuilder.replace(0, emailName.length(), HIDE_CHAR).toString();
    }
    if (emailName.length() < 4) {
        var hiddenNameEnd = HIDE_CHAR.repeat(emailName.length() - 1);
        return stringBuilder.replace(1, atSignIndex, hiddenNameEnd).toString();
    }
    else {
        stringBuilder.delete(3, atSignIndex);
        stringBuilder.insert(3, HIDE_CHAR.repeat(4));
        return stringBuilder.toString();
    }
}
DorianGray Sep 07 2020 at 18:35

Refatorei um pouco o código, usando uma instrução switch, comentando o código (importante!) E simplificando os casos individuais. Talvez um nome como obfuscateEMailseja mais compreensível.

O caso "Não deveria acontecer" poderia ser substituído lançando uma exceção.

public class EMail {
    public static void main(String[] args) {
        System.out.println(hideSomeOfEmailValue("[email protected]")); //$NON-NLS-1$
        System.out.println(hideSomeOfEmailValue("[email protected]")); //$NON-NLS-1$
        System.out.println(hideSomeOfEmailValue("[email protected]")); //$NON-NLS-1$
        System.out.println(hideSomeOfEmailValue("[email protected]")); //$NON-NLS-1$
        System.out.println(hideSomeOfEmailValue("[email protected]")); //$NON-NLS-1$
        System.out.println(hideSomeOfEmailValue("[email protected]")); //$NON-NLS-1$
    }
    
    /**
     * 
     * @param privateEmail
     * @return
     */
    public static String hideSomeOfEmailValue(String privateEmail) {
        final int atSignIndex = privateEmail.indexOf('@');
        if (atSignIndex <= 0) {
            // Not an E-Mail address.
            // Shouldn't happen. Return the input.
            return privateEmail;
        }
        
        final StringBuilder obfuscatedEmail = new StringBuilder(privateEmail);
        switch (atSignIndex) {
        case 1:
            // When email only has one letter then just cover that letter with the * symbol e.g. *@gmail.com
            obfuscatedEmail.setCharAt(0, '*');
            return obfuscatedEmail.toString();

        case 2:
            // When email has two letters then cover second letter with the * symbol e.g. t*@gmail.com
            obfuscatedEmail.setCharAt(1, '*');
            return obfuscatedEmail.toString();
            
        case 3:
            // When email has three letters then cover second and third with the symbol * e.g. t**gmail.com
            return obfuscatedEmail.replace(1, 3, "**").toString(); //$NON-NLS-1$
            
        default:
            // When email has four or more letters then show first three letters and add 4 stars at the ends - e.g. tim****@gmail.com
            return obfuscatedEmail.replace(3, atSignIndex, "****").toString(); //$NON-NLS-1$
        }
    }
}

A saída do metídeo principal é a seguinte (este deve ser um teste JUnit):

*@gmail.com
a*@gmail.com
a**@gmail.com
abc****@gmail.com
abc****@gmail.com
abc****@gmail.com