浏览代码

[Quarantine] Allow to redirect all quarantine messages to a specific address
[Web] Minor changes to quarantine UI

andryyy 5 年之前
父节点
当前提交
6c92688ff6

+ 9 - 2
data/Dockerfiles/dovecot/quarantine_notify.py

@@ -86,11 +86,18 @@ def notify_rcpt(rcpt, msg_count, quarantine_acl):
       msg.attach(html_part)
       msg['To'] = str(rcpt)
       bcc = r.get('Q_BCC') or ""
+      redirect = r.get('Q_REDIRECT') or ""
       text = msg.as_string()
       if bcc == '':
-        server.sendmail(msg['From'], str(rcpt), text)
+        if redirect == '':
+          server.sendmail(msg['From'], str(rcpt), text)
+        else:
+          server.sendmail(msg['From'], str(redirect), text)
       else:
-        server.sendmail(msg['From'], [str(rcpt)] + [str(bcc)], text)
+        if redirect == '':
+          server.sendmail(msg['From'], [str(rcpt)] + [str(bcc)], text)
+        else:
+          server.sendmail(msg['From'], [str(redirect)] + [str(bcc)], text)
       server.quit()
       for res in meta_query:
         query_mysql('UPDATE quarantine SET notified = 1 WHERE id = "%d"' % (res['id']), update = True)

+ 62 - 65
data/web/admin.php

@@ -767,85 +767,82 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
         <?php
         endif;
         ?>
-        <form class="form" data-id="quarantine" role="form" method="post">
-          <div class="row">
-            <div class="col-sm-6">
-              <div class="form-group">
-                <label for="retention_size"><?=$lang['admin']['quarantine_retention_size'];?></label>
-                <input type="number" class="form-control" name="retention_size" value="<?=$q_data['retention_size'];?>" placeholder="0" required>
-              </div>
-            </div>
-            <div class="col-sm-6">
-              <div class="form-group">
-                <label for="max_size"><?=$lang['admin']['quarantine_max_size'];?></label>
-                <input type="number" class="form-control" name="max_size" value="<?=$q_data['max_size'];?>" placeholder="0" required>
-              </div>
+        <form class="form-horizontal" data-id="quarantine" role="form" method="post">
+          <div class="form-group">
+            <label class="col-sm-4 control-label" for="retention_size"><?=$lang['admin']['quarantine_retention_size'];?></label>
+            <div class="col-sm-8">
+              <input type="number" class="form-control" name="retention_size" value="<?=$q_data['retention_size'];?>" placeholder="0" required>
             </div>
           </div>
-          <div class="row">
-            <div class="col-sm-6">
-              <div class="form-group">
-                <label for="max_age"><?=$lang['admin']['quarantine_max_age'];?></label>
-                <input type="number" class="form-control" name="max_age" value="<?=$q_data['max_age'];?>" min="1" required>
-              </div>
+          <div class="form-group">
+            <label class="col-sm-4 control-label" for="max_size"><?=$lang['admin']['quarantine_max_size'];?></label>
+            <div class="col-sm-8">
+              <input type="number" class="form-control" name="max_size" value="<?=$q_data['max_size'];?>" placeholder="0" required>
             </div>
-            <div class="col-sm-6">
-              <div class="form-group">
-                <label for="sender"><span class="glyphicon glyphicon-copy"></span> <?=$lang['admin']['quarantine_bcc'];?></label>
-                <input type="email" class="form-control" name="bcc" value="<?=htmlspecialchars($q_data['bcc']);?>" placeholder="">
-              </div>
+          </div>
+          <div class="form-group">
+            <label class="col-sm-4 control-label" for="max_age"><?=$lang['admin']['quarantine_max_age'];?></label>
+            <div class="col-sm-8">
+              <input type="number" class="form-control" name="max_age" value="<?=$q_data['max_age'];?>" min="1" required>
             </div>
           </div>
-          <div class="row">
-            <div class="col-sm-6">
-              <div class="form-group">
-                <label for="sender"><?=$lang['admin']['quarantine_notification_sender'];?>:</label>
-                <input type="email" class="form-control" name="sender" value="<?=htmlspecialchars($q_data['sender']);?>" placeholder="quarantine@localhost">
-              </div>
+          <hr>
+          <div class="form-group">
+            <label class="col-sm-4 control-label" for="sender"><span class="glyphicon glyphicon-share-alt"></span> <?=$lang['admin']['quarantine_redirect'];?></label>
+            <div class="col-sm-8">
+              <input type="email" class="form-control" name="redirect" value="<?=htmlspecialchars($q_data['redirect']);?>" placeholder="">
             </div>
