fix(classifier): iterate all email candidates per field; document method contract
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -216,6 +216,17 @@ final class Classifier
|
|||||||
return $hits;
|
return $hits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether any field value contains a syntactically valid email address.
|
||||||
|
*
|
||||||
|
* Used by drop-logic to spare submissions that include any plausible contact email
|
||||||
|
* (any TLD, including gmail.com and custom domains — not limited to RU domains).
|
||||||
|
*
|
||||||
|
* Handles flat string values and one level of array nesting (matches CF7 posted_data
|
||||||
|
* shape). Deeper nesting is intentionally NOT supported.
|
||||||
|
*
|
||||||
|
* @param array<string,string|string[]> $fields CF7 posted_data
|
||||||
|
*/
|
||||||
public static function has_valid_email_anywhere(array $fields): bool
|
public static function has_valid_email_anywhere(array $fields): bool
|
||||||
{
|
{
|
||||||
foreach ($fields as $v) {
|
foreach ($fields as $v) {
|
||||||
@@ -223,8 +234,10 @@ final class Classifier
|
|||||||
foreach ($values as $val) {
|
foreach ($values as $val) {
|
||||||
$val = trim((string)$val);
|
$val = trim((string)$val);
|
||||||
if ($val === '') continue;
|
if ($val === '') continue;
|
||||||
if (preg_match('/[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}/', $val, $m)) {
|
if (preg_match_all('/[A-Za-z0-9._%+\-]+@[A-Za-z0-9.\-]+\.[A-Za-z]{2,}/', $val, $matches)) {
|
||||||
if (is_email($m[0])) return true;
|
foreach ($matches[0] as $candidate) {
|
||||||
|
if (is_email($candidate)) return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,4 +29,18 @@ final class ClassifierDropTest extends Cf7stgTestCase
|
|||||||
{
|
{
|
||||||
self::assertFalse(Classifier::has_valid_email_anywhere([]));
|
self::assertFalse(Classifier::has_valid_email_anywhere([]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_has_valid_email_anywhere_finds_email_embedded_in_text(): void
|
||||||
|
{
|
||||||
|
$fields = ['your-message' => 'reach me at user@domain.com thanks'];
|
||||||
|
self::assertTrue(Classifier::has_valid_email_anywhere($fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_has_valid_email_anywhere_finds_second_email_when_first_invalid(): void
|
||||||
|
{
|
||||||
|
// First candidate is "alice@in" which is not a valid email; second is valid.
|
||||||
|
// Without preg_match_all, the method would return false here.
|
||||||
|
$fields = ['msg' => 'try alice@in or bob@example.com'];
|
||||||
|
self::assertTrue(Classifier::has_valid_email_anywhere($fields));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user