浏览代码

Merge pull request #6419 from mailcow/staging

Update 2025-03a
FreddleSpl0it 5 月之前
父节点
当前提交
2c47145dee

+ 2 - 2
data/Dockerfiles/dockerapi/main.py

@@ -241,9 +241,9 @@ async def handle_pubsub_messages(channel: aioredis.client.PubSub):
               else:
                 dockerapi.logger.error("api call: missing container_name, post_action or request")
             else:
-              dockerapi.logger.error("Unknwon PubSub recieved - %s" % json.dumps(data_json))
+              dockerapi.logger.error("Unknown PubSub received - %s" % json.dumps(data_json))
           else:
-            dockerapi.logger.error("Unknwon PubSub recieved - %s" % json.dumps(data_json))
+            dockerapi.logger.error("Unknown PubSub received - %s" % json.dumps(data_json))
 
         await asyncio.sleep(0.0)
     except asyncio.TimeoutError:

+ 11 - 11
data/Dockerfiles/watchdog/check_mysql_slavestatus.sh

@@ -49,7 +49,7 @@
 # 2013101601 Optical clean up                                           #
 # 2013101602 Rewrite help output                                        #
 # 2013101700 Handle Slave IO in 'Connecting' state                      #
-# 2013101701 Minor changes in output, handling UNKWNON situations now   #
+# 2013101701 Minor changes in output, handling UNKNOWN situations now   #
 # 2013101702 Exit CRITICAL when Slave IO in Connecting state            #
 # 2013123000 Slave_SQL_Running also matched Slave_SQL_Running_State     #
 # 2015011600 Added 'moving' check to catch possible connection issues   #
@@ -131,7 +131,7 @@ elif [[ -n "${socket}" && (-z "${user}" || -z "${password}") ]]; then
 fi
 
 # Connect to the DB server and store output in vars
-if [[ -n $socket ]]; then 
+if [[ -n $socket ]]; then
   ConnectionResult=$(mariadb --skip-ssl ${optfile} ${socket} ${user} -e "show slave ${connection} status\G" 2>&1)
 else
   ConnectionResult=$(mariadb --skip-ssl ${optfile} ${host} ${port} ${user} -e "show slave ${connection} status\G" 2>&1)
@@ -178,33 +178,33 @@ if [ ${check} = ${ok} ] && [ ${checkio} = ${ok} ]; then
   then echo "CRITICAL: Slave is ${delayinfo} seconds behind Master | delay=${delayinfo}s"; exit ${STATE_CRITICAL}
   elif [[ ${delayinfo} -ge ${warn_delay} ]]
   then echo "WARNING: Slave is ${delayinfo} seconds behind Master | delay=${delayinfo}s"; exit ${STATE_WARNING}
-  else 
+  else
     # Everything looks OK here but now let us check if the replication is moving
     if [[ -n ${moving} ]] && [[ -n ${tmpfile} ]] && [[ $readpos -eq $execpos ]]
-    then  
-      #echo "Debug: Read pos is $readpos - Exec pos is $execpos" 
+    then
+      #echo "Debug: Read pos is $readpos - Exec pos is $execpos"
       # Check if tmp file exists
       curtime=`date +%s`
-      if [[ -w $tmpfile ]] 
-      then 
+      if [[ -w $tmpfile ]]
+      then
         tmpfiletime=`date +%s -r $tmpfile`
         if [[ `expr $curtime - $tmpfiletime` -gt ${moving} ]]
         then
           exectmp=`cat $tmpfile`
           #echo "Debug: Exec pos in tmpfile is $exectmp"
           if [[ $exectmp -eq $execpos ]]
-          then 
+          then
             # The value read from the tmp file and from db are the same. Replication hasnt moved!
             echo "WARNING: Slave replication has not moved in ${moving} seconds. Manual check required."; exit ${STATE_WARNING}
-          else 
+          else
             # Replication has moved since the tmp file was written. Delete tmp file and output OK.
             rm $tmpfile
             echo "OK: Slave SQL running: ${check} Slave IO running: ${checkio} / master: ${masterinfo} / slave is ${delayinfo} seconds behind master | delay=${delayinfo}s"; exit ${STATE_OK};
           fi
-        else 
+        else
           echo "OK: Slave SQL running: ${check} Slave IO running: ${checkio} / master: ${masterinfo} / slave is ${delayinfo} seconds behind master | delay=${delayinfo}s"; exit ${STATE_OK};
         fi
