Files

83 lines
4.3 KiB
PHP

<?php
declare(strict_types=1);
require __DIR__ . '/tracking.php';
$policy = new \Box\Mod\Mailgateway\InboundPolicy();
$cases = [
[['auto_submitted' => '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 <list.example.com>'], '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' => '<automatic-' . $index . '@example.com>',
// 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' => '<minimal-auto@example.com>',
'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' => '<customer@example.com>'], ['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";