'Hide email address with stars (*)

I have this mail address [email protected].

How to convert it into this mail address a****[email protected]

I tried using strpos and get @ but I cannot get middle values and change it to ****.

php


Solution 1:[1]

At first, I thought that strpos() on @ would get me the length of the "local" part of the address and I could use substr_replace() to simply inject the asterisks BUT a valid email address can have multiple @ in the local part AND multibyte support is a necessary inclusion for any real-world project. This means that mb_strpos() would be an adequate replacement for strpos(), but there isn't yet a native mb_substr_replace() function in php, so the convolution of devising a non-regex snippet became increasingly unattractive.

If you want to see my original answer, you can check the edit history, but I no longer endorse its use. My original answer also detailed how other answers on this page fail to obfuscate email addresses which have 1 or 2 characters in the local substring. If you are considering using any other answers, but sure to test against [email protected] and [email protected] as preliminary unit tests.

My snippet to follow DOES NOT validate an email address; it is assumed that your project will use appropriate methods to validate the address before bothering to allow it into your system. The power/utility of this snippet is that it is multibyte-safe and it will add asterisks in all scenarios and when there is only a single character in the local part, the leading character is repeated before the @ so that the mutated address is harder to guess. Oh, and the number of asterisks to be added is declared as a variable for simpler maintenance.

Code: (Demo) (Regex Demo)

$minFill = 4;
echo preg_replace_callback(
         '/^(.)(.*?)([^@]?)(?=@[^@]+$)/u',
         function ($m) use ($minFill) {
              return $m[1]
                     . str_repeat("*", max($minFill, mb_strlen($m[2], 'UTF-8')))
                     . ($m[3] ?: $m[1]);
         },
         $email
     );

Input/Output:

'[email protected]'              => 'a****[email protected]',
'[email protected]'             => 'a****[email protected]',
'[email protected]'            => 'a****[email protected]',
'[email protected]'           => 'a****[email protected]',
'[email protected]'          => 'a****[email protected]',
'[email protected]'         => 'a****[email protected]',
'[email protected]'        => 'a*****[email protected]',
'[email protected]'              => '?****[email protected]',
'[email protected]'             => '?****[email protected]',
'[email protected]'            => '?****[email protected]',
'[email protected]'        => '?*****[email protected]',
'"a@tricky@one"@example.com' => '"************"@example.com',

Regex-planation:

/            #pattern delimiter
^            #start of string
(.)          #capture group #1 containing the first character
(.*?)        #capture group #2 containing zero or more characters (lazy, aka non-greedy)
([^@]?)      #capture group #3 containing an optional single non-@ character
(?=@[^@]+$)  #require that the next character is @ then one or more @ until the end of the string
/            #pattern delimiter
u            #unicode/multibyte pattern modifier

Callback explanation:

  • $m[1]
    the first character (capture group #1)
  • str_repeat("*", max($minFill, mb_strlen($m[2], 'UTF-8')))
    measure the multibyte length of capture group #2 using UTF-8 encoding, then use the higher value between that calculated length and the declared $minFill, then repeat the character * the number of times returned from the max() call.
  • ($m[3] ?: $m[1])
    the last character before the @ (capture group #3); if the element is empty in the $m array, then use the first element's value -- it will always be populated.

Solution 2:[2]

Here is the simple version:

$em = '[email protected]'; // 'a****[email protected]'
$em = '[email protected]'; // 'a*******[email protected]'

Using PHP String functions

$stars = 4; // Min Stars to use
$at = strpos($em,'@');
if($at - 2 > $stars) $stars = $at - 2;
print substr($em,0,1) . str_repeat('*',$stars) . substr($em,$at - 1);

Solution 3:[3]

Late answer but you can use:

$email = "[email protected]";
print preg_replace_callback('/(\w)(.*?)(\w)(@.*?)$/s', function ($matches){
    return $matches[1].preg_replace("/\w/", "*", $matches[2]).$matches[3].$matches[4];
}, $email);

# a****[email protected]

Solution 4:[4]

Regex: ^.\K[a-zA-Z\.0-9]+(?=.@) canbe changed to this ^[a-zA-Z]\K[a-zA-Z\.0-9]+(?=[a-zA-Z]@)

1. ^.\K This will match first character of email and \K will reset the match

2. [a-zA-Z\.0-9]+(?=.@) this will match string and positive look ahead for any character then @

In the second statement of code we are creating same no. of *'s as the no. of characters in match.

In the third statement we are using preg_replace to remove matched string with *'s

Try this code snippet here

<?php
$string='[email protected]';
preg_match('/^.\K[a-zA-Z\.0-9]+(?=.@)/',$string,$matches);//here we are gathering this part bced

$replacement= implode("",array_fill(0,strlen($matches[0]),"*"));//creating no. of *'s
echo preg_replace('/^(.)'.preg_quote($matches[0])."/", '$1'.$replacement, $string);

Output: a****[email protected]

Solution 5:[5]

In certain cases, you would like to show partial email to give users hint about their email id. If you are looking for similar, you can take half characters of email username and replace with certain characters. Here is the PHP function that you can use for your project to hide email address.

<?php
function hide_email($email) {
        // extract email text before @ symbol
        $em = explode("@", $email);
        $name = implode(array_slice($em, 0, count($em) - 1), '@');

        // count half characters length to hide
        $length = floor(strlen($name) / 2);

        // Replace half characters with * symbol
        return substr($name, 0, $length) . str_repeat('*', $length) . "@" . end($em);
}

echo hide_email("[email protected]");
?>

// Output: cont****@gmail.com

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dharman
Solution 2 Kae Cyphet
Solution 3 Pedro Lobito
Solution 4 Dharman
Solution 5 Deepak Rajpal