-      else 
+      else
         echo "$execpos" > $tmpfile
         echo "OK: Slave SQL running: ${check} Slave IO running: ${checkio} / master: ${masterinfo} / slave is ${delayinfo} seconds behind master | delay=${delayinfo}s"; exit ${STATE_OK};
       fi

+ 2 - 2
data/conf/nginx/templates/nginx.conf.j2

@@ -182,6 +182,8 @@ http {
         }
     }
 
+    include /etc/nginx/conf.d/*.conf;
+
     {% for cert in valid_cert_dirs %}
     server {
         {% if not HTTP_REDIRECT %}
@@ -206,6 +208,4 @@ http {
         include /etc/nginx/includes/sites-default.conf;
     }
     {% endfor %}
-
-    include /etc/nginx/conf.d/*.conf;
 }

+ 2 - 2
data/conf/phpfpm/crons/keycloak-sync.php

@@ -130,7 +130,7 @@ while (true) {
   curl_close($ch);
 
   if ($code != 200){
-    logMsg("err", "Recieved HTTP {$code}");
+    logMsg("err", "Received HTTP {$code}");
     session_destroy();
     exit;
   }
@@ -141,7 +141,7 @@ while (true) {
     break;
   }
   if (!is_array($response)){
-    logMsg("err", "Recieved malformed response from keycloak api");
+    logMsg("err", "Received malformed response from keycloak api");
     break;
   }
   if (count($response) == 0) {

+ 2 - 1
data/web/api/openapi.yaml

@@ -346,7 +346,8 @@ paths:
                   description: the domain which emails should be forwarded
                   type: string
                 type:
-                  description: the type of bcc map can be `sender` or `recipient`
+                  description: the type of bcc map can be `sender` or `rcpt`
+                  enum: [sender, rcpt]
                   type: string
               type: object
       summary: Create BCC Map

文件差异内容过多而无法显示
+ 0 - 0
data/web/css/build/007-languages.min.css


+ 10 - 7
data/web/inc/functions.inc.php

@@ -1385,6 +1385,7 @@ function fido2($_data) {
       );
     break;
     case "verify":
+      $role = "";
       $tokenData = json_decode($_data['token']);
       $clientDataJSON = base64_decode($tokenData->clientDataJSON);
       $authenticatorData = base64_decode($tokenData->authenticatorData);
@@ -1418,17 +1419,17 @@ function fido2($_data) {
       $stmt->execute(array(':username' => $process_fido2['username']));
       $obj_props = $stmt->fetch(PDO::FETCH_ASSOC);
       if ($obj_props['superadmin'] === 1 && (!$_data['user'] || $_data['user'] == "admin")) {
-        $_SESSION["mailcow_cc_role"] = "admin";
+        $role = "admin";
       }
       elseif ($obj_props['superadmin'] === 0 && (!$_data['user'] || $_data['user'] == "domainadmin")) {
-        $_SESSION["mailcow_cc_role"] = "domainadmin";
+        $role = "domainadmin";
       }
       elseif (!isset($obj_props['superadmin']) && (!$_data['user'] || $_data['user'] == "user")) {
         $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :username");
         $stmt->execute(array(':username' => $process_fido2['username']));
         $row = $stmt->fetch(PDO::FETCH_ASSOC);
         if ($row['username'] == $process_fido2['username']) {
-          $_SESSION["mailcow_cc_role"] = "user";
+          $role = "user";
         }
       }
       else {
@@ -1439,7 +1440,7 @@ function fido2($_data) {
         );
         return false;
       }
-      if (empty($_SESSION["mailcow_cc_role"])) {
+      if (empty($role)) {
         session_unset();
         session_destroy();
         $_SESSION['return'][] =  array(
@@ -1449,15 +1450,17 @@ function fido2($_data) {
         );
         return false;
       }
-      $_SESSION["mailcow_cc_username"] = $process_fido2['username'];
-      $_SESSION["fido2_cid"] = $process_fido2['cid'];
       unset($_SESSION["challenge"]);
       $_SESSION['return'][] =  array(
         'type' => 'success',
         'log' => array("fido2_login", $_data['user'], $process_fido2['username']),
         'msg' => array('logged_in_as', $process_fido2['username'])
       );
-      return true;
+      return array(
+        "role" => $role,
+        "username" => $process_fido2['username'],
+        "cid" => $process_fido2['cid']
+      );
     break;
   }
 }

+ 1 - 1
data/web/inc/functions.mailbox.inc.php

@@ -3324,7 +3324,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
           }
 
           $is_now = mailbox('get', 'mailbox_details', $old_username);
-          if (empty($is_now)) {
+          if (empty($is_now) || ($is_now['active'] != '1' && $is_now['active'] != '2')) {
             $_SESSION['return'][] = array(
               'type' => 'danger',
               'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),

+ 6 - 1
data/web/inc/triggers.admin.inc.php

@@ -19,11 +19,16 @@ if (isset($_POST["verify_tfa_login"])) {
   unset($_SESSION['pending_tfa_methods']);
 }
 if (isset($_POST["verify_fido2_login"])) {
-  fido2(array(
+  $res = fido2(array(
     "action" => "verify",
     "token" => $_POST["token"],
     "user" => "admin"
   ));
+  if (is_array($res) && $res['role'] == "admin" && !empty($res['username'])){
+    $_SESSION["mailcow_cc_username"] = $res['username'];
+    $_SESSION["mailcow_cc_role"] = $res['role'];
+    $_SESSION["fido2_cid"] = $res['cid'];
+  }
   exit;
 }
 

+ 6 - 1
data/web/inc/triggers.domainadmin.inc.php

@@ -30,11 +30,16 @@ if (isset($_POST["verify_tfa_login"])) {
   unset($_SESSION['pending_tfa_methods']);
 }
 if (isset($_POST["verify_fido2_login"])) {
-  fido2(array(
+  $res = fido2(array(
     "action" => "verify",
     "token" => $_POST["token"],
     "user" => "domainadmin"
   ));
+  if (is_array($res) && $res['role'] == "domainadmin" && !empty($res['username'])){
+    $_SESSION["mailcow_cc_username"] = $res['username'];
+    $_SESSION["mailcow_cc_role"] = $res['role'];
+    $_SESSION["fido2_cid"] = $res['cid'];
+  }
   exit;
 }
 

+ 20 - 2
data/web/inc/triggers.user.inc.php

@@ -21,7 +21,7 @@ if ($iam_provider){
     }
   } elseif ($_GET['code'] && $_GET['state'] === $_SESSION['oauth2state']) {
     // Check given state against previously stored one to mitigate CSRF attack
-    // Recieved access token in $_GET['code']
+    // Received access token in $_GET['code']
     // extract info and verify user
     identity_provider('verify-sso');
   }
@@ -66,6 +66,14 @@ if (isset($_POST["verify_tfa_login"])) {
         die();
       } else {
         set_user_loggedin_session($_SESSION['pending_mailcow_cc_username']);
+
+        if (isset($_SESSION['oauth2_request'])) {
+          $oauth2_request = $_SESSION['oauth2_request'];
+          unset($_SESSION['oauth2_request']);
+          header('Location: ' . $oauth2_request);
+          die();
+        }
+
         $user_details = mailbox("get", "mailbox_details", $_SESSION['mailcow_cc_username']);
         $is_dual = (!empty($_SESSION["dual-login"]["username"])) ? true : false;
         if (intval($user_details['attributes']['sogo_access']) == 1 && !$is_dual) {
@@ -84,11 +92,15 @@ if (isset($_POST["verify_tfa_login"])) {
   unset($_SESSION['pending_tfa_methods']);
 }
 if (isset($_POST["verify_fido2_login"])) {
-  fido2(array(
+  $res = fido2(array(
     "action" => "verify",
     "token" => $_POST["token"],
     "user" => "user"
   ));
+  if (is_array($res) && $res['role'] == "user" && !empty($res['username'])){
+    set_user_loggedin_session($res['username']);
+    $_SESSION["fido2_cid"] = $res['cid'];
+  }
   exit;
 }
 
@@ -118,6 +130,12 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) {
         header("Location: /mobileconfig.php");
         die();
     }
+    if (isset($_SESSION['oauth2_request'])) {
+      $oauth2_request = $_SESSION['oauth2_request'];
+      unset($_SESSION['oauth2_request']);
+      header('Location: ' . $oauth2_request);
+      die();
+    }
 
     $user_details = mailbox("get", "mailbox_details", $login_user);
     $is_dual = (!empty($_SESSION["dual-login"]["username"])) ? true : false;

+ 2 - 2
data/web/lang/lang.en-gb.json

@@ -624,7 +624,7 @@
         "alias": "Edit alias",
         "allow_from_smtp": "Only allow these IPs to use <b>SMTP</b>",
         "allow_from_smtp_info": "Leave empty to allow all senders.<br>IPv4/IPv6 addresses and networks.",
-        "allowed_protocols": "Allowed protocols",
+        "allowed_protocols": "Allowed protocols for direct user access (does not affect app password protocols)",
         "app_name": "App name",
         "app_passwd": "App password",
         "app_passwd_protocols": "Allowed protocols for app password",
@@ -844,7 +844,7 @@
         "all_domains": "All Domains",
         "allow_from_smtp": "Only allow these IPs to use <b>SMTP</b>",
         "allow_from_smtp_info": "Leave empty to allow all senders.<br>IPv4/IPv6 addresses and networks.",
-        "allowed_protocols": "Allowed protocols for direct user access (does not affect app password protocols)",
+        "allowed_protocols": "Allowed protocols",
         "backup_mx": "Relay domain",
         "bcc": "BCC",
         "bcc_destination": "BCC destination",

+ 2 - 2
data/web/lang/lang.ja-jp.json

@@ -581,7 +581,7 @@
         "alias": "エイリアスを編集",
         "allow_from_smtp": "<b>SMTP</b>を使用するこれらのIPのみを許可",
         "allow_from_smtp_info": "すべての送信者を許可するには空欄にしてください。<br>IPv4/IPv6アドレスおよびネットワークを指定できます。",
-        "allowed_protocols": "許可されたプロトコル",
+        "allowed_protocols": "直接ユーザーアクセスで許可されるプロトコル(アプリパスワードプロトコルには影響しません)",
         "app_name": "アプリ名",
         "app_passwd": "アプリパスワード",
         "app_passwd_protocols": "アプリパスワードで許可されるプロトコル",
@@ -798,7 +798,7 @@
         "all_domains": "すべてのドメイン",
         "allow_from_smtp": "<b>SMTP</b>を使用するこれらのIPのみを許可",
         "allow_from_smtp_info": "すべての送信者を許可するには空欄にしてください。<br>IPv4/IPv6アドレスおよびネットワークを指定可能。",
-        "allowed_protocols": "直接ユーザーアクセスで許可されるプロトコル(アプリパスワードプロトコルには影響しません)",
+        "allowed_protocols": "許可されたプロトコル",
         "backup_mx": "リレードメイン",
         "bcc": "BCC",
         "bcc_destination": "BCC送信先",

+ 2 - 2
data/web/lang/lang.pt-br.json

@@ -581,7 +581,7 @@
         "alias": "Editar alias",
         "allow_from_smtp": "<b>Permita que esses IPs usem apenas SMTP</b>",
         "allow_from_smtp_info": "Deixe em branco para permitir todos os remetentes. Endereços e <br>redes IPv4/IPv6.",
-        "allowed_protocols": "Protocolos permitidos",
+        "allowed_protocols": "Protocolos permitidos para acesso direto do usuário (não afeta os protocolos de senha do aplicativo)",
         "app_name": "Nome do aplicativo",
         "app_passwd": "Senha do aplicativo",
         "app_passwd_protocols": "Protocolos permitidos para a senha do aplicativo",
@@ -793,7 +793,7 @@
         "all_domains": "Todos os domínios",
         "allow_from_smtp": "<b>Permita que esses IPs usem apenas SMTP</b>",
         "allow_from_smtp_info": "Deixe em branco para permitir todos os remetentes. Endereços e <br>redes IPv4/IPv6.",
-        "allowed_protocols": "Protocolos permitidos para acesso direto do usuário (não afeta os protocolos de senha do aplicativo)",
+        "allowed_protocols": "Protocolos permitidos",
         "backup_mx": "Domínio de retransmissão",
         "bcc": "BCC",
         "bcc_destination": "Destino BCC",

+ 2 - 2
data/web/lang/lang.tr-tr.json

@@ -482,7 +482,7 @@
         "sender_acl_disabled": "<span class=\\\"label label-danger\\\">Gönderen denetimi devre dışı</span>",
         "allow_from_smtp": "Yalnızca bu IP'lerin <b>SMTP</b> kullanmasına izin verin",
         "allow_from_smtp_info": "Tüm gönderenlere izin vermek için boş bırakın.<br>IPv4/IPv6 adresleri ve ağları.",
-        "allowed_protocols": "İzin verilen protokoller",
+        "allowed_protocols": "Doğrudan kullanıcı erişimi için izin verilen protokoller (uygulama parola protokollerini etkilemez)",
         "app_name": "Uygulama adı",
         "app_passwd": "Uygulama şifresi",
         "app_passwd_protocols": "Uygulama şifresi için izin verilen protokoller",
@@ -782,7 +782,7 @@
         "aliases": "Takma Adlar",
         "all_domains": "Tüm Alan Adları",
         "allow_from_smtp": "Yalnızca bu IP'lerin <b>SMTP</b> kullanmasına izin verin",
-        "allowed_protocols": "Doğrudan kullanıcı erişimi için izin verilen protokoller (uygulama parola protokollerini etkilemez)",
+        "allowed_protocols": "İzin verilen protokoller",
         "backup_mx": "Geçiş alanı",
         "bcc": "BCC",
         "bcc_destination": "Gizli hedef",

+ 2 - 2
data/web/lang/lang.zh-cn.json

@@ -554,7 +554,7 @@
         "alias": "编辑别名",
         "allow_from_smtp": "只允许这些 IP 使用 <b>SMTP</b>",
         "allow_from_smtp_info": "留空以允许所有发送者。<br>IPv4/IPv6 地址和网络。",
-        "allowed_protocols": "允许的协议",
+        "allowed_protocols": "允许用户直接访问的协议 (不会影响应用的密码协议)",
         "app_name": "应用名称",
         "app_passwd": "应用密码",
         "app_passwd_protocols": "应用密码允许的协议",
@@ -770,7 +770,7 @@
         "all_domains": "全部域名",
         "allow_from_smtp": "只允许这些 IP 使用 <b>SMTP</b>",
         "allow_from_smtp_info": "留空以允许所有发送者。<br>IPv4/IPv6 地址或网络。",
-        "allowed_protocols": "允许用户直接访问的协议 (不会影响应用的密码协议)",
+        "allowed_protocols": "允许的协议",
         "backup_mx": "中继域名",
         "bcc": "BCC",
         "bcc_destination": "BCC 目标地址",

+ 2 - 2
data/web/lang/lang.zh-tw.json

@@ -553,7 +553,7 @@
         "alias": "編輯別名",
         "allow_from_smtp": "只允許這些 IP 使用 <b>SMTP</b>",
         "allow_from_smtp_info": "留空將允許所有寄件人<br>IPv4/IPv6 地址或網路",
-        "allowed_protocols": "允許的協定",
+        "allowed_protocols": "使用者直接存取時允許的協定 (不影響應用程式密碼所能使用的協定)",
         "app_name": "應用程式名稱",
         "app_passwd": "應用程式密碼",
         "app_passwd_protocols": "應用程式密碼允許的協定",
@@ -763,7 +763,7 @@
         "all_domains": "所有域名",
         "allow_from_smtp": "只允許這些 IP 使用<b>SMTP</b>",
         "allow_from_smtp_info": "留空以允許所有發送者<br>IPv4/IPv6 地址或網路",
-        "allowed_protocols": "使用者直接存取時允許的協定 (不影響應用程式密碼所能使用的協定)",
+        "allowed_protocols": "允許的協定",
         "backup_mx": "中繼域名",
         "bcc": "密件副本",
         "bcc_destination": "密件副本目標地址",

+ 2 - 2
update.sh

@@ -911,7 +911,7 @@ while (($#)); do
   --skip-start         -   Do not start mailcow after update
   --skip-ping-check    -   Skip ICMP Check to public DNS resolvers (Use it only if you'\''ve blocked any ICMP Connections to your mailcow machine)
   --stable             -   Switch your mailcow updates to the stable (master) branch. Default unless you changed it with --nightly or --legacy.
-  --legacy             -   Switch your mailcow updates to the legacy branch. The legacy branch will only recieve security updates until February 2026.
+  --legacy             -   Switch your mailcow updates to the legacy branch. The legacy branch will only receive security updates until February 2026.
   -f|--force           -   Force update, do not ask questions
   -d|--dev             -   Enables Developer Mode (No Checkout of update.sh for tests)
 '
@@ -1318,7 +1318,7 @@ if ! [ "$NEW_BRANCH" ]; then
     echo -e "\e[33mTo change that run the update.sh Script one time with the --stable parameter to switch to stable builds.\e[0m"
 
   elif [ "${BRANCH}" == "legacy" ]; then
-    echo -e "\e[31mYou are receiving legacy updates. The legacy branch will only recieve security updates until February 2026.\e[0m"
+    echo -e "\e[31mYou are receiving legacy updates. The legacy branch will only receive security updates until February 2026.\e[0m"
     sleep 1
     echo -e "\e[33mTo change that run the update.sh Script one time with the --stable parameter to switch to stable builds.\e[0m"
 

部分文件因为文件数量过多而无法显示