git subrepo commit (merge) mailcow/src/mailcow-dockerized

subrepo:
  subdir:   "mailcow/src/mailcow-dockerized"
  merged:   "81fb18894"
upstream:
  origin:   "https://github.com/mailcow/mailcow-dockerized.git"
  branch:   "master"
  commit:   "4ca02ecee"
git-subrepo:
  version:  "0.4.6"
  origin:   "???"
  commit:   "???"

Update to upstream 2026-10.  Local patches re-applied by hand
(no Unbound DNS for containers, IPv6 off by default, fake-MySQL
stubs in dockerapi, Postfix overrides, no .env symlink); dropped
the unused dovecot and clamd Dockerfile patches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Change-Id: I2c2c194d1d436b841358685f5f94aef09eb19ae8
diff --git a/mailcow/src/mailcow-dockerized/data/web/inc/functions.quarantine.inc.php b/mailcow/src/mailcow-dockerized/data/web/inc/functions.quarantine.inc.php
index f4f49de..c89b3e4 100644
--- a/mailcow/src/mailcow-dockerized/data/web/inc/functions.quarantine.inc.php
+++ b/mailcow/src/mailcow-dockerized/data/web/inc/functions.quarantine.inc.php
@@ -22,7 +22,7 @@
         return false;

       }

       $stmt = $pdo->prepare('SELECT `id` FROM `quarantine` LEFT OUTER JOIN `user_acl` ON `user_acl`.`username` = `rcpt`

-        WHERE SHA2(CONCAT(`id`, `qid`), 256) = :hash

+        WHERE `qhash` = :hash

           AND user_acl.quarantine = 1

           AND rcpt IN (SELECT username FROM mailbox)');

       $stmt->execute(array(':hash' => $hash));

@@ -65,7 +65,7 @@
         return false;

       }

       $stmt = $pdo->prepare('SELECT `id` FROM `quarantine` LEFT OUTER JOIN `user_acl` ON `user_acl`.`username` = `rcpt`

-        WHERE SHA2(CONCAT(`id`, `qid`), 256) = :hash

+        WHERE `qhash` = :hash

           AND `user_acl`.`quarantine` = 1

           AND `username` IN (SELECT `username` FROM `mailbox`)');

       $stmt->execute(array(':hash' => $hash));

@@ -169,7 +169,9 @@
           }

         }

         elseif ($release_format == 'raw') {

-          $detail_row['msg'] = preg_replace('/^X-Spam-Flag: (.*)/', 'X-Pre-Release-Spam-Flag $1', $detail_row['msg']);

+          $detail_row['msg'] = preg_replace('/^X-Spam-Flag: (.*)/m', 'X-Pre-Release-Spam-Flag: $1', $detail_row['msg']);

+          // dot-stuffing per RFC5321 4.5.2: escape leading dots

+          $detail_row['msg'] = preg_replace('~^\.~m', '..', $detail_row['msg']);

           $postfix_talk = array(

             array('220', 'HELO quarantine' . chr(10)),

             array('250', 'MAIL FROM: ' . $sender . chr(10)),

@@ -180,7 +182,7 @@
             array('221', '')

           );

           // Thanks to https://stackoverflow.com/questions/6632399/given-an-email-as-raw-text-how-can-i-send-it-using-php

-          $smtp_connection = fsockopen($postfix, 590, $errno, $errstr, 1); 

+          $smtp_connection = fsockopen($postfix, 590, $errno, $errstr, 1);

           if (!$smtp_connection) {

             logger(array('return' => array(

               array(

@@ -192,7 +194,7 @@
             return false;

           }

           for ($i=0; $i < count($postfix_talk); $i++) {

-            $smtp_resource = fgets($smtp_connection, 256); 

+            $smtp_resource = fgets($smtp_connection, 256);

             if (substr($smtp_resource, 0, 3) !== $postfix_talk[$i][0]) {

               $ret = substr($smtp_resource, 0, 3);

               $ret = (empty($ret)) ? '-' : $ret;

@@ -464,18 +466,20 @@
             }

           }

           elseif ($release_format == 'raw') {

-            $row['msg'] = preg_replace('/^X-Spam-Flag: (.*)/', 'X-Pre-Release-Spam-Flag $1', $row['msg']);

+            $row['msg'] = preg_replace('/^X-Spam-Flag: (.*)/m', 'X-Pre-Release-Spam-Flag: $1', $row['msg']);

+            // dot-stuffing per RFC5321 4.5.2: escape leading dots

+            $row['msg'] = preg_replace('~^\.~m', '..', $row['msg']);

             $postfix_talk = array(

               array('220', 'HELO quarantine' . chr(10)),

               array('250', 'MAIL FROM: ' . $sender . chr(10)),

               array('250', 'RCPT TO: ' . $row['rcpt'] . chr(10)),

               array('250', 'DATA' . chr(10)),

-              array('354', str_replace("\n.", '', $row['msg']) . chr(10) . '.' . chr(10)),

+              array('354', $row['msg'] . chr(10) . '.' . chr(10)),

               array('250', 'QUIT' . chr(10)),

               array('221', '')

             );

             // Thanks to https://stackoverflow.com/questions/6632399/given-an-email-as-raw-text-how-can-i-send-it-using-php

-            $smtp_connection = fsockopen($postfix, 590, $errno, $errstr, 1); 

+            $smtp_connection = fsockopen($postfix, 590, $errno, $errstr, 1);

             if (!$smtp_connection) {

               $_SESSION['return'][] = array(

                 'type' => 'warning',

@@ -485,7 +489,7 @@
               return false;

             }

             for ($i=0; $i < count($postfix_talk); $i++) {

-              $smtp_resource = fgets($smtp_connection, 256); 

+              $smtp_resource = fgets($smtp_connection, 256);

               if (substr($smtp_resource, 0, 3) !== $postfix_talk[$i][0]) {

                 $ret = substr($smtp_resource, 0, 3);

                 $ret = (empty($ret)) ? '-' : $ret;

@@ -833,7 +837,7 @@
         )));

         return false;

       }

-      $stmt = $pdo->prepare('SELECT * FROM `quarantine` WHERE SHA2(CONCAT(`id`, `qid`), 256) = :hash');

+      $stmt = $pdo->prepare('SELECT * FROM `quarantine` WHERE `qhash` = :hash');

       $stmt->execute(array(':hash' => $hash));

       return $stmt->fetch(PDO::FETCH_ASSOC);

     break;