Asked  7 Months ago    Answers:  5   Viewed   27 times

I am building a simple friend/buddy system, and when someone tries to search for new friends, I want to show partially hidden email addresses, so as to give an idea about who the user might be, without revealing the actual details.

So I want to become abcdl******

As a test I wrote:

$email = "";

$em = explode("@",$email);
$name = $em[0];
$len = strlen($name);
$showLen = floor($len/2);
$str_arr = str_split($name);
    $str_arr[$ii] = '*';
$em[0] = implode('',$str_arr); 
$new_name = implode('@',$em);
echo $new_name;

This works, but I was wondering if there was any easier/shorter way of applying the same logic? Like a regex maybe?



here's something quick:

function obfuscate_email($email)
    $em   = explode("@",$email);
    $name = implode('@', array_slice($em, 0, count($em)-1));
    $len  = floor(strlen($name)/2);

    return substr($name,0, $len) . str_repeat('*', $len) . "@" . end($em);   

// to see in action:
$emails = ['"Abc@def"', ''];

foreach ($emails as $email) 
    echo obfuscate_email($email) . "n";



uses substr() and str_repeat()

Wednesday, March 31, 2021
answered 7 Months ago

You should point to your vendor/autoload.php at Settings | PHP | PHPUnit when using PHPUnit via Composer.

This blog post has all the details (with pictures) to successfully configure IDE for such scenario:

Related usability ticket:

P.S. The WI-18388 ticket is already fixed in v8.0

Wednesday, March 31, 2021
answered 7 Months ago

On Mac OS X environment variables available in Terminal and for the normal applications can be different, check the related question for the solution how to make them similar.

Note that this solution will not work on Mountain Lion (10.8).

Saturday, May 29, 2021
answered 5 Months ago

You can use:

$email = preg_replace('/(?:^|@).K|.[^@]*$(*SKIP)(*F)|.(?=.*?.)/', '*', $email);

RegEx Demo

This will turn into g*****@g*****.com and will become m*******@g*****

and into t*********@g*****.com

Saturday, May 29, 2021
answered 5 Months ago

Since first posting this answer nearly 3 years ago, I am older and wiser so I decided to review my snippet. 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 and 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(
         function ($m) use ($minFill) {
              return $m[1]
                     . str_repeat("*", max($minFill, mb_strlen($m[2], 'UTF-8')))
                     . ($m[3] ?: $m[1]);


''              => 'a****',
''             => 'a****',
''            => 'a****',
''           => 'a****',
''          => 'a****',
''         => 'a****',
''        => 'a*****',
'Ф'              => 'Ф****Ф',
'ФѰ'             => 'Ф****Ѱ',
'ФѰД'            => 'Ф****Д',
'ФѰДӐӘӔӺ'        => 'Ф*****Ӻ',
'"a@tricky@one"' => '"************"',


/            #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.
Sunday, August 15, 2021
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :