1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2026-06-20 21:40:43 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
milkmaker dafde866ff update postscreen_access.cidr 2026-06-01 00:52:18 +00:00
20 changed files with 87 additions and 121 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
- "watchdog-mailcow" - "watchdog-mailcow"
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v7 - uses: actions/checkout@v6
- name: Setup Docker - name: Setup Docker
run: | run: |
curl -sSL https://get.docker.com/ | CHANNEL=stable sudo sh curl -sSL https://get.docker.com/ | CHANNEL=stable sudo sh
+2 -2
View File
@@ -8,11 +8,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v7 uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Run the Action - name: Run the Action
uses: devops-infra/action-pull-request@v1.3.0 uses: devops-infra/action-pull-request@v1.2.1
with: with:
github_token: ${{ secrets.PRTONIGHTLY_ACTION_PAT }} github_token: ${{ secrets.PRTONIGHTLY_ACTION_PAT }}
title: Automatic PR to nightly from ${{ github.event.repository.updated_at}} title: Automatic PR to nightly from ${{ github.event.repository.updated_at}}
+1 -1
View File
@@ -13,7 +13,7 @@ jobs:
packages: write packages: write
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v7 uses: actions/checkout@v6
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v4 uses: docker/setup-qemu-action@v4
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v7 uses: actions/checkout@v6
- name: Generate postscreen_access.cidr - name: Generate postscreen_access.cidr
run: | run: |
+2 -2
View File
@@ -7,13 +7,13 @@ ARG APCU_PECL_VERSION=5.1.28
# renovate: datasource=github-tags depName=Imagick/imagick versioning=semver-coerced extractVersion=(?<version>.*)$ # renovate: datasource=github-tags depName=Imagick/imagick versioning=semver-coerced extractVersion=(?<version>.*)$
ARG IMAGICK_PECL_VERSION=3.8.1 ARG IMAGICK_PECL_VERSION=3.8.1
# renovate: datasource=github-tags depName=php/pecl-mail-mailparse versioning=semver-coerced extractVersion=^v(?<version>.*)$ # renovate: datasource=github-tags depName=php/pecl-mail-mailparse versioning=semver-coerced extractVersion=^v(?<version>.*)$
ARG MAILPARSE_PECL_VERSION=3.2.0 ARG MAILPARSE_PECL_VERSION=3.1.9
# renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced extractVersion=^v(?<version>.*)$ # renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced extractVersion=^v(?<version>.*)$
ARG MEMCACHED_PECL_VERSION=3.4.0 ARG MEMCACHED_PECL_VERSION=3.4.0
# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=(?<version>.*)$ # renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=(?<version>.*)$
ARG REDIS_PECL_VERSION=6.3.0 ARG REDIS_PECL_VERSION=6.3.0
# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=(?<version>.*)$ # renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=(?<version>.*)$
ARG COMPOSER_VERSION=2.10.1 ARG COMPOSER_VERSION=2.9.5
RUN apk add -U --no-cache autoconf \ RUN apk add -U --no-cache autoconf \
aspell-dev \ aspell-dev \
+1 -1
View File
@@ -2,7 +2,7 @@ FROM debian:trixie-slim
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>" LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
ARG RSPAMD_VER=rspamd_4.1.0-1~e2b0b18 ARG RSPAMD_VER=rspamd_3.14.3-1~236eb65
ARG CODENAME=trixie ARG CODENAME=trixie
ENV LC_ALL=C ENV LC_ALL=C
+3 -3
View File
@@ -1,6 +1,6 @@
# SOGo built from source to enable security patch application # SOGo built from source to enable security patch application
# Repository: https://github.com/Alinto/sogo # Repository: https://github.com/Alinto/sogo
# Version: SOGo-5.12.9 # Version: SOGo-5.12.8
# #
# Applied security patches: # Applied security patches:
# - # -
@@ -12,8 +12,8 @@ FROM debian:bookworm
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>" LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
ARG SOGO_VERSION=SOGo-5.12.9 ARG SOGO_VERSION=SOGo-5.12.8
ARG SOPE_VERSION=SOPE-5.12.9 ARG SOPE_VERSION=SOPE-5.12.8
# Security patches to apply (space-separated commit hashes) # Security patches to apply (space-separated commit hashes)
ARG SOGO_SECURITY_PATCHES="" ARG SOGO_SECURITY_PATCHES=""
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?<version>.*)$ # renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?<version>.*)$
@@ -3,7 +3,8 @@ rules {
backend = "http"; backend = "http";
url = "http://nginx:9081/pipe.php"; url = "http://nginx:9081/pipe.php";
selector = "reject_no_global_bl"; selector = "reject_no_global_bl";
formatter = "multipart"; formatter = "default";
meta_headers = true;
} }
RLINFO { RLINFO {
backend = "http"; backend = "http";
@@ -15,7 +16,8 @@ rules {
backend = "http"; backend = "http";
url = "http://nginx:9081/pushover.php"; url = "http://nginx:9081/pushover.php";
selector = "mailcow_rcpt"; selector = "mailcow_rcpt";
formatter = "multipart"; formatter = "json";
meta_headers = true;
} }
} }
+32 -27
View File
@@ -32,42 +32,47 @@ function parse_email($email) {
$a = strrpos($email, '@'); $a = strrpos($email, '@');
return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1)); return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1));
} }
// rspamd metadata_exporter (multipart formatter): if (!function_exists('getallheaders')) {
// - $_POST['metadata'] JSON with the rspamd metadata function getallheaders() {
// - $_FILES['message'] raw RFC822 message if (!is_array($_SERVER)) {
if (empty($_POST['metadata']) || !isset($_FILES['message']) || $_FILES['message']['error'] !== UPLOAD_ERR_OK) { return array();
error_log("QUARANTINE: missing multipart parts from rspamd" . PHP_EOL); }
http_response_code(400); $headers = array();
exit; foreach ($_SERVER as $name => $value) {
if (substr($name, 0, 5) == 'HTTP_') {
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
}
}
return $headers;
}
} }
$meta = json_decode($_POST['metadata'], true); $raw_data_content = file_get_contents('php://input');
if (!is_array($meta)) {
error_log("QUARANTINE: cannot decode metadata JSON" . PHP_EOL);
http_response_code(400);
exit;
}
$raw_data_content = file_get_contents($_FILES['message']['tmp_name']);
$raw_data = mb_convert_encoding($raw_data_content, 'HTML-ENTITIES', "UTF-8"); $raw_data = mb_convert_encoding($raw_data_content, 'HTML-ENTITIES', "UTF-8");
$raw_size = (int)$_FILES['message']['size']; $headers = getallheaders();
$qid = $meta['qid'] ?? 'unknown'; $qid = $headers['X-Rspamd-Qid'];
$subject = iconv_mime_decode($meta['subject'] ?? ''); $fuzzy = $headers['X-Rspamd-Fuzzy'];
$score = $meta['score'] ?? 0; $subject = iconv_mime_decode($headers['X-Rspamd-Subject']);
$rcpts = $meta['rcpt'] ?? array(); $score = $headers['X-Rspamd-Score'];
$user = $meta['user'] ?? 'unknown'; $rcpts = $headers['X-Rspamd-Rcpt'];
$ip = $meta['ip'] ?? 'unknown'; $user = $headers['X-Rspamd-User'];
$action = $meta['action'] ?? 'no action'; $ip = $headers['X-Rspamd-Ip'];
$sender = $meta['from'] ?? ''; $action = $headers['X-Rspamd-Action'];
$symbols = json_encode($meta['symbols'] ?? array()); $sender = $headers['X-Rspamd-From'];
$fuzzy = json_encode(is_array($meta['fuzzy'] ?? null) ? $meta['fuzzy'] : array()); $symbols = $headers['X-Rspamd-Symbols'];
$raw_size = (int)$_SERVER['CONTENT_LENGTH'];
if (empty($sender)) { if (empty($sender)) {
error_log("QUARANTINE: Unknown sender, assuming empty-env-from@localhost" . PHP_EOL); error_log("QUARANTINE: Unknown sender, assuming empty-env-from@localhost" . PHP_EOL);
$sender = 'empty-env-from@localhost'; $sender = 'empty-env-from@localhost';
} }
if ($fuzzy == 'unknown') {
$fuzzy = '[]';
}
try { try {
$max_size = (int)$redis->Get('Q_MAX_SIZE'); $max_size = (int)$redis->Get('Q_MAX_SIZE');
if (($max_size * 1048576) < $raw_size) { if (($max_size * 1048576) < $raw_size) {
@@ -89,7 +94,7 @@ catch (RedisException $e) {
$rcpt_final_mailboxes = array(); $rcpt_final_mailboxes = array();
// Loop through all rcpts // Loop through all rcpts
foreach ($rcpts as $rcpt) { foreach (json_decode($rcpts, true) as $rcpt) {
// Remove tag // Remove tag
$rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt); $rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt);
+26 -22
View File
@@ -32,46 +32,50 @@ function parse_email($email) {
$a = strrpos($email, '@'); $a = strrpos($email, '@');
return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1)); return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1));
} }
// rspamd metadata_exporter (multipart formatter): metadata JSON arrives as $_POST['metadata']. if (!function_exists('getallheaders')) {
if (empty($_POST['metadata'])) { function getallheaders() {
error_log("NOTIFY: missing metadata part from rspamd" . PHP_EOL); if (!is_array($_SERVER)) {
http_response_code(400); return array();
exit; }
$headers = array();
foreach ($_SERVER as $name => $value) {
if (substr($name, 0, 5) == 'HTTP_') {
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
}
}
return $headers;
}
} }
$meta = json_decode($_POST['metadata'], true); $headers = getallheaders();
if (!is_array($meta)) { $json_body = json_decode(file_get_contents('php://input'));
error_log("NOTIFY: cannot decode metadata JSON" . PHP_EOL);
http_response_code(400);
exit;
}
$qid = $meta['qid'] ?? 'unknown'; $qid = $headers['X-Rspamd-Qid'];
$rcpts = $meta['rcpt'] ?? array(); $rcpts = $headers['X-Rspamd-Rcpt'];
$sender = $meta['from'] ?? ''; $sender = $headers['X-Rspamd-From'];
$ip = $meta['ip'] ?? 'unknown'; $ip = $headers['X-Rspamd-Ip'];
$subject = iconv_mime_decode($meta['subject'] ?? ''); $subject = iconv_mime_decode($headers['X-Rspamd-Subject']);
$messageid= $meta['message_id'] ?? ''; $messageid= $json_body->message_id;
$priority = 0; $priority = 0;
$symbols_array = $meta['symbols'] ?? array(); $symbols_array = json_decode($headers['X-Rspamd-Symbols'], true);
if (is_array($symbols_array)) { if (is_array($symbols_array)) {
foreach ($symbols_array as $symbol) { foreach ($symbols_array as $symbol) {
if (($symbol['name'] ?? null) == 'HAS_X_PRIO_ONE') { if ($symbol['name'] == 'HAS_X_PRIO_ONE') {
$priority = 1; $priority = 1;
break; break;
} }
} }
} }
$sender_address = $meta['header_from'][0] ?? ''; $sender_address = $json_body->header_from[0];
$sender_name = '-'; $sender_name = '-';
if (preg_match('/(?<name>.*?)<(?<address>.*?)>/i', $sender_address, $matches)) { if (preg_match('/(?<name>.*?)<(?<address>.*?)>/i', $sender_address, $matches)) {
$sender_address = $matches['address']; $sender_address = $matches['address'];
$sender_name = trim($matches['name'], '"\' '); $sender_name = trim($matches['name'], '"\' ');
} }
$to_address = $meta['header_to'][0] ?? ''; $to_address = $json_body->header_to[0];
$to_name = '-'; $to_name = '-';
if (preg_match('/(?<name>.*?)<(?<address>.*?)>/i', $to_address, $matches)) { if (preg_match('/(?<name>.*?)<(?<address>.*?)>/i', $to_address, $matches)) {
$to_address = $matches['address']; $to_address = $matches['address'];
@@ -81,7 +85,7 @@ if (preg_match('/(?<name>.*?)<(?<address>.*?)>/i', $to_address, $matches)) {
$rcpt_final_mailboxes = array(); $rcpt_final_mailboxes = array();
// Loop through all rcpts // Loop through all rcpts
foreach ($rcpts as $rcpt) { foreach (json_decode($rcpts, true) as $rcpt) {
// Remove tag // Remove tag
$rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt); $rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt);
-12
View File
@@ -1072,7 +1072,6 @@ paths:
password2: "*" password2: "*"
quota: "3072" quota: "3072"
force_pw_update: "1" force_pw_update: "1"
force_tfa: "1"
tls_enforce_in: "1" tls_enforce_in: "1"
tls_enforce_out: "1" tls_enforce_out: "1"
tags: ["tag1", "tag2"] tags: ["tag1", "tag2"]
@@ -1119,7 +1118,6 @@ paths:
password2: atedismonsin password2: atedismonsin
quota: "3072" quota: "3072"
force_pw_update: "1" force_pw_update: "1"
force_tfa: "1"
tls_enforce_in: "1" tls_enforce_in: "1"
tls_enforce_out: "1" tls_enforce_out: "1"
tags: ["tag1", "tag2"] tags: ["tag1", "tag2"]
@@ -1153,9 +1151,6 @@ paths:
force_pw_update: force_pw_update:
description: forces the user to update its password on first login description: forces the user to update its password on first login
type: boolean type: boolean
force_tfa:
description: force 2FA enrollment at login
type: boolean
tls_enforce_in: tls_enforce_in:
description: force inbound email tls encryption description: force inbound email tls encryption
type: boolean type: boolean
@@ -3419,7 +3414,6 @@ paths:
- mailbox - mailbox
- active: "1" - active: "1"
force_pw_update: "0" force_pw_update: "0"
force_tfa: "0"
name: Full name name: Full name
password: "*" password: "*"
password2: "*" password2: "*"
@@ -3470,7 +3464,6 @@ paths:
attr: attr:
active: "1" active: "1"
force_pw_update: "0" force_pw_update: "0"
force_tfa: "0"
name: Full name name: Full name
authsource: mailcow authsource: mailcow
password: "" password: ""
@@ -3494,9 +3487,6 @@ paths:
force_pw_update: force_pw_update:
description: force user to change password on next login description: force user to change password on next login
type: boolean type: boolean
force_tfa:
description: force 2FA enrollment at login
type: boolean
name: name:
description: Full name of the mailbox user description: Full name of the mailbox user
type: string type: string
@@ -4891,7 +4881,6 @@ paths:
- active: "1" - active: "1"
attributes: attributes:
force_pw_update: "0" force_pw_update: "0"
force_tfa: "0"
mailbox_format: "maildir:" mailbox_format: "maildir:"
quarantine_notification: never quarantine_notification: never
sogo_access: "1" sogo_access: "1"
@@ -5816,7 +5805,6 @@ paths:
- active: "1" - active: "1"
attributes: attributes:
force_pw_update: "0" force_pw_update: "0"
force_tfa: "0"
mailbox_format: "maildir:" mailbox_format: "maildir:"
quarantine_notification: never quarantine_notification: never
sogo_access: "1" sogo_access: "1"
+2 -1
View File
@@ -3505,6 +3505,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
// Track affected mailboxes for SOGo update // Track affected mailboxes for SOGo update
$update_sogo_mailboxes[] = $username; $update_sogo_mailboxes[] = $username;
} }
return true;
break; break;
case 'mailbox_rename': case 'mailbox_rename':
$domain = $_data['domain']; $domain = $_data['domain'];
@@ -3827,7 +3828,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : $is_now['rl_frame']; $attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : $is_now['rl_frame'];
$attr["rl_value"] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : $is_now['rl_value']; $attr["rl_value"] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : $is_now['rl_value'];
$attr["force_pw_update"] = isset($_data['force_pw_update']) ? intval($_data['force_pw_update']) : $is_now['force_pw_update']; $attr["force_pw_update"] = isset($_data['force_pw_update']) ? intval($_data['force_pw_update']) : $is_now['force_pw_update'];
$attr["force_tfa"] = isset($_data['force_tfa']) ? intval($_data['force_tfa']) : $is_now['force_tfa'];
$attr["sogo_access"] = isset($_data['sogo_access']) ? intval($_data['sogo_access']) : $is_now['sogo_access']; $attr["sogo_access"] = isset($_data['sogo_access']) ? intval($_data['sogo_access']) : $is_now['sogo_access'];
$attr["active"] = isset($_data['active']) ? intval($_data['active']) : $is_now['active']; $attr["active"] = isset($_data['active']) ? intval($_data['active']) : $is_now['active'];
$attr["tls_enforce_in"] = isset($_data['tls_enforce_in']) ? intval($_data['tls_enforce_in']) : $is_now['tls_enforce_in']; $attr["tls_enforce_in"] = isset($_data['tls_enforce_in']) ? intval($_data['tls_enforce_in']) : $is_now['tls_enforce_in'];
@@ -6127,6 +6127,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
// Track affected mailboxes for SOGo update // Track affected mailboxes for SOGo update
$update_sogo_mailboxes[] = $username; $update_sogo_mailboxes[] = $username;
} }
return true;
break; break;
case 'mailbox_templates': case 'mailbox_templates':
if ($_SESSION['mailcow_cc_role'] != "admin") { if ($_SESSION['mailcow_cc_role'] != "admin") {
-11
View File
@@ -424,11 +424,6 @@ $(document).ready(function() {
} else { } else {
$('#force_pw_update').prop('checked', false); $('#force_pw_update').prop('checked', false);
} }
if (template.force_tfa == 1){
$('#force_tfa').prop('checked', true);
} else {
$('#force_tfa').prop('checked', false);
}
if (template.sogo_access == 1){ if (template.sogo_access == 1){
$('#sogo_access').prop('checked', true); $('#sogo_access').prop('checked', true);
} else { } else {
@@ -1247,7 +1242,6 @@ jQuery(function($){
item.attributes.eas_access = '<i class="text-' + (item.attributes.eas_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.eas_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.eas_access == 1 ? '1' : '0') + '</span></i>'; item.attributes.eas_access = '<i class="text-' + (item.attributes.eas_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.eas_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.eas_access == 1 ? '1' : '0') + '</span></i>';
item.attributes.dav_access = '<i class="text-' + (item.attributes.dav_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.dav_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.dav_access == 1 ? '1' : '0') + '</span></i>'; item.attributes.dav_access = '<i class="text-' + (item.attributes.dav_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.dav_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.dav_access == 1 ? '1' : '0') + '</span></i>';
item.attributes.sogo_access = '<i class="text-' + (item.attributes.sogo_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sogo_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sogo_access == 1 ? '1' : '0') + '</span></i>'; item.attributes.sogo_access = '<i class="text-' + (item.attributes.sogo_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sogo_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sogo_access == 1 ? '1' : '0') + '</span></i>';
item.attributes.force_tfa = '<i class="text-' + (item.attributes.force_tfa == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.force_tfa == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.force_tfa == 1 ? '1' : '0') + '</span></i>';
if (item.attributes.quarantine_notification === 'never') { if (item.attributes.quarantine_notification === 'never') {
item.attributes.quarantine_notification = lang.never; item.attributes.quarantine_notification = lang.never;
} else if (item.attributes.quarantine_notification === 'hourly') { } else if (item.attributes.quarantine_notification === 'hourly') {
@@ -1391,11 +1385,6 @@ jQuery(function($){
return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>'; return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
} }
}, },
{
title: lang.force_tfa,
data: 'attributes.force_tfa',
defaultContent: ''
},
{ {
title: lang_edit.ratelimit, title: lang_edit.ratelimit,
data: 'attributes.ratelimit', data: 'attributes.ratelimit',
-1
View File
@@ -929,7 +929,6 @@
"filters": "Filters", "filters": "Filters",
"fname": "Full name", "fname": "Full name",
"force_pw_update": "Force password update at next login", "force_pw_update": "Force password update at next login",
"force_tfa": "TFA",
"gal": "Global Address List", "gal": "Global Address List",
"goto_ham": "Learn as <b>ham</b>", "goto_ham": "Learn as <b>ham</b>",
"goto_spam": "Learn as <b>spam</b>", "goto_spam": "Learn as <b>spam</b>",
+6 -17
View File
@@ -111,8 +111,7 @@
"app_passwd_protocols": "Protocoles autorisés pour le mot de passe de l'application", "app_passwd_protocols": "Protocoles autorisés pour le mot de passe de l'application",
"dry": "Simuler la synchronisation", "dry": "Simuler la synchronisation",
"internal": "Interne", "internal": "Interne",
"internal_info": "Les alias internes sont accessibles uniquement depuis le domaine ou les alias du domaine.", "internal_info": "Les alias internes sont accessibles uniquement depuis le domaine ou les alias du domaine."
"sender_allowed": "Autoriser l'envoi sous cet alias"
}, },
"admin": { "admin": {
"access": "Accès", "access": "Accès",
@@ -557,9 +556,7 @@
"max_age_invalid": "L'âge maximum %s est invalide", "max_age_invalid": "L'âge maximum %s est invalide",
"mode_invalid": "Le mode %s est invalide", "mode_invalid": "Le mode %s est invalide",
"mx_invalid": "L'enregistrement MX %s est invalide", "mx_invalid": "L'enregistrement MX %s est invalide",
"version_invalid": "La version %s est invalide", "version_invalid": "La version %s est invalide"
"tfa_removal_blocked": "Lauthentification à deux facteurs ne peut pas être supprimée, car elle est requise pour votre compte.",
"quarantine_category_invalid": "La catégorie de quarantaine doit être lune des suivantes : add_header, reject, all\""
}, },
"debug": { "debug": {
"chart_this_server": "Graphique (ce serveur)", "chart_this_server": "Graphique (ce serveur)",
@@ -758,9 +755,7 @@
"mta_sts_info": "<a href='https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol#SMTP_MTA_Strict_Transport_Security' target='_blank'>MTA-STS</a> est un standard qui oblige la délivrance des courriels entre les serveurs de courriels à utiliser TLS avec des certificats valides. <br>Il est utilisé quand <a target='_blank' href='https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities'>DANE</a> n'est pas possible à cause d'un manque ou d'un non support de DNSSEC.<br><b>Note</b> : Si le domaine du destinataire supporte DANE avec DNSSEC, DANE est <b>toujours</b> préféré MTA-STS sert seulement en secours.", "mta_sts_info": "<a href='https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol#SMTP_MTA_Strict_Transport_Security' target='_blank'>MTA-STS</a> est un standard qui oblige la délivrance des courriels entre les serveurs de courriels à utiliser TLS avec des certificats valides. <br>Il est utilisé quand <a target='_blank' href='https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities'>DANE</a> n'est pas possible à cause d'un manque ou d'un non support de DNSSEC.<br><b>Note</b> : Si le domaine du destinataire supporte DANE avec DNSSEC, DANE est <b>toujours</b> préféré MTA-STS sert seulement en secours.",
"mta_sts_mode_info": "Il y a trois modes parmi lesquels choisir :<ul><li><em>testing</em> la politique est seulement surveillée, les violations n'ont pas d'impact.</li><li><em>enforce</em> la politique est appliquée strictement, les connexions sans TLS valide sont rejetées.</li><li><em>none</em> la politique est publiée mais non appliquée.</li></ul>", "mta_sts_mode_info": "Il y a trois modes parmi lesquels choisir :<ul><li><em>testing</em> la politique est seulement surveillée, les violations n'ont pas d'impact.</li><li><em>enforce</em> la politique est appliquée strictement, les connexions sans TLS valide sont rejetées.</li><li><em>none</em> la politique est publiée mais non appliquée.</li></ul>",
"mta_sts_max_age_info": "Durée en secondes pendant laquelle les serveurs de courriel peuvent mettre en cache cette politique avant de revérifier.", "mta_sts_max_age_info": "Durée en secondes pendant laquelle les serveurs de courriel peuvent mettre en cache cette politique avant de revérifier.",
"mta_sts_mx_info": "Autoriser l'envoi uniquement aux noms d'hôtes des serveurs de courriels indiqués explicitement ; le MTA émetteur vérifie si le nom d'hôte DNS du MX correspond à la liste de la politique, et autorise la délivrance seulement avec un certificat TLS valide (protège contre le MITM).", "mta_sts_mx_info": "Autoriser l'envoi uniquement aux noms d'hôtes des serveurs de courriels indiqués explicitement ; le MTA émetteur vérifie si le nom d'hôte DNS du MX correspond à la liste de la politique, et autorise la délivrance seulement avec un certificat TLS valide (protège contre le MITM)."
"sender_allowed": "Autoriser l'envoi sous cet alias",
"sender_allowed_info": "Si cette option est désactivée, cet alias peut uniquement recevoir des courriels. Utilisez les ACL dexpéditeur pour autoriser certaines boîtes aux lettres à envoyer des messages via cet alias."
}, },
"footer": { "footer": {
"cancel": "Annuler", "cancel": "Annuler",
@@ -993,8 +988,7 @@
"recipient": "Destinataire", "recipient": "Destinataire",
"open_logs": "Afficher les journaux", "open_logs": "Afficher les journaux",
"iam": "Fournisseur d'identité", "iam": "Fournisseur d'identité",
"internal": "Interne", "internal": "Interne"
"force_tfa": "TFA"
}, },
"oauth2": { "oauth2": {
"access_denied": "Veuillez vous connecter en tant que propriétaire de la boîte de réception pour accorder laccès via Oauth2.", "access_denied": "Veuillez vous connecter en tant que propriétaire de la boîte de réception pour accorder laccès via Oauth2.",
@@ -1195,11 +1189,7 @@
"yubi_otp": "Authentification OTP Yubico", "yubi_otp": "Authentification OTP Yubico",
"authenticators": "Authentificateurs", "authenticators": "Authentificateurs",
"u2f_deprecated_important": "Veuillez enregistrer votre clé dans le panneau d'administration avec la nouvelle méthode WebAuthn.", "u2f_deprecated_important": "Veuillez enregistrer votre clé dans le panneau d'administration avec la nouvelle méthode WebAuthn.",
"u2f_deprecated": "Il semble que votre clé ait été enregistrée à l'aide de la méthode U2F obsolète. Nous allons désactiver l'authentification à deux facteurs pour vous et supprimer votre clé.", "u2f_deprecated": "Il semble que votre clé ait été enregistrée à l'aide de la méthode U2F obsolète. Nous allons désactiver l'authentification à deux facteurs pour vous et supprimer votre clé."
"force_tfa": "Imposer l'authentification à deux facteurs lors de la connexion",
"force_tfa_info": "Lutilisateur doit configurer lauthentification à deux facteurs avant de pouvoir accéder à linterface.",
"setup_title": "Authentification à deux facteurs requise",
"setup_required": "Votre compte nécessite lauthentification à deux facteurs. Veuillez configurer une méthode 2FA pour continuer."
}, },
"fido2": { "fido2": {
"set_fn": "Définir un nom", "set_fn": "Définir un nom",
@@ -1388,8 +1378,7 @@
"forever": "Pour toujours", "forever": "Pour toujours",
"spam_aliases_info": "Un alias de spam est une adresse de courriel temporaire qui peut être utilisée pour protéger les véritables adresses de courriel. <br> De manière optionnelle, une durée d'expiration peut être définie afin que l'alias soit automatiquement désactivé après la période définie, éliminant ainsi les adresses étant abusées ou ayant fuité.", "spam_aliases_info": "Un alias de spam est une adresse de courriel temporaire qui peut être utilisée pour protéger les véritables adresses de courriel. <br> De manière optionnelle, une durée d'expiration peut être définie afin que l'alias soit automatiquement désactivé après la période définie, éliminant ainsi les adresses étant abusées ou ayant fuité.",
"authentication": "Authentification", "authentication": "Authentification",
"protocols": "Protocoles", "protocols": "Protocoles"
"pw_update_required": "Votre compte nécessite un changement de mot de passe. Veuillez définir un nouveau mot de passe pour continuer."
}, },
"warning": { "warning": {
"cannot_delete_self": "Impossible de supprimer lutilisateur connecté", "cannot_delete_self": "Impossible de supprimer lutilisateur connecté",
+1 -2
View File
@@ -1001,8 +1001,7 @@
"weekly": "Tedensko", "weekly": "Tedensko",
"sieve_info": "Na uporabnika lahko shranite več filtrov, vendar je lahko hkrati aktiven le en predfilter in en postfilter.<br>\nVsak filter bo obdelan v opisanem vrstnem redu. Niti neuspešen skript niti izdan ukaz »keep;« ne bosta ustavila obdelave nadaljnjih skript. Spremembe globalnih skriptov sita bodo sprožile ponovni zagon Dovecota.<br><br>Globalni predfilter sita &#8226; Predfilter &#8226; Uporabniški skripti &#8226; Postfilter &#8226; Globalni postfilter sita", "sieve_info": "Na uporabnika lahko shranite več filtrov, vendar je lahko hkrati aktiven le en predfilter in en postfilter.<br>\nVsak filter bo obdelan v opisanem vrstnem redu. Niti neuspešen skript niti izdan ukaz »keep;« ne bosta ustavila obdelave nadaljnjih skript. Spremembe globalnih skriptov sita bodo sprožile ponovni zagon Dovecota.<br><br>Globalni predfilter sita &#8226; Predfilter &#8226; Uporabniški skripti &#8226; Postfilter &#8226; Globalni postfilter sita",
"tls_policy_maps_info": "Ta preslikava pravilnikov preglasi pravila odhodnega prenosa TLS neodvisno od uporabnikovih nastavitev pravilnikov TLS.<br>\n Za več informacij preverite <a href=\"http://www.postfix.org/postconf.5.html#smtp_tls_policy_maps\" target=\"_blank\">dokumentacijo »smtp_tls_policy_maps«</a>.", "tls_policy_maps_info": "Ta preslikava pravilnikov preglasi pravila odhodnega prenosa TLS neodvisno od uporabnikovih nastavitev pravilnikov TLS.<br>\n Za več informacij preverite <a href=\"http://www.postfix.org/postconf.5.html#smtp_tls_policy_maps\" target=\"_blank\">dokumentacijo »smtp_tls_policy_maps«</a>.",
"internal": "Notranje", "internal": "Notranje"
"force_tfa": "TFA"
}, },
"fido2": { "fido2": {
"known_ids": "Znani ID-ji", "known_ids": "Znani ID-ji",
-1
View File
@@ -65,7 +65,6 @@ if (isset($_GET['app_password'])) {
$attr['protocols'][] = 'dav_access'; $attr['protocols'][] = 'dav_access';
} }
app_passwd("add", $attr); app_passwd("add", $attr);
$password = htmlspecialchars($password, ENT_NOQUOTES);
} else { } else {
$app_password = false; $app_password = false;
} }
@@ -8,7 +8,6 @@
<input type="hidden" value="default" name="sender_acl"> <input type="hidden" value="default" name="sender_acl">
<input type="hidden" value="0" name="force_pw_update"> <input type="hidden" value="0" name="force_pw_update">
<input type="hidden" value="0" name="force_tfa">
<input type="hidden" value="0" name="sogo_access"> <input type="hidden" value="0" name="sogo_access">
<input type="hidden" value="0" name="protocol_access"> <input type="hidden" value="0" name="protocol_access">
@@ -166,14 +165,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="offset-sm-2 col-sm-10">
<div class="form-check">
<label><input type="checkbox" class="form-check-input" value="1" name="force_tfa" id="force_tfa"{% if template.attributes.force_tfa == '1' %} checked{% endif %}> {{ lang.tfa.force_tfa }}</label>
<small class="text-muted">{{ lang.tfa.force_tfa_info }}</small>
</div>
</div>
</div>
{% if not skip_sogo %} {% if not skip_sogo %}
<div class="row"> <div class="row">
<div class="offset-sm-2 col-sm-10"> <div class="offset-sm-2 col-sm-10">
+3 -3
View File
@@ -84,7 +84,7 @@ services:
- clamd - clamd
rspamd-mailcow: rspamd-mailcow:
image: ghcr.io/mailcow/rspamd:4.1.0-1 image: ghcr.io/mailcow/rspamd:3.14.3-1
stop_grace_period: 30s stop_grace_period: 30s
depends_on: depends_on:
- dovecot-mailcow - dovecot-mailcow
@@ -117,7 +117,7 @@ services:
- rspamd - rspamd
php-fpm-mailcow: php-fpm-mailcow:
image: ghcr.io/mailcow/phpfpm:8.2.29-3 image: ghcr.io/mailcow/phpfpm:8.2.29-2
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0" command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
depends_on: depends_on:
- redis-mailcow - redis-mailcow
@@ -200,7 +200,7 @@ services:
- phpfpm - phpfpm
sogo-mailcow: sogo-mailcow:
image: ghcr.io/mailcow/sogo:5.12.9-1 image: ghcr.io/mailcow/sogo:5.12.8-1
environment: environment:
- DBNAME=${DBNAME} - DBNAME=${DBNAME}
- DBUSER=${DBUSER} - DBUSER=${DBUSER}
@@ -25,6 +25,6 @@ services:
- /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock - /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock
mysql-mailcow: mysql-mailcow:
image: alpine:3.24 image: alpine:3.23
command: /bin/true command: /bin/true
restart: "no" restart: "no"