maize-tech/laravel-email-domain-rule
A Laravel validation rule that restricts email addresses by domain, letting you allow or block specific domains and disposable providers. Drop it into form requests or validators to keep signups clean with one simple, configurable rule.
Architecture fit
maize-tech/laravel-email-domain-rule is a single-purpose validation rule that plugs directly into Laravel's Validator contract, so it sits on an existing extension point rather than introducing a new architectural layer. It is a natural fit wherever email capture is an input boundary: registration, invite flows, lead/contact forms, B2B signup gating, and suppression of disposable/consumer domains. Integration is via FormRequest rules arrays and ad-hoc Validator::make() calls, with a publishable config file for domain allow/deny lists — meaning policy lives in configuration, not in application code. Coupling is low: it is a Composer dependency with no service provider surface likely to conflict with host-app bootstrapping. The main architectural judgement call is where domain policy belongs: this package puts it in-process at validation time, which is appropriate for static blocklists but is the wrong layer if the business wants centrally managed, frequently changing domain policy (that argues for a remote service or a cached config source the app refreshes).
Integration feasibility
Low effort. Standard composer require, optional vendor:publish for the config, then one rule class added to existing rule arrays. No database migrations, no queue workers, no new infrastructure. The realistic work is not the wiring but the policy definition: deciding whether the rule is used as an allowlist (corporate-only signup) or a denylist (block disposable providers), and who owns that list afterwards. A single spike in a dev branch should confirm behaviour in well under a day; a full rollout across all email entry points is a small, enumerable change set.
Technical risk
illuminate/support constraints. The release is versioned 3.2.0 (minor, nominally non-breaking), but if the PR narrowed the constraint to ^11.0 only, apps on Laravel 9/10 will be silently pinned to 3.1.x or fail to resolve. This must be verified against composer.json before assuming a safe in-place upgrade.mail.example.com vs example.com), internationalised domains (IDN/punycode), case sensitivity, and plus-addressing are all places where naive domain matching produces false accept/reject decisions that surface as customer support tickets.Key questions
composer.json in 3.2.0 widen the Laravel constraint to include 11.x, or replace 9/10 support? What is the full supported matrix (PHP × Laravel)?Stack fit
Fits any Laravel 9–11 application on PHP 8.1–8.3, assuming the constraint check above passes. It is agnostic to frontend, queue, and database choices, so it drops into monoliths and API-only services alike. Best structural fit is as a policy boundary: rules composed in FormRequest classes so domain policy is declared once per input surface and testable in isolation.
Migration path
composer.json and composer why-not against the host app's pinned Laravel version.email_domain_rule.enabled) so it can be disabled without a deploy.Compatibility
Confirm the rule's exception/message rendering integrates with the app's localisation and API error format — validation messages surface to end users and inconsistent copy is a visible regression. Check interaction with any existing email validation (email:rfc,dns, EmailRule variants) to avoid duplicated or contradictory DNS checks. Verify behaviour under strict mode and with sometimes/nullable rules.
Sequencing Composer bump and lockfile update (isolated PR) → config published, policy defined and reviewed by the business owner of the list → unit tests asserting accept/reject on a fixture set of domains (including subdomain and IDN cases) → staging with a log-only/shadow mode to measure how many real signups would be rejected → enable per-surface in production with dashboards on rejection rate → post-launch review at 2 weeks.
Maintenance Ongoing cost is list stewardship, not code. Assign an owner and a cadence (monthly) for reviewing the denylist/allowlist; without this the rule degrades into a false sense of security. Track the package for upstream releases; a framework-compatibility release like 3.2.0 is a reminder that this dependency is tied to major-version upgrade cycles and should be included in framework upgrade runbooks, not discovered at composer-resolve time.
Support Support burden concentrates at the customer-facing edge: legitimate users blocked by a false positive. Requires a documented manual-override path — an admin bypass, an exception list the support team can edit, or a "contact us" route with SLA. If the rule is used as a corporate allowlist, this is higher stakes than as a disposable-domain denylist. Note also the single-maintainer bus factor: if the package is load-bearing for signup, consider vendoring or forking it, which is cheap for a rule of this size.
Scaling If checks are static list lookups, cost is negligible (in-memory matching) and scales linearly with traffic at effectively zero marginal cost — the list should be loaded once and cached in opcache/config cache. If DNS resolution is involved, scaling behaviour changes materially: network calls per validation, resolver rate limits, and multi-second tails under resolver degradation. In that case, front it with a cache keyed by domain (long TTL for positives, short for negatives), set explicit timeouts, and never perform lookups inside a synchronous path without a fallback.
Failure modes
composer update pulls 3.2.0 into a Laravel 10 app and resolution fails, or worse, an app is stuck on an unpatched 3.1.x.Ramp-up Low engineering ramp-up: a Laravel developer unfamiliar with the package can read the rule class and config in under an hour. The real ramp-up is organisational — support agents need to recognise domain-block rejections and know the override path, and the person owning the domain list needs a documented process. Budget roughly a day of engineering for integration and tests, plus a recurring monthly review obligation.
How can I help you explore Laravel packages today?