فهرست منبع

[Rspamd][Web] Internal alias support

FreddleSpl0it 2 روز پیش
والد
کامیت
f67c0530f5

+ 35 - 3
data/conf/rspamd/dynmaps/settings.php

@@ -56,7 +56,7 @@ function normalize_email($email) {
     $email = explode('@', $email);
     $email[0] = str_replace('.', '', $email[0]);
     $email = implode('@', $email);
-  } 
+  }
   $gm_alt = "@googlemail.com";
   if (substr_compare($email, $gm_alt, -strlen($gm_alt)) == 0) {
     $email = explode('@', $email);
@@ -114,7 +114,7 @@ function ucl_rcpts($object, $type) {
       $rcpt[] = str_replace('/', '\/', $row['address']);
     }
     // Aliases by alias domains
-    $stmt = $pdo->prepare("SELECT CONCAT(`local_part`, '@', `alias_domain`.`alias_domain`) AS `alias` FROM `mailbox` 
+    $stmt = $pdo->prepare("SELECT CONCAT(`local_part`, '@', `alias_domain`.`alias_domain`) AS `alias` FROM `mailbox`
       LEFT OUTER JOIN `alias_domain` ON `mailbox`.`domain` = `alias_domain`.`target_domain`
       WHERE `mailbox`.`username` = :object");
     $stmt->execute(array(
@@ -184,7 +184,7 @@ while ($row = array_shift($rows)) {
     rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
 <?php
   }
-  $stmt = $pdo->prepare("SELECT `option`, `value` FROM `filterconf` 
+  $stmt = $pdo->prepare("SELECT `option`, `value` FROM `filterconf`
     WHERE (`option` = 'highspamlevel' OR `option` = 'lowspamlevel')
       AND `object`= :object");
   $stmt->execute(array(':object' => $row['object']));
@@ -468,4 +468,36 @@ while ($row = array_shift($rows)) {
 <?php
 }
 ?>
+
+<?php
+// Start internal aliases
+
+$stmt = $pdo->query("SELECT `id`, `address`, `domain` FROM `alias` WHERE `active` = '1' AND `internal` = '1'");
+$aliases = $stmt->fetchAll(PDO::FETCH_ASSOC);
+while ($alias = array_shift($aliases)) {
+  // build allowed_domains regex and add target domain and alias domains
+  $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `active` = '1' AND `target_domain` = :target_domain");
+  $stmt->execute(array(':target_domain' => $alias['domain']));
+  $allowed_domains = $stmt->fetchAll(PDO::FETCH_ASSOC);
+  $allowed_domains = array_map(function($item) {
+    return str_replace('.', '\.', $item['alias_domain']);
+  }, $allowed_domains);
+  $allowed_domains[] = str_replace('.', '\.', $alias['domain']);
+  $allowed_domains = implode('|', $allowed_domains);
+?>
+  internal_alias_<?=$alias['id'];?> {
+    priority = 10;
+    rcpt = "<?=$alias['address'];?>";
+    from = "/^((?!.*@(<?=$allowed_domains;?>)).)*$/";
+    apply "default" {
+      MAILCOW_INTERNAL_ALIAS = 9999.0;
+    }
+    symbols [
+      "MAILCOW_INTERNAL_ALIAS"
+    ]
+  }
+<?php
+}
+?>
+
 }

+ 18 - 10
data/web/inc/functions.mailbox.inc.php

@@ -684,15 +684,16 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
           return true;
         break;
         case 'alias':
-          $addresses  = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['address']));
-          $gotos      = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['goto']));
-          $active = intval($_data['active']);
-          $sogo_visible = intval($_data['sogo_visible']);
-          $goto_null = intval($_data['goto_null']);
-          $goto_spam = intval($_data['goto_spam']);
-          $goto_ham = intval($_data['goto_ham']);
+          $addresses       = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['address']));
+          $gotos           = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['goto']));
+          $internal        = intval($_data['internal']);
+          $active          = intval($_data['active']);
+          $sogo_visible    = intval($_data['sogo_visible']);
+          $goto_null       = intval($_data['goto_null']);
+          $goto_spam       = intval($_data['goto_spam']);
+          $goto_ham        = intval($_data['goto_ham']);
           $private_comment = $_data['private_comment'];
-          $public_comment = $_data['public_comment'];
+          $public_comment  = $_data['public_comment'];
           if (strlen($private_comment) > 160 | strlen($public_comment) > 160){
             $_SESSION['return'][] = array(
               'type' => 'danger',
@@ -842,8 +843,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
               );
               continue;
             }
