$values) { if (!is_string($name)) { throw new InformationException('Header names must be strings'); } $name = strtolower(str_replace('_', '-', $name)); if (!in_array($name, self::FIELDS, true)) { continue; } $values = is_array($values) ? $values : [$values]; if (count($values) > 20) { throw new InformationException('Too many repeated header values'); } foreach ($values as $value) { if (!is_string($value) || strlen($value) > 16384) { throw new InformationException('Header values must be strings of at most 16384 bytes'); } $value = preg_replace('/\r?\n[ \t]+/', ' ', $value); if (preg_match('/[\x00-\x08\x0A-\x1F\x7F]/', $value)) { throw new InformationException('Invalid control character in header value'); } $headers[$name][] = strtolower(trim($value)); } } ksort($headers); return $headers; } public function ignoreReason(array $headers): ?string { foreach ($headers['auto-submitted'] ?? [] as $value) { if (trim(explode(';', $value, 2)[0]) !== 'no') { return 'auto_submitted'; } } foreach ($headers['return-path'] ?? [] as $value) { if (preg_match('/^<\s*>$/D', $value)) { return 'null_return_path'; } } foreach ($headers['content-type'] ?? [] as $value) { if (preg_match('/^multipart\/report\s*(?:;|$)/', $value) || preg_match('/^message\/(?:delivery-status|disposition-notification|global-delivery-status)\s*(?:;|$)/', $value)) { return 'delivery_report'; } } foreach ($headers['precedence'] ?? [] as $value) { if (in_array(trim(explode(';', $value, 2)[0]), ['bulk', 'list', 'junk'], true)) { return 'bulk_mail'; } } foreach ($headers['list-id'] ?? [] as $value) { if ($value !== '') { return 'mailing_list'; } } foreach ($headers['x-auto-response-suppress'] ?? [] as $value) { if (preg_match('/(?:^|[\s,;])(?:all|autoreply|oof|dr|ndr|rn|nrn)(?:$|[\s,;])/', $value)) { return 'response_suppressed'; } } foreach (['x-autoreply', 'x-autorespond'] as $field) { foreach ($headers[$field] ?? [] as $value) { if (!in_array($value, ['', 'no', 'false', '0'], true)) { return 'legacy_autoresponder'; } } } return null; } }