-            <div class="col-sm-6">
-              <div class="form-group">
-                <label for="subject"><?=$lang['admin']['quarantine_notification_subject'];?>:</label>
-                <input type="text" class="form-control" name="subject" value="<?=htmlspecialchars($q_data['subject']);?>" placeholder="Spam Quarantine Notification">
-              </div>
+          </div>
+          <div class="form-group">
+            <label class="col-sm-4 control-label" for="sender"><span class="glyphicon glyphicon-copy"></span> <?=$lang['admin']['quarantine_bcc'];?></label>
+            <div class="col-sm-8">
+              <input type="email" class="form-control" name="bcc" value="<?=htmlspecialchars($q_data['bcc']);?>" placeholder="">
             </div>
           </div>
           <hr>
-          <div class="row">
-            <div class="col-sm-12">
-              <legend data-target="#quarantine_template" style="cursor:pointer" class="arrow-toggle" unselectable="on" data-toggle="collapse">
-                <span style="font-size:12px" class="arrow rotate glyphicon glyphicon-menu-down"></span> <?=$lang['admin']['quarantine_notification_html'];?>
-              </legend>
-              <div id="quarantine_template" class="collapse" >
-                <textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="20" name="html_tmpl"><?=$q_data['html_tmpl'];?></textarea>
-              </div>
+          <div class="form-group">
+            <label class="col-sm-4 control-label" for="sender"><?=$lang['admin']['quarantine_notification_sender'];?>:</label>
+            <div class="col-sm-8">
+              <input type="email" class="form-control" name="sender" value="<?=htmlspecialchars($q_data['sender']);?>" placeholder="quarantine@localhost">
             </div>
           </div>
-          <div class="row">
-            <div class="col-sm-6">
-              <div class="form-group">
-                <label for="release_format"><?=$lang['admin']['quarantine_release_format'];?>:</label>
-                <select data-width="100%" name="release_format" class="selectpicker" title="<?=$lang['tfa']['select'];?>">
-                  <option <?=($q_data['release_format'] == 'raw') ? 'selected' : null;?> value="raw"><?=$lang['admin']['quarantine_release_format_raw'];?></option>
-                  <option <?=($q_data['release_format'] == 'attachment') ? 'selected' : null;?> value="attachment"><?=$lang['admin']['quarantine_release_format_att'];?></option>
-                </select>
-              </div>
+          <div class="form-group">
+            <label class="col-sm-4 control-label" for="subject"><?=$lang['admin']['quarantine_notification_subject'];?>:</label>
+            <div class="col-sm-8">
+              <input type="text" class="form-control" name="subject" value="<?=htmlspecialchars($q_data['subject']);?>" placeholder="Spam Quarantine Notification">
             </div>
