'auto-replied'], 'auto_submitted'], [['auto_submitted' => 'Auto-Generated; owner-email="support@example.com"'], 'auto_submitted'], [['headers' => ['AUTO-SUBMITTED' => ['no', 'auto-replied']]], 'auto_submitted'], [['return_path' => '<>'], 'null_return_path'], [['content_type' => 'multipart/report; report-type=delivery-status; boundary=abc'], 'delivery_report'], [['content_type' => 'message/disposition-notification'], 'delivery_report'], [['precedence' => 'bulk'], 'bulk_mail'], [['precedence' => 'LIST'], 'bulk_mail'], [['list_id' => 'Announcements '], 'mailing_list'], [['x_auto_response_suppress' => 'All'], 'response_suppressed'], [['x_auto_response_suppress' => 'DR, OOF, AutoReply'], 'response_suppressed'], [['x_autoreply' => 'yes'], 'legacy_autoresponder'], [['x_autorespond' => 'true'], 'legacy_autoresponder'], ]; $messageCount = (int) $connection->fetchOne('SELECT COUNT(*) FROM test_messages'); $notifications = $trackingService->notifications; foreach ($cases as $index => [$fields, $reason]) { $input = array_merge([ 'mailbox' => 'support@dev.sebs.space', 'message_id' => '', // Would normally reject this mismatched reply and send a notification. 'subject' => 'Re: [Ticket #41] Test', 'sender_email' => 'wrong@example.com', 'content' => 'Away from the office', ], $fields); $result = $tracker->process($input, $trackingService); if ($result !== ['action' => 'ignored', 'reason' => $reason, 'duplicate' => false]) { throw new RuntimeException('Automatic message was not ignored: ' . $index); } $repeat = $tracker->process($input, $trackingService); if (!$repeat['duplicate'] || $repeat['action'] !== 'ignored') { throw new RuntimeException('Ignored message retry was not deduplicated'); } $row = $connection->fetchAssociative('SELECT ticket_id FROM mailgateway_message WHERE message_id = ?', [$input['message_id']]); if (!$row || $row['ticket_id'] !== null) { throw new RuntimeException('Ignored mail acquired a ticket association'); } // The underlying service methods must also skip without database or mail access. $guardedService = new \Box\Mod\Mailgateway\Service(); foreach (['import', 'reply'] as $method) { if ($guardedService->$method($fields) !== ['action' => 'ignored', 'reason' => $reason]) { throw new RuntimeException('Service method responded to automatic mail'); } } } $minimal = $tracker->process([ 'mailbox' => 'support@dev.sebs.space', 'message_id' => '', 'auto_submitted' => 'auto-replied', ], $trackingService); if ($minimal['action'] !== 'ignored' || (int) $connection->fetchOne('SELECT COUNT(*) FROM test_messages') !== $messageCount || $trackingService->notifications !== $notifications) { throw new RuntimeException('Automatic mail created a message or sent a notification'); } foreach ([[], ['auto_submitted' => 'NO'], ['auto_submitted' => 'no; extension=value'], ['return_path' => ''], ['content_type' => 'text/plain; charset=utf-8'], ['x_auto_response_suppress' => 'None'], ['x_autoreply' => 'false']] as $fields) { if ($policy->ignoreReason($policy->headers($fields)) !== null) { throw new RuntimeException('Normal message classified as automatic'); } } $folded = $policy->headers(['headers' => ['Auto-Submitted' => "auto-replied;\r\n owner=test"]]); if ($policy->ignoreReason($folded) !== 'auto_submitted') { throw new RuntimeException('Folded header failed'); } try { $policy->headers(['auto_submitted' => "no\r\nInjected: value"]); throw new RuntimeException('Header injection accepted'); } catch (\FOSSBilling\InformationException) {} try { $tracker->process(array_merge($input, ['auto_submitted' => 'no']), $trackingService); throw new RuntimeException('Changed detection headers bypassed deduplication'); } catch (\FOSSBilling\InformationException) {} echo "Passed automatic-message filtering, repeated/mixed/folded headers, ignored-message deduplication, no ticket writes or notifications, service method protection, and normal-mail exceptions.\n";