Skip to content

Block disposable email domains at registration#122

Merged
pierredup merged 2 commits into
mainfrom
block-disposable-emails
Jun 17, 2026
Merged

Block disposable email domains at registration#122
pierredup merged 2 commits into
mainfrom
block-disposable-emails

Conversation

@pierredup

Copy link
Copy Markdown
Member

Block disposable email domains at registration

Rejects disposable / temporary email domains on the platform's base User
entity at validation time, surfacing a normal form-validation error. The check
is always-on: it is declared on the abstract base's protected email
property, so every concrete subclass inherits it automatically with no
per-extender wiring.

What changed

  • Dependency — added mattketmo/email-checker:^3.0 as the detection engine
    (exact + parent/suffix domain matching out of the box).
  • Constraint#[NotThrowawayEmail] added to User::$email, alongside the
    existing NotBlank / Email asserts.
  • Detection list — the package's built-in list is layered with a
    supplemental, refreshable file via
    AggregatorAdapter([BuiltInAdapter, FileAdapter]). The committed snapshot
    lives at Resources/data/disposable_email_blocklist.conf.
  • Service wiringNotThrowawayEmailValidator is registered as a service so
    our aggregated EmailChecker (built-in + supplemental file) is injected,
    rather than the package default that only sees the built-in list.
  • Refresh commandplatform:disposable-domains:update downloads the
    upstream
    disposable-email-domains
    blocklist and rewrites the data file.

Drive-by fix

  • Removed a stale #[Override] from User::eraseCredentials(). Symfony 7.3
    removed that method from UserInterface, so the attribute was a latent fatal
    that prevented any concrete User from being instantiated — which the new
    validation path requires.

Tests

  • DisposableEmailValidationTest — constraint inheritance (concrete subclass)
    plus matching behavior: built-in domain, supplemental-list domain, subdomain
    (parent matching), and a normal domain (no violation).
  • UpdateDisposableDomainsCommandTest — mocked HTTP client, asserts the data
    file is written and the command returns success.

All new tests pass (6 tests). The 4 pre-existing LemonSqueezyPayloadConverter
snapshot failures are unrelated environment drift (empty-object serialization
whitespace) in a bundle untouched here.


Note on scope

This branch also carries earlier commits not yet in main (Tiptap
TextEditorType form type, the auto-detected 2FA security-config redesign, and
related docs), so the diff is broader than the disposable-email feature alone.

Add an always-on NotThrowawayEmail constraint (via mattketmo/email-checker)
to the base User entity's email property, layering the package's built-in
list with a supplemental, refreshable blocklist file. Includes a console
command to refresh the file from upstream and covering tests.
Copilot AI review requested due to automatic review settings June 16, 2026 18:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds disposable/temporary email domain blocking to the PlatformBundle’s base User model by attaching an email-checker validation constraint to the inherited email property, and wires the EmailChecker service to use both the vendor built-in list and a bundled supplemental blocklist file. It also introduces a console command to refresh that supplemental list, plus tests covering constraint inheritance and matching behavior.

Changes:

  • Add mattketmo/email-checker and apply #[NotThrowawayEmail] to PlatformBundle\Model\User::$email.
  • Register an aggregated EmailChecker + NotThrowawayEmailValidator service, backed by BuiltInAdapter and FileAdapter pointing to Resources/data/disposable_email_blocklist.conf.
  • Add platform:disposable-domains:update plus PHPUnit tests for validation behavior and list refresh.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
composer.json Adds mattketmo/email-checker dependency.
src/Bundle/Platform/Model/User.php Adds NotThrowawayEmail constraint to the base email property; removes stale #[Override] on eraseCredentials().
src/Bundle/Platform/Resources/config/services.php Wires EmailChecker with an aggregated adapter and registers the vendor validator as a service; configures the update command output path.
src/Bundle/Platform/Command/UpdateDisposableDomainsCommand.php Adds a command to download and rewrite the supplemental disposable-domain blocklist file.
src/Bundle/Platform/Resources/data/disposable_email_blocklist.conf Adds the supplemental disposable-domain snapshot used by the FileAdapter.
tests/Bundle/PlatformBundle/Validator/Fixtures/UserFixture.php Adds a concrete User subclass fixture to assert inherited constraints.
tests/Bundle/PlatformBundle/Validator/DisposableEmailValidationTest.php Adds tests for inheritance and matching (built-in, custom list, parent/subdomain).
tests/Bundle/PlatformBundle/Command/UpdateDisposableDomainsCommandTest.php Adds a test for the refresh command using a mocked HTTP client.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

)]
final class UpdateDisposableDomainsCommand extends Command
{
private const string SOURCE_URL = 'https://raw.githubusercontent.com/disposable-email-domains/disposable-email-domains/master/disposable_email_blocklist.conf';
Comment on lines +97 to +100
public function getInstance(Constraint $constraint): ConstraintValidatorInterface
{
return $this->notThrowawayEmailValidator;
}
@pierredup pierredup merged commit fb05b2a into main Jun 17, 2026
3 of 7 checks passed
@pierredup pierredup deleted the block-disposable-emails branch June 17, 2026 19:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants