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

Compare commits

..

3 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] 4a89078240 fix: align transport password escaping
Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com>
2025-12-12 11:17:24 +00:00
copilot-swe-agent[bot] e8262ce12f fix: avoid double escaping relayhost passwords
Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com>
2025-12-12 11:15:35 +00:00
copilot-swe-agent[bot] e53e4f890f Initial plan 2025-12-12 11:11:50 +00:00
12 changed files with 13 additions and 81 deletions
-19
View File
@@ -246,25 +246,6 @@ while true; do
done done
VALIDATED_CONFIG_DOMAINS+=("${VALIDATED_CONFIG_DOMAINS_SUBDOMAINS[*]}") VALIDATED_CONFIG_DOMAINS+=("${VALIDATED_CONFIG_DOMAINS_SUBDOMAINS[*]}")
done done
# Fetch alias domains where target domain has MTA-STS enabled
if [[ ${AUTODISCOVER_SAN} == "y" ]]; then
SQL_ALIAS_DOMAINS=$(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT ad.alias_domain FROM alias_domain ad INNER JOIN mta_sts m ON ad.target_domain = m.domain WHERE ad.active = 1 AND m.active = 1" -Bs)
if [[ $? -eq 0 ]]; then
while read alias_domain; do
if [[ -z "${alias_domain}" ]]; then
# ignore empty lines
continue
fi
# Only add mta-sts subdomain for alias domains
if [[ "mta-sts.${alias_domain}" != "${MAILCOW_HOSTNAME}" ]]; then
if check_domain "mta-sts.${alias_domain}"; then
VALIDATED_CONFIG_DOMAINS+=("mta-sts.${alias_domain}")
fi
fi
done <<< "${SQL_ALIAS_DOMAINS}"
fi
fi
fi fi
if check_domain ${MAILCOW_HOSTNAME}; then if check_domain ${MAILCOW_HOSTNAME}; then
+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_3.14.2-82~90302bc ARG RSPAMD_VER=rspamd_3.14.1-1~46a758617
ARG CODENAME=trixie ARG CODENAME=trixie
ENV LC_ALL=C ENV LC_ALL=C
-2
View File
@@ -1,4 +1,3 @@
{%- if env.SKIP_CLAMD == "n" or env.SKIP_CLAMD == "no" -%}
clamav { clamav {
# Scan whole message # Scan whole message
scan_mime_parts = false; scan_mime_parts = false;
@@ -10,4 +9,3 @@ clamav {
servers = "clamd:3310"; servers = "clamd:3310";
max_size = 20971520; max_size = 20971520;
} }
{% endif %}
+1 -10
View File
@@ -129,16 +129,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
); );
} }
// Check if domain is an alias domain and get target domain's MTA-STS $mta_sts = mailbox('get', 'mta_sts', $domain);
$alias_domain_details = mailbox('get', 'alias_domain_details', $domain);
$mta_sts_domain = $domain;
if ($alias_domain_details !== false && !empty($alias_domain_details['target_domain'])) {
// This is an alias domain, check target domain for MTA-STS
$mta_sts_domain = $alias_domain_details['target_domain'];
}
$mta_sts = mailbox('get', 'mta_sts', $mta_sts_domain);
if (count($mta_sts) > 0 && $mta_sts['active'] == 1) { if (count($mta_sts) > 0 && $mta_sts['active'] == 1) {
if (!in_array($domain, $alias_domains)) { if (!in_array($domain, $alias_domains)) {
$records[] = array( $records[] = array(
+2 -2
View File
@@ -30,7 +30,7 @@ function relayhost($_action, $_data = null) {
$stmt->execute(array( $stmt->execute(array(
':hostname' => $hostname, ':hostname' => $hostname,
':username' => $username, ':username' => $username,
':password' => str_replace(':', '\:', $password), ':password' => $password,
':active' => '1' ':active' => '1'
)); ));
} }
@@ -291,7 +291,7 @@ function transport($_action, $_data = null) {
':destination' => $insert_dest, ':destination' => $insert_dest,
':is_mx_based' => $is_mx_based, ':is_mx_based' => $is_mx_based,
':username' => $username, ':username' => $username,
':password' => str_replace(':', '\:', $password), ':password' => $password,
':active' => $active ':active' => $active
)); ));
} }
-9
View File
@@ -54,16 +54,7 @@ jQuery(function($){
$.get("/inc/ajax/show_rspamd_global_filters.php"); $.get("/inc/ajax/show_rspamd_global_filters.php");
$("#confirm_show_rspamd_global_filters").hide(); $("#confirm_show_rspamd_global_filters").hide();
$("#rspamd_global_filters").removeClass("d-none"); $("#rspamd_global_filters").removeClass("d-none");
localStorage.setItem('rspamd_global_filters_confirmed', 'true');
}); });
$(document).ready(function() {
if (localStorage.getItem('rspamd_global_filters_confirmed') === 'true') {
$("#confirm_show_rspamd_global_filters").hide();
$("#rspamd_global_filters").removeClass("d-none");
}
});
$("#super_delete").click(function() { return confirm(lang.queue_ays); }); $("#super_delete").click(function() { return confirm(lang.queue_ays); });
$(".refresh_table").on('click', function(e) { $(".refresh_table").on('click', function(e) {
+1 -1
View File
@@ -1266,7 +1266,7 @@
"no_last_login": "Aucune dernière information de connexion à l'interface", "no_last_login": "Aucune dernière information de connexion à l'interface",
"no_record": "Pas d'enregistrement", "no_record": "Pas d'enregistrement",
"password": "Mot de passe", "password": "Mot de passe",
"password_now": "Mot de passe actuel (confirmer les changements)", "password_now": "Mot de passe courant (confirmer les changements)",
"password_repeat": "Mot de passe (répéter)", "password_repeat": "Mot de passe (répéter)",
"pushover_evaluate_x_prio": "Acheminement du courrier hautement prioritaire [<code>X-Priority: 1</code>]", "pushover_evaluate_x_prio": "Acheminement du courrier hautement prioritaire [<code>X-Priority: 1</code>]",
"pushover_info": "Les paramètres de notification push sappliqueront à tout le courrier propre (non spam) livré à <b>%s</b> y compris les alias (partagés, non partagés, étiquetés).", "pushover_info": "Les paramètres de notification push sappliqueront à tout le courrier propre (non spam) livré à <b>%s</b> y compris les alias (partagés, non partagés, étiquetés).",
+3 -7
View File
@@ -240,7 +240,7 @@
"generate": "Generuj", "generate": "Generuj",
"guid": "GUID - unikalny identyfikator instancji", "guid": "GUID - unikalny identyfikator instancji",
"guid_and_license": "GUID & licencja", "guid_and_license": "GUID & licencja",
"hash_remove_info": "Usunięcie hasha z limitem współczynnika (jeśli nadal istnieje) spowoduje całkowite zresetowanie jego licznika.<br> Każdy hash jest oznaczony indywidualnym kolorem.", "hash_remove_info": "Usunięcie hasha z limitem współczynnika (jeśli nadal istnieje) spowoduje całkowite zresetowanie jego licznika.<br>\n\n\n\n Każdy hash jest oznaczony indywidualnym kolorem.",
"help_text": "Zastąp tekst pomocy poniżej maski logowania (dozwolone HTML)", "help_text": "Zastąp tekst pomocy poniżej maski logowania (dozwolone HTML)",
"html": "HTML", "html": "HTML",
"iam": "Dostawca tożsamości", "iam": "Dostawca tożsamości",
@@ -683,11 +683,7 @@
"mailbox_rename_agree": "Stworzyłem kopię zapasową.", "mailbox_rename_agree": "Stworzyłem kopię zapasową.",
"mailbox_rename_warning": "WAŻNE! Utwórz kopię zapasową przed zmianą nazwy skrzynki pocztowej.", "mailbox_rename_warning": "WAŻNE! Utwórz kopię zapasową przed zmianą nazwy skrzynki pocztowej.",
"mailbox_rename_alias": "Tworzenie aliasów automatycznie", "mailbox_rename_alias": "Tworzenie aliasów automatycznie",
"mailbox_rename_title": "Nowa nazwa lokalnej skrzynki pocztowej", "mailbox_rename_title": "Nowa nazwa lokalnej skrzynki pocztowej"
"mbox_rl_info": "Ten limit szybkości dotyczy nazwy logowania SASL i odpowiada dowolnemu adresowi „from” używanemu przez zalogowanego użytkownika. Limit szybkości dla skrzynki pocztowej nadpisuje limit szybkości dla całej domeny.",
"nexthop": "Następny hop",
"private_comment": "Prywatny komentarz",
"public_comment": "Komentarz publiczny"
}, },
"footer": { "footer": {
"cancel": "Anuluj", "cancel": "Anuluj",
@@ -1079,7 +1075,7 @@
"spamfilter_table_remove": "Usuń", "spamfilter_table_remove": "Usuń",
"spamfilter_table_rule": "Zasada", "spamfilter_table_rule": "Zasada",
"spamfilter_wl": "Biała lista", "spamfilter_wl": "Biała lista",
"spamfilter_wl_desc": "Adresy e-mail znajdujące się na liście dozwolonych (allowlist) są zaprogramowane tak, aby <b> nigdy nie </b> były klasyfikowane jako spam. Można używać symboli wieloznacznych (wildcardów).Filtr jest stosowany wyłącznie do bezpośrednich aliasów (aliasów wskazujących na jedną skrzynkę pocztową), z wyłączeniem aliasów typu „catch-all” oraz samej skrzynki pocztowej", "spamfilter_wl_desc": "Adresy e-mail znajdujące się na liście dozwolonych (allowlist) są zaprogramowane tak, aby <b> nigdy nie </b> były klasyfikowane jako spam.\nMożna używać symboli wieloznacznych (wildcardów).\nFiltr jest stosowany wyłącznie do bezpośrednich aliasów (aliasów wskazujących na jedną skrzynkę pocztową), z wyłączeniem aliasów typu „catch-all” oraz samej skrzynki pocztowej",
"spamfilter_yellow": "Żółty: ta wiadomość może być spamem, zostanie oznaczona jako spam i przeniesiona do folderu spam", "spamfilter_yellow": "Żółty: ta wiadomość może być spamem, zostanie oznaczona jako spam i przeniesiona do folderu spam",
"sync_jobs": "Zadania synchronizacji", "sync_jobs": "Zadania synchronizacji",
"tag_handling": "Ustaw obsługę znaczników pocztowych", "tag_handling": "Ustaw obsługę znaczników pocztowych",
+1 -2
View File
@@ -340,8 +340,7 @@
"tls_policy": "Política de TLS", "tls_policy": "Política de TLS",
"quarantine_attachments": "Anexos de quarentena", "quarantine_attachments": "Anexos de quarentena",
"filters": "Filtros", "filters": "Filtros",
"smtp_ip_access": "Mudar anfitriões permitidos para SMTP", "smtp_ip_access": "Mudar anfitriões permitidos para SMTP"
"app_passwds": "Gerenciar senhas de aplicativos"
}, },
"warning": { "warning": {
"no_active_admin": "Não é possível desactivar o último administrador activo" "no_active_admin": "Não é possível desactivar o último administrador activo"
+1 -24
View File
@@ -7,30 +7,7 @@ if (!isset($_SERVER['HTTP_HOST']) || strpos($_SERVER['HTTP_HOST'], 'mta-sts.') !
} }
$host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']); $host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']);
$domain = idn_to_ascii(strtolower(str_replace('mta-sts.', '', $host)), 0, INTL_IDNA_VARIANT_UTS46); $domain = str_replace('mta-sts.', '', $host);
// Validate domain or return 404 on error
if ($domain === false || empty($domain)) {
http_response_code(404);
exit;
}
// Check if domain is an alias domain and resolve to target domain
try {
$stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain");
$stmt->execute(array(':domain' => $domain));
$alias_row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($alias_row !== false && !empty($alias_row['target_domain'])) {
// This is an alias domain, use the target domain for MTA-STS lookup
$domain = $alias_row['target_domain'];
}
} catch (PDOException $e) {
// On database error, return 404
http_response_code(404);
exit;
}
$mta_sts = mailbox('get', 'mta_sts', $domain); $mta_sts = mailbox('get', 'mta_sts', $domain);
if (count($mta_sts) == 0 || if (count($mta_sts) == 0 ||
+1 -1
View File
@@ -144,7 +144,7 @@
<form action="/" method="post" id="logout"><input type="hidden" name="logout"></form> <form action="/" method="post" id="logout"><input type="hidden" name="logout"></form>
{% if ui_texts.ui_announcement_text and ui_texts.ui_announcement_active and not is_root_uri and mailcow_cc_username %} {% if ui_texts.ui_announcement_text and ui_texts.ui_announcement_active and not is_root_uri %}
<div class="container mt-4"> <div class="container mt-4">
<div class="alert alert-{{ ui_texts.ui_announcement_type }}">{{ ui_texts.ui_announcement_text }}</div> <div class="alert alert-{{ ui_texts.ui_announcement_type }}">{{ ui_texts.ui_announcement_text }}</div>
</div> </div>
+2 -3
View File
@@ -84,7 +84,7 @@ services:
- clamd - clamd
rspamd-mailcow: rspamd-mailcow:
image: ghcr.io/mailcow/rspamd:3.14.2 image: ghcr.io/mailcow/rspamd:3.14.1
stop_grace_period: 30s stop_grace_period: 30s
depends_on: depends_on:
- dovecot-mailcow - dovecot-mailcow
@@ -97,7 +97,6 @@ services:
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-} - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
- REDISPASS=${REDISPASS} - REDISPASS=${REDISPASS}
- SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-} - SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-}
- RSPAMD_SKIP_CLAMD=${SKIP_CLAMD:-n}
volumes: volumes:
- ./data/hooks/rspamd:/hooks:Z - ./data/hooks/rspamd:/hooks:Z
- ./data/conf/rspamd/custom/:/etc/rspamd/custom:z - ./data/conf/rspamd/custom/:/etc/rspamd/custom:z
@@ -466,7 +465,7 @@ services:
condition: service_started condition: service_started
unbound-mailcow: unbound-mailcow:
condition: service_healthy condition: service_healthy
image: ghcr.io/mailcow/acme:1.95 image: ghcr.io/mailcow/acme:1.94
dns: dns:
- ${IPV4_NETWORK:-172.22.1}.254 - ${IPV4_NETWORK:-172.22.1}.254
environment: environment: