feat: implement exim autoresponder worker

This commit is contained in:
Marek Miklewicz
2026-06-02 20:17:49 +02:00
parent 7493e3f9da
commit d3f2fd69db
5 changed files with 287 additions and 7 deletions
+98
View File
@@ -0,0 +1,98 @@
<?php
declare(strict_types=1);
require_once PLUGIN_ROOT . '/scripts/global_autoresponder_worker.php';
test('exim worker sends active rule for resolved mailbox only', function (): void {
$settingsPath = TEST_TMP . '/worker-settings.conf';
test_write($settingsPath, "GLOBAL_AUTORESPONDER_BACKEND=exim\nGLOBAL_AUTORESPONDER_REPEAT_MINUTES=60\n");
$settings = Settings::load($settingsPath);
$virtualRoot = TEST_TMP . '/worker-virtual';
test_write($virtualRoot . '/domainowners', "example.com: alice\n");
test_write($virtualRoot . '/example.com/passwd', "info:x:1000:12::/home/alice/imap/example.com/info:/bin/false\n");
$repo = new RuleRepository(TEST_TMP . '/worker-data');
$created = $repo->create('alice', [
'subject' => 'Urlop',
'body' => 'Odpowiem później',
'start_ts' => 900,
'end_ts' => 1100,
'enabled' => true,
]);
$sent = [];
$worker = new GlobalAutoresponderWorker(
$settings,
$repo,
new MailboxDirectory($virtualRoot),
new RepeatState(TEST_TMP . '/worker-state', 1000),
static function (string $from, string $to, string $subject, string $body) use (&$sent): bool {
$sent[] = compact('from', 'to', 'subject', 'body');
return true;
},
1000
);
$count = $worker->handle(
['SENDER_ADDRESS' => 'person@example.net', 'LOCAL_PART' => 'info', 'DOMAIN' => 'example.com'],
"Auto-Submitted: no\nSubject: hello\n\nBody"
);
assert_same(1, $count);
assert_same('info@example.com', $sent[0]['from']);
assert_same('person@example.net', $sent[0]['to']);
assert_same('Urlop', $sent[0]['subject']);
assert_same('Odpowiem później', $sent[0]['body']);
$count = $worker->handle(
['SENDER_ADDRESS' => 'person@example.net', 'RECIPIENT' => 'info@example.com'],
"Auto-Submitted: no\nSubject: hello\n\nBody"
);
assert_same(0, $count, 'repeat policy should block immediate second response');
assert_true(isset($created['id']));
});
test('exim worker suppresses automated messages and ignores unresolved recipients', function (): void {
$settingsPath = TEST_TMP . '/worker-suppress-settings.conf';
test_write($settingsPath, "GLOBAL_AUTORESPONDER_BACKEND=exim\nGLOBAL_AUTORESPONDER_REPLY_EVERY_MESSAGE=true\n");
$settings = Settings::load($settingsPath);
$virtualRoot = TEST_TMP . '/worker-suppress-virtual';
test_write($virtualRoot . '/domainowners', "example.com: alice\n");
test_write($virtualRoot . '/example.com/passwd', "info:x:1000:12::/home/alice/imap/example.com/info:/bin/false\n");
test_write($virtualRoot . '/example.com/aliases', "alias: info\n");
$repo = new RuleRepository(TEST_TMP . '/worker-suppress-data');
$repo->create('alice', [
'subject' => 'Urlop',
'body' => 'Body',
'start_ts' => 1,
'end_ts' => 2000,
'enabled' => true,
]);
$sent = 0;
$worker = new GlobalAutoresponderWorker(
$settings,
$repo,
new MailboxDirectory($virtualRoot),
new RepeatState(TEST_TMP . '/worker-suppress-state', 1000),
static function () use (&$sent): bool {
$sent++;
return true;
},
1000
);
assert_same(0, $worker->handle(
['SENDER_ADDRESS' => 'person@example.net', 'RECIPIENT' => 'info@example.com'],
"Precedence: bulk\n\nBody"
));
assert_same(0, $worker->handle(
['SENDER_ADDRESS' => 'person@example.net', 'RECIPIENT' => 'alias@example.com'],
"Auto-Submitted: no\n\nBody"
));
assert_same(0, $sent);
});
+3
View File
@@ -14,4 +14,7 @@ test('mailbox directory returns only pop imap mailboxes owned by user', function
$mailboxes = $dir->mailboxesForUser('alice');
assert_same(['info@example.com', 'sales@example.com'], array_column($mailboxes, 'email'));
assert_same('alice', $dir->resolveRecipient('info@example.com')['owner'] ?? '');
assert_same(null, $dir->resolveRecipient('alias@example.com'));
assert_same(null, $dir->resolveRecipient('missing@example.com'));
});