spatie/email-concealer
Replaces email domains in any string (e.g., dumps) to safely use production data locally without real addresses. Create a Concealer and call conceal(): info@spatie.be becomes info@example.com. Simple, fast, and handy for anonymizing text.
Installation:
composer require spatie/email-concealer
No additional configuration is required—just require the package in your project.
First Use Case: Replace visible emails in strings (e.g., logs, dumps, or public-facing content) with masked versions:
use Spatie\EmailConcealer\Concealer;
$concealer = Concealer::create();
$maskedEmail = $concealer->conceal('contact@example.com');
// Returns: "contact@example.com" (default mask) or custom placeholder if configured.
Where to Look First:
Concealer class: Core functionality for masking emails.Concealer::create(): Static factory method to instantiate the concealer.conceal() method: Primary method to process strings.Basic Masking:
Replace all emails in a string with a default placeholder (e.g., example.com):
$concealer = Concealer::create();
$text = "Emails: user@domain.com, admin@test.org";
echo $concealer->conceal($text);
// Output: "Emails: user@example.com, admin@example.com"
Custom Placeholders: Override the default domain (e.g., for testing):
$concealer = Concealer::create('masked.test');
$concealer->conceal('user@domain.com');
// Output: "user@masked.test"
Integration with Laravel:
// app/Helpers/EmailHelper.php
if (!function_exists('concealEmail')) {
function concealEmail($email) {
return Concealer::create()->conceal($email);
}
}
{{ concealEmail('user@domain.com') }}
retrieved events for sensitive data:
use Spatie\EmailConcealer\Concealer;
class UserObserver {
public function retrieved($user) {
$user->email = Concealer::create()->conceal($user->email);
}
}
Batch Processing: Mask emails in arrays or collections:
$emails = ['a@test.com', 'b@work.org'];
$masked = array_map([Concealer::create(), 'conceal'], $emails);
// ['a@example.com', 'b@example.com']
Regex Patterns: Extend the default regex to handle edge cases (e.g., subdomains):
$concealer = Concealer::create();
$concealer->setRegex('/[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}/i');
Regex Limitations:
user+tag@sub.domain.co.uk).Case Sensitivity:
User@DOMAIN.COM) might behave unexpectedly.strtolower() on input strings if consistency is critical.Performance:
Concealer instance or use Laravel’s Str::of() for chained operations:
Str::of($largeText)->replaceMatches('/\b[\w.%+-]+@[\w.-]+\.\w+\b/i', function ($match) {
return Concealer::create()->conceal($match);
});
False Positives:
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
return Concealer::create()->conceal($email);
}
\Log::debug('Masked:', ['email' => $concealer->conceal($email)]);
用户@例子.测试)."user name"@domain.com).Custom Concealer Classes:
Extend the Concealer class to add logic (e.g., logging masked emails):
class CustomConcealer extends \Spatie\EmailConcealer\Concealer {
public function conceal($string) {
$masked = parent::conceal($string);
\Log::info("Email masked: $string => $masked");
return $masked;
}
}
Service Provider Binding: Bind the concealer to Laravel’s container for dependency injection:
// app/Providers/AppServiceProvider.php
public function register() {
$this->app->singleton(Concealer::class, function () {
return Concealer::create('app.test');
});
}
Then inject it into controllers/services:
use Spatie\EmailConcealer\Concealer;
class UserController {
public function __construct(private Concealer $concealer) {}
}
Environment-Specific Config: Use Laravel’s config to switch masking behavior:
// config/email-concealer.php
return [
'placeholder' => env('EMAIL_MASK_PLACEHOLDER', 'example.com'),
'enabled' => env('EMAIL_MASK_ENABLED', true),
];
Then conditionally apply masking:
if (config('email-concealer.enabled')) {
$concealer = Concealer::create(config('email-concealer.placeholder'));
}
laravel-debugbar: Add a tab to visualize masked emails in development.egulias/email-validator.How can I help you explore Laravel packages today?