$value, 'domain' => $domain, ]); $fail('Temporary or disposable email addresses are not allowed.'); return; } // Check 2: Check against our hardcoded blacklist if (in_array($domain, self::BLOCKED_DOMAINS, true)) { Log::warning('Disposable email attempt blocked (hardcoded blacklist)', [ 'email' => $value, 'domain' => $domain, ]); $fail('Temporary or disposable email addresses are not allowed.'); return; } // Check 3: Check for suspicious patterns in domain name foreach (self::SUSPICIOUS_PATTERNS as $pattern) { if (str_contains($domain, $pattern)) { Log::warning('Disposable email attempt blocked (pattern match)', [ 'email' => $value, 'domain' => $domain, 'pattern' => $pattern, ]); $fail('Temporary or disposable email addresses are not allowed.'); return; } } // Check 4: Validate domain has valid DNS records (MX or A record) if (! $this->validateDnsRecords($domain)) { Log::warning('Email domain has no valid DNS records', [ 'email' => $value, 'domain' => $domain, ]); $fail('The email domain does not appear to be valid or reachable.'); return; } // Check 5: Block common free email services with plus addressing abuse // (optional - you may want to comment this out if you want to allow Gmail, etc.) // if ($this->hasSuspiciousPlusAddressing($value)) { // Log::warning('Suspicious plus addressing detected', [ // 'email' => $value, // 'domain' => $domain, // ]); // $fail('This email format is not allowed.'); // return; // } } /** * Validate that the domain has proper DNS records */ protected function validateDnsRecords(string $domain): bool { // Check for MX records (primary email validation) if (@checkdnsrr($domain, 'MX')) { return true; } // Fall back to A record check (some domains use A records for email) if (@checkdnsrr($domain, 'A')) { return true; } return false; } /** * Check for suspicious plus addressing patterns * Some users abuse plus addressing to create multiple accounts * * @phpstan-ignore method.unused */ private function hasSuspiciousPlusAddressing(string $email): bool { $parts = explode('@', $email); $localPart = $parts[0]; // Check if contains + with suspicious patterns if (str_contains($localPart, '+')) { // You can add more sophisticated checks here // For now, just log it but don't block return false; } return false; } }