-            <div class="col-sm-6">
-              <div class="form-group">
-                <label for="exclude_domains"><?=$lang['admin']['quarantine_exclude_domains'];?>:</label><br />
-                <select data-width="100%" name="exclude_domains" class="selectpicker" title="<?=$lang['tfa']['select'];?>" multiple>
-                <?php
-                foreach (array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains')) as $domain):
-                ?>
-                  <option <?=(in_array($domain, $q_data['exclude_domains'])) ? 'selected' : null;?>><?=htmlspecialchars($domain);?></option>
-                <?php
-                endforeach;
-                ?>
-                </select>
-              </div>
+          </div>
+          <hr>
+          <div class="form-group">
+            <label class="col-sm-4 control-label" for="release_format"><?=$lang['admin']['quarantine_release_format'];?>:</label>
+            <div class="col-sm-8">
+              <select data-width="100%" name="release_format" class="selectpicker" title="<?=$lang['tfa']['select'];?>">
+                <option <?=($q_data['release_format'] == 'raw') ? 'selected' : null;?> value="raw"><?=$lang['admin']['quarantine_release_format_raw'];?></option>
+                <option <?=($q_data['release_format'] == 'attachment') ? 'selected' : null;?> value="attachment"><?=$lang['admin']['quarantine_release_format_att'];?></option>
+              </select>
             </div>
           </div>
+          <div class="form-group">
+            <label class="col-sm-4 control-label" for="exclude_domains"><?=$lang['admin']['quarantine_exclude_domains'];?>:</label><br />
+            <div class="col-sm-8">
+              <select data-width="100%" name="exclude_domains" class="selectpicker" title="<?=$lang['tfa']['select'];?>" multiple>
+              <?php
+              foreach (array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains')) as $domain):
+              ?>
+                <option <?=(in_array($domain, $q_data['exclude_domains'])) ? 'selected' : null;?>><?=htmlspecialchars($domain);?></option>
+              <?php
+              endforeach;
+              ?>
+              </select>
+            </div>
+          </div>
+          <hr>
+          <legend data-target="#quarantine_template" style="cursor:pointer" class="arrow-toggle" unselectable="on" data-toggle="collapse">
+            <span style="font-size:12px" class="arrow rotate glyphicon glyphicon-menu-down"></span> <?=$lang['admin']['quarantine_notification_html'];?>
+          </legend>
+          <div id="quarantine_template" class="collapse" >
+            <textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="40" name="html_tmpl"><?=$q_data['html_tmpl'];?></textarea>
+          </div>
           <button class="btn btn-sm btn-success" data-action="edit_selected" data-item="self" data-id="quarantine" data-api-url='edit/quarantine' data-api-attr='{"action":"settings"}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
         </form>
       </div>

+ 3 - 0
data/web/css/site/admin.css

@@ -70,3 +70,6 @@ table tbody tr {
 table tbody tr td input[type="checkbox"] {
   cursor: pointer;
 }
+#quarantine_template {
+  margin:20px;
+}

+ 8 - 0
data/web/inc/functions.quarantine.inc.php

@@ -307,6 +307,12 @@ function quarantine($_action, $_data = null) {
         else {
           $bcc = $_data['bcc'];
         }
+        if (!filter_var($_data['redirect'], FILTER_VALIDATE_EMAIL)) {
+          $redirect = '';
+        }
+        else {
+          $redirect = $_data['redirect'];
+        }
         if (!filter_var($_data['sender'], FILTER_VALIDATE_EMAIL)) {
           $sender = '';
         }
@@ -326,6 +332,7 @@ function quarantine($_action, $_data = null) {
           $redis->Set('Q_RELEASE_FORMAT', $release_format);
           $redis->Set('Q_SENDER', $sender);
           $redis->Set('Q_BCC', $bcc);
+          $redis->Set('Q_REDIRECT', $redirect);
           $redis->Set('Q_SUBJ', $subject);
           $redis->Set('Q_HTML', $html);
         }
@@ -793,6 +800,7 @@ function quarantine($_action, $_data = null) {
         $settings['subject'] = $redis->Get('Q_SUBJ');
         $settings['sender'] = $redis->Get('Q_SENDER');
         $settings['bcc'] = $redis->Get('Q_BCC');
+        $settings['redirect'] = $redis->Get('Q_REDIRECT');
         $settings['html_tmpl'] = htmlspecialchars($redis->Get('Q_HTML'));
         if (empty($settings['html_tmpl'])) {
           $settings['html_tmpl'] = htmlspecialchars(file_get_contents("/tpls/quarantine.tpl"));

+ 2 - 1
data/web/lang/lang.de.json

@@ -223,6 +223,7 @@
         "quarantine_notification_html": "Benachrichtigungs-E-Mail Inhalt:<br><small>Leer lassen, um Standard-Template wiederherzustellen.</small>",
         "quarantine_notification_sender": "Benachrichtigungs-E-Mail Absender",
         "quarantine_notification_subject": "Benachrichtigungs-E-Mail Betreff",
+        "quarantine_redirect": "<b>Alle</b> Benachrichtigungen an folgendes Postfach umleiten:<br><small>Leer bedeutet deaktiviert. <b>Unsignierte, ungeprüfte E-Mail. Sollte nur intern zugestellt werden.</b></small>",
         "quarantine_release_format": "Format freigegebener Mails",
         "quarantine_release_format_att": "Als Anhang",
         "quarantine_release_format_raw": "Unverändertes Original",
@@ -736,7 +737,7 @@
         "check_hash": "Checksumme auf VirusTotal suchen",
         "confirm_delete": "Bestätigen Sie die Löschung dieses Elements.",
         "danger": "Gefahr",
-        "disabled_by_config": "Die derzeitige Konfiguration deaktiviert die Funktion des Quarantäne-Systems.",
+        "disabled_by_config": "Die derzeitige Konfiguration deaktiviert die Funktion des Quarantäne-Systems. Zur Funktion muss eine Anzahl an Rückhaltungen pro Mailbox sowie ein Limit für die maximale Größe pro Element definiert werden.",
         "download_eml": "Herunterladen (.eml)",
         "empty": "Keine Einträge",
         "high_danger": "Hohe Gefahr",

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

@@ -222,6 +222,7 @@
         "quarantine_notification_html": "Notification email template:<br><small>Leave empty to restore default template.</small>",
         "quarantine_notification_sender": "Notification email sender",
         "quarantine_notification_subject": "Notification email subject",
+        "quarantine_redirect": "<b>Redirect all notifications</b> to this recipient:<br><small>Leave empty to disable. <b>Unsigned, unchecked mail. Should be delivered internally only.</b></small>",
         "quarantine_release_format": "Format of released items",
         "quarantine_release_format_att": "As attachment",
         "quarantine_release_format_raw": "Unmodified original",
@@ -736,7 +737,7 @@
         "check_hash": "Search file hash @ VT",
         "confirm_delete": "Confirm the deletion of this element.",
         "danger": "Danger",
-        "disabled_by_config": "The current system configuration disables the quarantine functionality.",
+        "disabled_by_config": "The current system configuration disables the quarantine functionality. Please set \"retentions per mailbox\" and a \"maximum size\" for quarantine elements.",
         "download_eml": "Download (.eml)",
         "empty": "No results",
         "high_danger": "High",

+ 1 - 1
docker-compose.yml

@@ -193,7 +193,7 @@ services:
             - sogo
 
     dovecot-mailcow:
-      image: mailcow/dovecot:1.126
+      image: mailcow/dovecot:1.127
       depends_on:
         - mysql-mailcow
       dns: