Compare commits

...

16 Commits

Author SHA1 Message Date
FreddleSpl0it 54170d075a [Web] Move mailcow update check to server side 2026-07-28 13:32:18 +02:00
FreddleSpl0it 4b62af9d02 update README.md sponsors 2026-07-15 08:29:46 +02:00
FreddleSpl0it c1d75cf808 Merge pull request #7312 from mailcow/renovate/composer-composer-2.x
Update dependency composer/composer to v2.10.2
2026-07-13 09:40:58 +02:00
FreddleSpl0it 473fe2885d Merge pull request #7326 from ralfbergs/fix/quarantine-text-refining
Refined wording for displaying of active settings on quarantine page.
2026-07-13 09:40:24 +02:00
FreddleSpl0it 31e1550668 [Postfix] change postscreen blacklist_action to denylist_action 2026-07-13 08:45:56 +02:00
FreddleSpl0it 315f55bc65 Merge pull request #7323 from DerLinkman/feat/postfix-deb13
postfix: migrate from bookworm to trixie
2026-07-13 08:23:57 +02:00
Ralf Bergs e696ee2f6c Refined wording for displaying of active settings on quarantine page. 2026-07-12 17:22:15 +02:00
renovate[bot] d65aa11870 Update devops-infra/action-pull-request action to v1.4.0 (#7321)
Signed-off-by: milkmaker <milkmaker@mailcow.de>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-12 15:20:18 +02:00
renovate[bot] f6630e5b43 Update actions/stale action to v10.4.0 (#7322)
Signed-off-by: milkmaker <milkmaker@mailcow.de>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-12 15:19:49 +02:00
DerLinkman 98e26c5603 compose: upgrade Postfix 2026-07-10 18:41:58 +02:00
DerLinkman 3098caebbc migrate postfix to trixie 2026-07-10 18:29:45 +02:00
renovate[bot] 94e23a3cd3 Update dependency composer/composer to v2.10.2
Signed-off-by: milkmaker <milkmaker@mailcow.de>
2026-07-01 09:32:23 +00:00
milkmaker 1840074991 update postscreen_access.cidr (#7311) 2026-07-01 11:31:58 +02:00
FreddleSpl0it 99768e16f5 Merge pull request #7305 from mailcow/feat/nginx-1.30.3
[Nignx] Update to 1.30.3
2026-06-25 12:20:25 +02:00
FreddleSpl0it 1f8b4679cc [Nignx] Update to 1.30.3 2026-06-25 12:17:37 +02:00
milkmaker 9e723e942d Translations update from Weblate (#7302)
* [Web] Updated lang.fr-fr.json

Co-authored-by: Romain Ayme <ayme.romain@hotmail.fr>

* [Web] Updated lang.si-si.json

Co-authored-by: Matjaž Tekavec <matjaz@moj-svet.si>

---------

Co-authored-by: Romain Ayme <ayme.romain@hotmail.fr>
Co-authored-by: Matjaž Tekavec <matjaz@moj-svet.si>
2026-06-20 13:57:15 +02:00
18 changed files with 135 additions and 62 deletions
@@ -14,7 +14,7 @@ jobs:
pull-requests: write
steps:
- name: Mark/Close Stale Issues and Pull Requests 🗑️
uses: actions/stale@v10.3.0
uses: actions/stale@v10.4.0
with:
repo-token: ${{ secrets.STALE_ACTION_PAT }}
days-before-stale: 60
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
with:
fetch-depth: 0
- name: Run the Action
uses: devops-infra/action-pull-request@v1.3.0
uses: devops-infra/action-pull-request@v1.4.0
with:
github_token: ${{ secrets.PRTONIGHTLY_ACTION_PAT }}
title: Automatic PR to nightly from ${{ github.event.repository.updated_at}}
+3
View File
@@ -23,6 +23,9 @@ A big thank you to everyone supporting us on GitHub Sponsors—your contribution
<a href="https://www.maehdros.com/" target=_blank><img
src="https://avatars.githubusercontent.com/u/173894712" height="58"
/></a>
<a href="https://garske-systems.de/" target=_blank><img
src="https://garske-systems.de/img/logo_min.png" height="58"
/></a>
### 50$/Month Sponsors
<a href="https://github.com/vnukhr" target=_blank><img
+1 -1
View File
@@ -1,4 +1,4 @@
FROM nginx:1.30.2-alpine
FROM nginx:1.30.3-alpine
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
ENV PIP_BREAK_SYSTEM_PACKAGES=1
+1 -1
View File
@@ -13,7 +13,7 @@ ARG MEMCACHED_PECL_VERSION=3.4.0
# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=(?<version>.*)$
ARG REDIS_PECL_VERSION=6.3.0
# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=(?<version>.*)$
ARG COMPOSER_VERSION=2.10.1
ARG COMPOSER_VERSION=2.10.2
RUN apk add -U --no-cache autoconf \
aspell-dev \
+1 -1
View File
@@ -1,4 +1,4 @@
FROM debian:bookworm-slim
FROM debian:trixie-slim
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
@@ -1,4 +1,4 @@
@version: 3.38
@version: 4.8
@include "scl.conf"
options {
chain_hostnames(off);
@@ -7,7 +7,7 @@ options {
dns_cache(no);
use_fqdn(no);
owner("root"); group("adm"); perm(0640);
stats_freq(0);
stats(freq(0));
bad_hostname("^gconfd$");
};
source s_src {
+2 -2
View File
@@ -1,4 +1,4 @@
@version: 3.38
@version: 4.8
@include "scl.conf"
options {
chain_hostnames(off);
@@ -7,7 +7,7 @@ options {
dns_cache(no);
use_fqdn(no);
owner("root"); group("adm"); perm(0640);
stats_freq(0);
stats(freq(0));
bad_hostname("^gconfd$");
};
source s_src {
+1 -3
View File
@@ -37,7 +37,7 @@ postscreen_access_list = permit_mynetworks,
cidr:/opt/postfix/conf/postscreen_access.cidr,
tcp:127.0.0.1:10027
postscreen_bare_newline_enable = no
postscreen_blacklist_action = drop
postscreen_denylist_action = drop
postscreen_cache_cleanup_interval = 24h
postscreen_cache_map = proxy:btree:$data_directory/postscreen_cache
postscreen_dnsbl_action = enforce
@@ -107,8 +107,6 @@ smtpd_sender_restrictions = reject_authenticated_sender_login_mismatch,
reject_unknown_sender_domain
smtpd_soft_error_limit = 3
smtpd_tls_auth_only = yes
smtpd_tls_dh1024_param_file = /etc/ssl/mail/dhparams.pem
smtpd_tls_eecdh_grade = auto
smtpd_tls_exclude_ciphers = ECDHE-RSA-RC4-SHA, RC4, aNULL, DES-CBC3-SHA, ECDHE-RSA-DES-CBC3-SHA, EDH-RSA-DES-CBC3-SHA
smtpd_tls_loglevel = 1
-2
View File
@@ -29,7 +29,6 @@ smtps inet n - n - - smtpd
# TLS protocol can be modified by setting submission_smtpd_tls_mandatory_protocols in extra.cf
submission inet n - n - - smtpd
-o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
-o smtpd_enforce_tls=yes
-o smtpd_tls_security_level=encrypt
-o smtpd_tls_mandatory_protocols=$submission_smtpd_tls_mandatory_protocols
-o tls_preempt_cipherlist=yes
@@ -38,7 +37,6 @@ submission inet n - n - - smtpd
10587 inet n - n - - smtpd
-o smtpd_upstream_proxy_protocol=haproxy
-o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
-o smtpd_enforce_tls=yes
-o smtpd_tls_security_level=encrypt
-o smtpd_tls_mandatory_protocols=$submission_smtpd_tls_mandatory_protocols
-o tls_preempt_cipherlist=yes
+14 -4
View File
@@ -1,6 +1,6 @@
# Whitelist generated by Postwhite v3.4 on Mon Jun 1 00:52:17 UTC 2026
# Whitelist generated by Postwhite v3.4 on Wed Jul 1 00:51:20 UTC 2026
# https://github.com/stevejenkins/postwhite/
# 2186 total rules
# 2251 total rules
2a00:1450:4000::/36 permit
2a00:1450:4864::/56 permit
2a01:111:f400::/48 permit
@@ -1528,7 +1528,7 @@
149.97.173.180 permit
149.118.160.128/25 permit
150.136.21.199 permit
150.171.109.118 permit
150.171.109.183 permit
150.230.98.160 permit
151.145.38.14 permit
152.67.105.195 permit
@@ -1605,6 +1605,12 @@
164.152.25.241 permit
164.177.132.168/30 permit
165.1.100.0/25 permit
165.173.128.0/24 permit
165.173.180.0/24 permit
165.173.180.250/31 permit
165.173.182.0/24 permit
165.173.182.250/31 permit
165.173.189.205 permit
166.78.68.0/22 permit
166.78.68.221 permit
166.78.69.169 permit
@@ -1651,6 +1657,7 @@
173.203.81.39 permit
173.224.161.128/25 permit
173.224.165.0/26 permit
173.224.166.48/28 permit
174.36.84.8/29 permit
174.36.84.16/29 permit
174.36.84.32/29 permit
@@ -2171,7 +2178,10 @@
2001:748:400:3301::4 permit
2404:6800:4000::/36 permit
2404:6800:4864::/56 permit
2603:1061:14:40::1 permit
2603:1061:14:1c2::1 permit
2607:13c0:0001:0000:0000:0000:0000:7000/116 permit
2607:13c0:0002:0000:0000:0000:0000:1000/116 permit
2607:13c0:0004:0000:0000:0000:0000:0000/116 permit
2607:f8b0:4000::/36 permit
2607:f8b0:4864::/56 permit
2620:109:c003:104::/64 permit
+67
View File
@@ -0,0 +1,67 @@
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
header('Content-Type: application/json');
// Admins only
if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] !== 'admin') {
http_response_code(403);
echo json_encode(array('status' => 'error', 'message' => 'access denied'));
exit;
}
$owner = $GLOBALS['MAILCOW_GIT_OWNER'];
$repo = $GLOBALS['MAILCOW_GIT_REPO'];
$current = $GLOBALS['MAILCOW_GIT_VERSION'];
// Cache key is bound to the running version, so an update invalidates it naturally
$cache_key = 'MAILCOW_UPDATE_CHECK/' . $current;
// Serve cached result if present (one GitHub call per TTL, not one per page load)
$cached = $redis->get($cache_key);
if ($cached !== false) {
echo $cached;
exit;
}
// GitHub requires a User-Agent and rate-limits unauthenticated requests to 60/h per IP
function github_get($url) {
$ch = curl_init($url);
curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERAGENT => 'mailcow-update-check',
CURLOPT_TIMEOUT => 10,
CURLOPT_HTTPHEADER => array('Accept: application/vnd.github+json'),
));
$body = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($body === false || $code !== 200) return false;
$json = json_decode($body, true);
return is_array($json) ? $json : false;
}
$latest = github_get("https://api.github.com/repos/{$owner}/{$repo}/releases/latest");
$release = github_get("https://api.github.com/repos/{$owner}/{$repo}/releases/tags/{$current}");
// Any failure (rate limit, offline, unexpected payload) -> honest error, cached briefly
if ($latest === false || $release === false ||
empty($latest['tag_name']) || empty($latest['created_at']) || empty($release['created_at'])) {
$result = json_encode(array('status' => 'error', 'message' => 'could not reach GitHub API'));
$redis->setex($cache_key, 300, $result);
echo $result;
exit;
}
$date_latest = strtotime($latest['created_at']);
$date_current = strtotime($release['created_at']);
if ($date_latest <= $date_current) {
$result = json_encode(array('status' => 'no_update'));
} else {
$result = json_encode(array('status' => 'update_available', 'latest_tag' => $latest['tag_name']));
}
// Cache the positive result for an hour
$redis->setex($cache_key, 3600, $result);
echo $result;
+18 -33
View File
@@ -30,7 +30,7 @@ $(document).ready(function() {
// create host cpu and mem charts
createHostCpuAndMemChart();
// check for new version
if (mailcow_info.branch === "master"){
if (mailcow_info.branch === "master" && mailcow_cc_role === "admin"){
check_update(mailcow_info.version_tag, mailcow_info.project_url);
}
$("#mailcow_version").click(function(){
@@ -1669,41 +1669,26 @@ function createHostCpuAndMemChart(){
function check_update(current_version, github_repo_url){
if (!current_version || !github_repo_url) return false;
var github_account = github_repo_url.split("/")[3];
var github_repo_name = github_repo_url.split("/")[4];
// get details about latest release
window.fetch("https://api.github.com/repos/"+github_account+"/"+github_repo_name+"/releases/latest", {method:'GET',cache:'no-cache'}).then(function(response) {
window.fetch("/inc/ajax/update_check.php", {method:'GET',cache:'no-cache'}).then(function(response) {
if (!response.ok) throw new Error("update check returned " + response.status);
return response.json();
}).then(function(latest_data) {
// get details about current release
window.fetch("https://api.github.com/repos/"+github_account+"/"+github_repo_name+"/releases/tags/"+current_version, {method:'GET',cache:'no-cache'}).then(function(response) {
return response.json();
}).then(function(current_data) {
// compare releases
var date_current = new Date(current_data.created_at);
var date_latest = new Date(latest_data.created_at);
if (date_latest.getTime() <= date_current.getTime()){
// no update available
$("#mailcow_update").removeClass("text-warning text-danger").addClass("text-success");
$("#mailcow_update").html("<b>" + lang_debug.no_update_available + "</b>");
} else {
// update available
$("#mailcow_update").removeClass("text-danger text-success").addClass("text-warning");
$("#mailcow_update").html(lang_debug.update_available + ` <a href="#" id="mailcow_update_changelog">`+latest_data.tag_name+`</a>`);
$("#mailcow_update_changelog").click(function(){
if (mailcow_cc_role !== "admin" && mailcow_cc_role !== "domainadmin")
return;
}).then(function(data) {
if (data.status === "no_update") {
$("#mailcow_update").removeClass("text-warning text-danger").addClass("text-success");
$("#mailcow_update").html("<b>" + lang_debug.no_update_available + "</b>");
} else if (data.status === "update_available") {
$("#mailcow_update").removeClass("text-danger text-success").addClass("text-warning");
$("#mailcow_update").html(lang_debug.update_available + ` <a href="#" id="mailcow_update_changelog">`+data.latest_tag+`</a>`);
$("#mailcow_update_changelog").click(function(){
if (mailcow_cc_role !== "admin" && mailcow_cc_role !== "domainadmin")
return;
showVersionModal("New Release " + latest_data.tag_name, latest_data.tag_name);
})
}
}).catch(err => {
// err
console.log(err);
$("#mailcow_update").removeClass("text-success text-warning").addClass("text-danger");
$("#mailcow_update").html("<b>"+ lang_debug.update_failed +"</b>");
});
showVersionModal("New Release " + data.latest_tag, data.latest_tag);
})
} else {
throw new Error(data.message || "update check failed");
}
}).catch(err => {
// err
console.log(err);
+1 -1
View File
@@ -1086,7 +1086,7 @@
"rspamd_result": "Rspamd-Ergebnis",
"sender": "Sender (SMTP)",
"sender_header": "Sender (\"From\"-Header)",
"settings_info": "Maximale Anzahl der zurückgehaltenen E-Mails: %s<br>Maximale Größe einer zu speichernden E-Mail: %s MiB",
"settings_info": "Maximale Anzahl der zurückgehaltenen E-Mails (pro Mailbox): %s<br>Maximale Größe einer zu speichernden E-Mail: %s MiB",
"show_item": "Details",
"spam": "Spam",
"spam_score": "Bewertung",
+1 -1
View File
@@ -1087,7 +1087,7 @@
"rspamd_result": "Rspamd result",
"sender": "Sender (SMTP)",
"sender_header": "Sender (\"From\" header)",
"settings_info": "Maximum amount of elements to be quarantined: %s<br>Maximum email size: %s MiB",
"settings_info": "Maximum amount of elements to be quarantined (per mailbox): %s<br>Maximum email size: %s MiB",
"show_item": "Show item",
"spam": "Spam",
"spam_score": "Score",
+17 -6
View File
@@ -111,7 +111,8 @@
"app_passwd_protocols": "Protocoles autorisés pour le mot de passe de l'application",
"dry": "Simuler la synchronisation",
"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": {
"access": "Accès",
@@ -556,7 +557,9 @@
"max_age_invalid": "L'âge maximum %s est invalide",
"mode_invalid": "Le mode %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": {
"chart_this_server": "Graphique (ce serveur)",
@@ -755,7 +758,9 @@
"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_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": {
"cancel": "Annuler",
@@ -988,7 +993,8 @@
"recipient": "Destinataire",
"open_logs": "Afficher les journaux",
"iam": "Fournisseur d'identité",
"internal": "Interne"
"internal": "Interne",
"force_tfa": "TFA"
},
"oauth2": {
"access_denied": "Veuillez vous connecter en tant que propriétaire de la boîte de réception pour accorder laccès via Oauth2.",
@@ -1189,7 +1195,11 @@
"yubi_otp": "Authentification OTP Yubico",
"authenticators": "Authentificateurs",
"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": {
"set_fn": "Définir un nom",
@@ -1378,7 +1388,8 @@
"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é.",
"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": {
"cannot_delete_self": "Impossible de supprimer lutilisateur connecté",
+2 -1
View File
@@ -1001,7 +1001,8 @@
"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",
"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": {
"known_ids": "Znani ID-ji",
+2 -2
View File
@@ -339,7 +339,7 @@ services:
- dovecot
postfix-mailcow:
image: ghcr.io/mailcow/postfix:3.7.11-2
image: ghcr.io/mailcow/postfix:3.10.12-1
depends_on:
mysql-mailcow:
condition: service_started
@@ -419,7 +419,7 @@ services:
- php-fpm-mailcow
- sogo-mailcow
- rspamd-mailcow
image: ghcr.io/mailcow/nginx:1.30.2-1
image: ghcr.io/mailcow/nginx:1.30.3-1
dns:
- ${IPV4_NETWORK:-172.22.1}.254
environment: