mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-11-09 10:21:45 +00:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c304040140 | ||
|
|
7a1b68c5e2 | ||
|
|
ce2062db5f |
No files matched your search
@@ -199,7 +199,8 @@ plugin {
|
|||||||
sieve_plugins = sieve_imapsieve sieve_extprograms
|
sieve_plugins = sieve_imapsieve sieve_extprograms
|
||||||
sieve_vacation_send_from_recipient = yes
|
sieve_vacation_send_from_recipient = yes
|
||||||
sieve_redirect_envelope_from = recipient
|
sieve_redirect_envelope_from = recipient
|
||||||
# Notifications are sent with the address of the mailbox (not :from or postmaster), so mail policies apply
|
# Notifications are sent with the address of the mailbox (not :from or postmaster), so mail policies apply;
|
||||||
|
# the old notify extension always sends as postmaster and is on by default, so sieve_extensions disables it
|
||||||
sieve_notify_mailto_envelope_from = recipient
|
sieve_notify_mailto_envelope_from = recipient
|
||||||
# From elsewhere to Spam folder
|
# From elsewhere to Spam folder
|
||||||
imapsieve_mailbox1_name = Junk
|
imapsieve_mailbox1_name = Junk
|
||||||
@@ -217,7 +218,7 @@ plugin {
|
|||||||
quota_warning2 = storage=80%% quota-warning 80 %u
|
quota_warning2 = storage=80%% quota-warning 80 %u
|
||||||
sieve_pipe_bin_dir = /usr/lib/dovecot/sieve
|
sieve_pipe_bin_dir = /usr/lib/dovecot/sieve
|
||||||
sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.execute
|
sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.execute
|
||||||
sieve_extensions = +notify +imapflags +vacation-seconds +editheader
|
sieve_extensions = -notify +imapflags +vacation-seconds +editheader
|
||||||
sieve_max_script_size = 1M
|
sieve_max_script_size = 1M
|
||||||
sieve_max_redirects = 100
|
sieve_max_redirects = 100
|
||||||
sieve_max_actions = 101
|
sieve_max_actions = 101
|
||||||
|
|||||||
@@ -121,9 +121,10 @@ smtp_sender_cleanup unix n - y - 0 cleanup
|
|||||||
mailcow-policy unix - n n - 0 spawn user=nobody argv=/usr/local/bin/mailcow-policy.py
|
mailcow-policy unix - n n - 0 spawn user=nobody argv=/usr/local/bin/mailcow-policy.py
|
||||||
|
|
||||||
# start watchdog-specific
|
# start watchdog-specific
|
||||||
# logs to local7 (hidden)
|
# logs to local7 (hidden), no mail policy check
|
||||||
589 inet n - n - - smtpd
|
589 inet n - n - - smtpd
|
||||||
-o smtpd_client_restrictions=permit_mynetworks,reject
|
-o smtpd_client_restrictions=permit_mynetworks,reject
|
||||||
|
-o smtpd_recipient_restrictions=permit_mynetworks,reject
|
||||||
-o syslog_name=watchdog
|
-o syslog_name=watchdog
|
||||||
-o syslog_facility=local7
|
-o syslog_facility=local7
|
||||||
-o smtpd_milters=
|
-o smtpd_milters=
|
||||||
|
|||||||
@@ -105,9 +105,11 @@ class PolicyEngine
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return match ($mode) {
|
return match ($mode) {
|
||||||
|
'all' => true,
|
||||||
'internal' => $internal || $this->any($allow, $matches),
|
'internal' => $internal || $this->any($allow, $matches),
|
||||||
'list' => $this->any($allow, $matches),
|
'list' => $this->any($allow, $matches),
|
||||||
default => true,
|
// an unknown mode lets nothing through
|
||||||
|
default => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -288,11 +288,15 @@ class PolicyService
|
|||||||
}
|
}
|
||||||
$entry = 'group:' . $id;
|
$entry = 'group:' . $id;
|
||||||
} elseif (str_contains(ltrim($entry, '@'), '@')) {
|
} elseif (str_contains(ltrim($entry, '@'), '@')) {
|
||||||
if (!filter_var($entry, FILTER_VALIDATE_EMAIL)) {
|
// in the form the engine compares: domain without the final dot, never a +tag or an IP literal
|
||||||
|
$at = strrpos($entry, '@');
|
||||||
|
$local = substr($entry, 0, $at);
|
||||||
|
$entry = $local . '@' . rtrim(substr($entry, $at + 1), '.');
|
||||||
|
if (!filter_var($entry, FILTER_VALIDATE_EMAIL) || str_contains(substr($local, 1), '+') || str_contains($entry, '@[')) {
|
||||||
throw new UserError('mail_policy_entry_invalid', [htmlspecialchars($entry)]);
|
throw new UserError('mail_policy_entry_invalid', [htmlspecialchars($entry)]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$entry = ltrim($entry, '@');
|
$entry = rtrim(ltrim($entry, '@'), '.');
|
||||||
if (!str_contains($entry, '.') || !filter_var($entry, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)) {
|
if (!str_contains($entry, '.') || !filter_var($entry, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME)) {
|
||||||
throw new UserError('mail_policy_entry_invalid', [htmlspecialchars($entry)]);
|
throw new UserError('mail_policy_entry_invalid', [htmlspecialchars($entry)]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,13 @@ class PolicyEngineTest extends TestCase
|
|||||||
$this->assertSame('DUNNO', $this->engine->check('azubi@firma.de', 'x@extern.example', 'azubi@firma.de')->action());
|
$this->assertSame('DUNNO', $this->engine->check('azubi@firma.de', 'x@extern.example', 'azubi@firma.de')->action());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testUnknownModeLetsNothingThrough(): void
|
||||||
|
{
|
||||||
|
$this->lookup->mailboxPolicies['azubi@firma.de'] = [self::policy(1, ['sendMode' => 'nobody', 'receiveMode' => ''])];
|
||||||
|
$this->assertSame([false, 'send'], $this->check('azubi@firma.de', 'kollege@firma.de', 'azubi@firma.de'));
|
||||||
|
$this->assertSame([false, 'receive'], $this->check('kollege@firma.de', 'azubi@firma.de', 'kollege@firma.de'));
|
||||||
|
}
|
||||||
|
|
||||||
public function testSendOnlyInternalWithAllowedAndBlockedEntries(): void
|
public function testSendOnlyInternalWithAllowedAndBlockedEntries(): void
|
||||||
{
|
{
|
||||||
$this->lookup->mailboxPolicies['azubi@firma.de'] = [self::policy(1, [
|
$this->lookup->mailboxPolicies['azubi@firma.de'] = [self::policy(1, [
|
||||||
|
|||||||
@@ -113,6 +113,9 @@ class PolicyServiceTest extends TestCase
|
|||||||
'mode' => [['send_mode' => 'nobody'], 'mail_policy_mode_invalid'],
|
'mode' => [['send_mode' => 'nobody'], 'mail_policy_mode_invalid'],
|
||||||
'domain without dot' => [['send_allow' => 'localhost'], ['mail_policy_entry_invalid', 'localhost']],
|
'domain without dot' => [['send_allow' => 'localhost'], ['mail_policy_entry_invalid', 'localhost']],
|
||||||
'address' => [['receive_block' => 'a@@b.de'], ['mail_policy_entry_invalid', 'a@@b.de']],
|
'address' => [['receive_block' => 'a@@b.de'], ['mail_policy_entry_invalid', 'a@@b.de']],
|
||||||
|
'address with +tag' => [['receive_block' => 'news+promo@vendor.example'], ['mail_policy_entry_invalid', 'news+promo@vendor.example']],
|
||||||
|
'IP literal' => [['send_allow' => 'u@[127.0.0.1]'], ['mail_policy_entry_invalid', 'u@[127.0.0.1]']],
|
||||||
|
'top level domain' => [['send_block' => 'com.'], ['mail_policy_entry_invalid', 'com']],
|
||||||
'unknown group' => [['receive_block_groups' => ['8']], ['mail_policy_entry_invalid', 'group:8']],
|
'unknown group' => [['receive_block_groups' => ['8']], ['mail_policy_entry_invalid', 'group:8']],
|
||||||
'reject text with line break' => [['reject_text' => "a\r\nb"], 'mail_policy_reject_text_invalid'],
|
'reject text with line break' => [['reject_text' => "a\r\nb"], 'mail_policy_reject_text_invalid'],
|
||||||
'reject text not ASCII' => [['reject_text' => 'Nur für Azubis'], 'mail_policy_reject_text_invalid'],
|
'reject text not ASCII' => [['reject_text' => 'Nur für Azubis'], 'mail_policy_reject_text_invalid'],
|
||||||
@@ -122,6 +125,12 @@ class PolicyServiceTest extends TestCase
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testEntriesInTheFormTheEngineCompares(): void
|
||||||
|
{
|
||||||
|
$policy = $this->service()->create(['domain' => 'firma.de', 'name' => 'Test', 'receive_block' => "Spam.Example.\n@news.example\nBoss@Ext.Example.\n+x@ext.example"]);
|
||||||
|
$this->assertSame(['spam.example', 'news.example', 'boss@ext.example', '+x@ext.example'], $policy->receiveBlock);
|
||||||
|
}
|
||||||
|
|
||||||
#[DataProvider('invalidInput')]
|
#[DataProvider('invalidInput')]
|
||||||
public function testInvalidInput(array $input, string|array $error): void
|
public function testInvalidInput(array $input, string|array $error): void
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user