PHPackages                             emailsherlock/email-guard-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Mail &amp; Notifications](/categories/mail)
4. /
5. emailsherlock/email-guard-bundle

ActiveSymfony-bundle[Mail &amp; Notifications](/categories/mail)

emailsherlock/email-guard-bundle
================================

Symfony integration for Email-Guard: a VerifiedEmail constraint and a verify\_email form option that block disposable and undeliverable addresses at submit time.

v0.3.1(1mo ago)07.1kMITPHPPHP &gt;=8.1CI passing

Since Jun 12Pushed 1mo agoCompare

[ Source](https://github.com/Emailsherlock1/email-guard-bundle)[ Packagist](https://packagist.org/packages/emailsherlock/email-guard-bundle)[ Docs](https://github.com/Emailsherlock1/email-guard-bundle)[ RSS](/packages/emailsherlock-email-guard-bundle/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (17)Versions (8)Used By (0)

email-guard-bundle
==================

[](#email-guard-bundle)

Symfony integration for [Email-Guard](https://github.com/Emailsherlock1/email-guard-spec): blocks junk email addresses at form submit, before they reach your database.

`deleted+user274@deleted.invalid` passes Symfony's `Email` constraint. So does every disposable address. This bundle adds the missing layer on top of [email-guard-core](https://github.com/Emailsherlock1/email-guard-core-php): syntax profile, reserved TLDs, 73k+ disposable domains, all checked locally with zero latency. An [EmailSherlock API key](https://emailsherlock.com/api/docs)adds live MX, SMTP probe, and a fresh disposable list.

Install
-------

[](#install)

```
composer require emailsherlock/email-guard-bundle
```

Symfony Flex registers the bundle; otherwise add `EmailGuardBundle` to `config/bundles.php`.

Configure
---------

[](#configure)

Everything is optional. Without config the guard runs local checks with the spec defaults:

```
# config/packages/email_guard.yaml
email_guard:
    api_key: '%env(default::EMAILGUARD_API_KEY)%'   # optional, null = local only
    fail_open: true
    timeout_ms: 800
    block_on: ['invalid', 'disposable']
    review_on: []
```

**Fail-open is the default on purpose.** If the API is unreachable, local checks keep working and the rest passes. Your signup form never breaks because of our API.

Use
---

[](#use)

As a form option, one line per field:

```
$builder->add('email', EmailType::class, [
    'verify_email' => true,
]);
```

As a constraint, wherever Symfony validation runs (forms, API DTOs, manual `validate()`):

```
use Emailsherlock\EmailGuardBundle\Validator\VerifiedEmail;

#[VerifiedEmail]
private string $email;

#[VerifiedEmail(blockOn: ['invalid', 'disposable', 'role'])]
private string $contactEmail;
```

A denied address produces one violation: *"This email address can't receive mail. Check it for typos."* Override per constraint via `message:`.

Review flows
------------

[](#review-flows)

`review_on` verdicts add no violation; validation is allow-or-deny by design. For a second gate (hold the signup, require confirmation), inject the guard and read the result yourself:

```
use Emailsherlock\EmailGuard\EmailGuard;

public function __construct(private EmailGuard $guard) {}

$result = $this->guard->check($email);
if ($result->needsReview()) { ... }
```

Reacting to decisions
---------------------

[](#reacting-to-decisions)

The bundle dispatches a `GuardDecisionEvent` for every decision (allow, deny, review), so you can react however you like: log to your own channel, write to your own store, push a metric, fire a webhook. Register a listener:

```
use Emailsherlock\EmailGuardBundle\Event\GuardDecisionEvent;

#[AsEventListener]
final class MyGuardListener
{
    public function __invoke(GuardDecisionEvent $event): void
    {
        if ($event->result->isDenied()) {
            // $event->domain  -> the domain part (not personal data)
            // $event->input   -> the raw address (PII: your responsibility)
            // $event->result  -> verdict, action, reasons, degraded, ...
        }
    }
}
```

The bundle ships one default listener that logs denies as `email_guard.denied` (domain only, never the address) via PSR-3, so blocks are visible even without an API key. It is just one subscriber: to silence it, override the `email_guard.event.decision_log_listener` service.

For aggregate analytics across your sites, set an API key instead: the guard then reports decisions to your EmailSherlock account (domain only), no listener needed.

Custom transport
----------------

[](#custom-transport)

Bind your own `TransportInterface` (e.g. `Psr18Transport` around your HTTP client) by decorating the `email_guard.factory` service arguments. The default uses ext-curl.

License
-------

[](#license)

MIT, see [LICENSE](LICENSE).

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance92

Actively maintained with recent releases

Popularity26

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

7

Last Release

39d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/a3a353e879e2fe9677d4575d87d7980fca9f2236be38bfa172d422ef7f12059f?d=identicon)[matthiastosch](/maintainers/matthiastosch)

---

Top Contributors

[![matthiastosch](https://avatars.githubusercontent.com/u/12081225?v=4)](https://github.com/matthiastosch "matthiastosch (7 commits)")

---

Tags

symfonyemailform validationconstraintdisposableemail validationemail-verificationemailsherlock

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/emailsherlock-email-guard-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/emailsherlock-email-guard-bundle/health.svg)](https://phpackages.com/packages/emailsherlock-email-guard-bundle)
```

###  Alternatives

[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.9M401](/packages/easycorp-easyadmin-bundle)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.6M605](/packages/shopware-core)[web-auth/webauthn-framework

FIDO2/Webauthn library for PHP and Symfony Bundle.

515100.5k3](/packages/web-auth-webauthn-framework)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