-            $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `public_comment`, `private_comment`, `goto`, `domain`, `sogo_visible`, `active`)
-              VALUES (:address, :public_comment, :private_comment, :goto, :domain, :sogo_visible, :active)");
+            $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `public_comment`, `private_comment`, `goto`, `domain`, `sogo_visible`, `internal`, `active`)
+              VALUES (:address, :public_comment, :private_comment, :goto, :domain, :sogo_visible, :internal, :active)");
             if (!filter_var($address, FILTER_VALIDATE_EMAIL) === true) {
               $stmt->execute(array(
                 ':address' => '@'.$domain,
@@ -853,6 +854,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
                 ':goto' => $goto,
                 ':domain' => $domain,
                 ':sogo_visible' => $sogo_visible,
+                ':internal' => $internal,
                 ':active' => $active
               ));
             }
@@ -864,6 +866,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
                 ':goto' => $goto,
                 ':domain' => $domain,
                 ':sogo_visible' => $sogo_visible,
+                ':internal' => $internal,
                 ':active' => $active
               ));
             }
@@ -2481,6 +2484,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
           foreach ($ids as $id) {
             $is_now = mailbox('get', 'alias_details', $id);
             if (!empty($is_now)) {
+              $internal = (isset($_data['internal'])) ? intval($_data['internal']) : $is_now['internal'];
               $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
               $sogo_visible = (isset($_data['sogo_visible'])) ? intval($_data['sogo_visible']) : $is_now['sogo_visible'];
               $goto_null = (isset($_data['goto_null'])) ? intval($_data['goto_null']) : 0;
@@ -2666,6 +2670,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
                 `domain` = :domain,
                 `goto` = :goto,
                 `sogo_visible`= :sogo_visible,
+                `internal`= :internal,
                 `active`= :active
                   WHERE `id` = :id");
               $stmt->execute(array(
@@ -2675,6 +2680,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
                 ':domain' => $domain,
                 ':goto' => $goto,
                 ':sogo_visible' => $sogo_visible,
+                ':internal' => $internal,
                 ':active' => $active,
                 ':id' => $is_now['id']
               ));
@@ -4700,6 +4706,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
             `address`,
             `public_comment`,
             `private_comment`,
+            `internal`,
             `active`,
             `sogo_visible`,
             `created`,
@@ -4730,6 +4737,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
           $aliasdata['goto'] = $row['goto'];
           $aliasdata['address'] = $row['address'];
           (!filter_var($aliasdata['address'], FILTER_VALIDATE_EMAIL)) ? $aliasdata['is_catch_all'] = 1 : $aliasdata['is_catch_all'] = 0;
+          $aliasdata['internal'] = $row['internal'];
           $aliasdata['active'] = $row['active'];
           $aliasdata['active_int'] = $row['active'];
           $aliasdata['sogo_visible'] = $row['sogo_visible'];

+ 1 - 0
data/web/inc/init_db.inc.php

@@ -184,6 +184,7 @@ function init_db_schema()
           "private_comment" => "TEXT",
           "public_comment" => "TEXT",
           "sogo_visible" => "TINYINT(1) NOT NULL DEFAULT '1'",
+          "internal" => "TINYINT(1) NOT NULL DEFAULT '0'",
           "active" => "TINYINT(1) NOT NULL DEFAULT '1'"
         ),
         "keys" => array(

+ 9 - 0
data/web/js/site/mailbox.js

@@ -1972,6 +1972,15 @@ jQuery(function($){
           data: 'private_comment',
           defaultContent: ''
         },
+        {
+          title: lang.internal,
+          data: 'internal',
+          defaultContent: '',
+          responsivePriority: 6,
+          render: function (data, type) {
+            return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
+          }
+        },
         {
           title: lang.active,
           data: 'active',

+ 5 - 0
data/web/lang/lang.de-de.json

@@ -71,6 +71,8 @@
         "goto_spam": "Nachrichten als <span class=\"text-danger\"><b>Spam</b></span> lernen",
         "hostname": "Host",
         "inactive": "Inaktiv",
+        "internal": "Intern",
+        "internal_info": "Interne Aliasse sind nur von der eigenen Domäne oder Alias-Domänen erreichbar.",
         "kind": "Art",
         "mailbox_quota_def": "Standard-Quota einer Mailbox",
         "mailbox_quota_m": "Max. Speicherplatz pro Mailbox (MiB)",
@@ -690,6 +692,8 @@
         "grant_types": "Grant-types",
         "hostname": "Servername",
         "inactive": "Inaktiv",
+        "internal": "Intern",
+        "internal_info": "Interne Aliasse sind nur von der eigenen Domäne oder Alias-Domänen erreichbar.",
         "kind": "Art",
         "last_modified": "Zuletzt geändert",
         "lookup_mx": "Ziel mit MX vergleichen (Regex, etwa <code>.*\\.google\\.com</code>, um alle Ziele mit MX *google.com zu routen)",
@@ -923,6 +927,7 @@
         "in_use": "Prozentualer Gebrauch",
         "inactive": "Inaktiv",
         "insert_preset": "Beispiel \"%s\" laden",
+        "internal": "Intern",
         "kind": "Art",
         "last_mail_login": "Letzter Mail-Login",
         "last_modified": "Zuletzt geändert",

+ 5 - 0
data/web/lang/lang.en-gb.json

@@ -71,6 +71,8 @@
         "goto_spam": "Learn as <span class=\"text-danger\"><b>spam</b></span>",
         "hostname": "Host",
         "inactive": "Inactive",
+        "internal": "Internal",
+        "internal_info": "Internal aliases are only accessible from the own domain or alias domains.",
         "kind": "Kind",
         "mailbox_quota_def": "Default mailbox quota",
         "mailbox_quota_m": "Max. quota per mailbox (MiB)",
@@ -690,6 +692,8 @@
         "grant_types": "Grant types",
         "hostname": "Hostname",
         "inactive": "Inactive",
+        "internal": "Internal",
+        "internal_info": "Internal aliases are only accessible from the own domain or alias domains.",
         "kind": "Kind",
         "last_modified": "Last modified",
         "lookup_mx": "Destination is a regular expression to match against MX name (<code>.*\\.google\\.com</code> to route all mail targeted to a MX ending in google.com over this hop)",
@@ -928,6 +932,7 @@
         "in_use": "In use (%)",
         "inactive": "Inactive",
         "insert_preset": "Insert example preset \"%s\"",
+        "internal": "Internal",
         "kind": "Kind",
         "last_mail_login": "Last mail login",
         "last_modified": "Last modified",

+ 6 - 1
data/web/templates/edit/alias.twig

@@ -6,6 +6,7 @@
 <br>
 <form class="form-horizontal" data-id="editalias" role="form" method="post">
   <input type="hidden" value="0" name="active">
+  <input type="hidden" value="0" name="internal">
   {% if not skip_sogo %}
   <input type="hidden" value="0" name="sogo_visible">
   {% endif %}
@@ -33,8 +34,12 @@
       <div class="form-check">
         <label><input type="checkbox" class="form-check-input" value="1" name="sogo_visible"{% if result.sogo_visible == '1' %} checked{% endif %}> {{ lang.edit.sogo_visible }}</label>
       </div>
-      <p class="text-muted">{{ lang.edit.sogo_visible_info }}</p>
+      <small class="text-muted d-block mb-2">{{ lang.edit.sogo_visible_info }}</small>
       {% endif %}
+      <div class="form-check">
+        <label><input type="checkbox" class="form-check-input" value="1" name="internal"{% if result.internal == '1' %} checked{% endif %}> {{ lang.edit.internal }}</label>
+      </div>
+      <small class="text-muted d-block">{{ lang.edit.internal_info }}</small>
     </div>
   </div>
   <hr>

+ 7 - 2
data/web/templates/modals/mailbox.twig

@@ -777,6 +777,7 @@
       <div class="modal-body">
         <form class="form-horizontal" data-cached-form="true" role="form" data-id="add_alias">
           <input type="hidden" value="0" name="active">
+          <input type="hidden" value="0" name="internal">
           <div class="row mb-2">
             <label class="control-label col-sm-2 text-sm-end" for="address">{{ lang.add.alias_address }}</label>
             <div class="col-sm-10">
@@ -803,11 +804,15 @@
               <div class="form-check">
                 <label><input type="checkbox" class="form-check-input" value="1" name="sogo_visible" checked> {{ lang.edit.sogo_visible }}</label>
               </div>
-              <p class="text-muted">{{ lang.edit.sogo_visible_info }}</p>
+              <small class="text-muted d-block mb-2">{{ lang.edit.sogo_visible_info }}</small>
               {% endif %}
+              <div class="form-check">
+                <label><input type="checkbox" class="form-check-input" value="1" name="internal"> {{ lang.add.internal }}</label>
+              </div>
+              <small class="text-muted d-block">{{ lang.edit.internal_info }}</small>
             </div>
           </div>
-          <div class="row mb-2">
+          <div class="row mb-4">
             <div class="offset-sm-2 col-sm-10">
               <div class="form-check">
                 <label><input type="checkbox" class="form-check-input" value="1" name="active" checked> {{ lang.add.active }}</label>