Ver código fonte

[Web, Dovecot] Add new options to imapsync, other minor changes to forms, partly fixes #955

andre.peters 7 anos atrás
pai
commit
04f9d74339

+ 26 - 20
data/Dockerfiles/dovecot/imapsync_cron.pl

@@ -33,26 +33,29 @@ open my $file, '<', "/etc/sogo/sieve.creds";
 my $creds = <$file>; 
 close $file;
 my ($master_user, $master_pass) = split /:/, $creds;
-my $sth = $dbh->prepare("SELECT id, user1, user2, host1, authmech1, password1, exclude, port1, enc1, delete2duplicates, maxage, subfolder2, delete1, delete2 FROM imapsync WHERE active = 1 AND (UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(last_run) > mins_interval * 60 OR last_run IS NULL) ORDER BY last_run");
+my $sth = $dbh->prepare("SELECT id, user1, user2, host1, authmech1, password1, exclude, port1, enc1, delete2duplicates, maxage, subfolder2, delete1, delete2, automap, skipcrossduplicates, maxbytespersecond FROM imapsync WHERE active = 1 AND (UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(last_run) > mins_interval * 60 OR last_run IS NULL) ORDER BY last_run");
 $sth->execute();
 my $row;
 
 while ($row = $sth->fetchrow_arrayref()) {
 
-  $id                 = @$row[0];
-  $user1              = @$row[1];
-  $user2              = @$row[2];
-  $host1              = @$row[3];
-  $authmech1          = @$row[4];
-  $password1          = @$row[5];
-  $exclude            = @$row[6];
-  $port1              = @$row[7];
-  $enc1               = @$row[8];
-  $delete2duplicates  = @$row[9];
-  $maxage             = @$row[10];
-  $subfolder2         = @$row[11];
-  $delete1            = @$row[12];
-  $delete2            = @$row[13];
+  $id                  = @$row[0];
+  $user1               = @$row[1];
+  $user2               = @$row[2];
+  $host1               = @$row[3];
+  $authmech1           = @$row[4];
+  $password1           = @$row[5];
+  $exclude             = @$row[6];
+  $port1               = @$row[7];
+  $enc1                = @$row[8];
+  $delete2duplicates   = @$row[9];
+  $maxage              = @$row[10];
+  $subfolder2          = @$row[11];
+  $delete1             = @$row[12];
+  $delete2             = @$row[13];
+  $automap             = @$row[14];
+  $skipcrossduplicates = @$row[15];
+  $maxbytespersecond   = @$row[16];
 
   $is_running = $dbh->prepare("UPDATE imapsync SET is_running = 1 WHERE id = ?");
   $is_running->bind_param( 1, ${id} );
@@ -72,11 +75,14 @@ while ($row = $sth->fetchrow_arrayref()) {
 	"--tmpdir", "/tmp",
 	"--subscribeall",
 	($exclude eq ""	? () : ("--exclude", $exclude)),
-	($subfolder2 eq ""	? () : ('--subfolder2', $subfolder2)),
-	($maxage eq "0"	? () : ('--maxage', $maxage)),
-	($delete2duplicates	ne "1"	? () : ('--delete2duplicates')),
-	($delete1	ne "1"	? () : ('--delete')),
-    ($delete2   ne "1"  ? () : ('--delete2')),
+	($subfolder2 eq "" ? () : ('--subfolder2', $subfolder2)),
+	($maxage eq "0" ? () : ('--maxage', $maxage)),
+  ($maxbytespersecond eq "0" ? () : ('--maxbytespersecond', $maxage)),
+	($delete2duplicates	ne "1" ? () : ('--delete2duplicates')),
+	($delete1	ne "1" ? () : ('--delete')),
+  ($delete2 ne "1" ? () : ('--delete2')),
+  ($automap ne "1" ? () : ('--automap')),
+  ($skipcrossduplicates ne "1" ? () : ('--skipcrossduplicates')),
 	(!defined($enc1) ? () : ($enc1)),
 	"--host1", $host1,
 	"--user1", $user1,

+ 27 - 1
data/web/edit.php

@@ -661,12 +661,15 @@ if (isset($_SESSION['mailcow_cc_role'])) {
         $id = $_GET["syncjob"];
         $result = mailbox('get', 'syncjob_details', $id);
         if (!empty($result)) {
+          print_r($result);
         ?>
           <h4><?=$lang['edit']['syncjob'];?></h4>
           <form class="form-horizontal" data-id="editsyncjob" role="form" method="post">
             <input type="hidden" value="0" name="delete2duplicates">
             <input type="hidden" value="0" name="delete1">
             <input type="hidden" value="0" name="delete2">
+            <input type="hidden" value="0" name="automap">
+            <input type="hidden" value="0" name="skipcrossduplicates">
             <input type="hidden" value="0" name="active">
             <div class="form-group">
               <label class="control-label col-sm-2" for="host1"><?=$lang['edit']['hostname'];?></label>
@@ -706,6 +709,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
               <label class="control-label col-sm-2" for="mins_interval"><?=$lang['edit']['mins_interval'];?></label>
               <div class="col-sm-10">
                 <input type="number" class="form-control" name="mins_interval" min="1" max="3600" value="<?=htmlspecialchars($result['mins_interval'], ENT_QUOTES, 'UTF-8');?>" required>
+                <small class="help-block">10-3600</small>
               </div>
             </div>
             <div class="form-group">
@@ -717,7 +721,15 @@ if (isset($_SESSION['mailcow_cc_role'])) {
             <div class="form-group">
               <label class="control-label col-sm-2" for="maxage"><?=$lang['edit']['maxage'];?></label>
               <div class="col-sm-10">
-              <input type="number" class="form-control" name="maxage" id="maxage" value="<?=htmlspecialchars($result['maxage'], ENT_QUOTES, 'UTF-8');?>">
+              <input type="number" class="form-control" name="maxage" id="maxage" min="0" max="32000" value="<?=htmlspecialchars($result['maxage'], ENT_QUOTES, 'UTF-8');?>">
+              <small class="help-block">0-32000</small>
+              </div>
+            </div>
+            <div class="form-group">
+              <label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label>
+              <div class="col-sm-10">
+              <input type="number" class="form-control" name="maxbytespersecond" id="maxbytespersecond" min="0" max="125000000" value="<?=htmlspecialchars($result['maxbytespersecond'], ENT_QUOTES, 'UTF-8');?>">
+              <small class="help-block">0-125000000</small>
               </div>
             </div>
             <div class="form-group">
@@ -747,6 +759,20 @@ if (isset($_SESSION['mailcow_cc_role'])) {
                 </div>
               </div>
             </div>
+            <div class="form-group">
+              <div class="col-sm-offset-2 col-sm-10">
+                <div class="checkbox">
+                <label><input type="checkbox" value="1" name="automap" <?=($result['automap']=="1") ? "checked" : "";?>> <?=$lang['edit']['automap'];?></label>
+                </div>
+              </div>
+            </div>
+            <div class="form-group">
+              <div class="col-sm-offset-2 col-sm-10">
+                <div class="checkbox">
+                <label><input type="checkbox" value="1" name="skipcrossduplicates" <?=($result['skipcrossduplicates']=="1") ? "checked" : "";?>> <?=$lang['edit']['skipcrossduplicates'];?></label>
+                </div>
+              </div>
+            </div>
             <div class="form-group">
               <div class="col-sm-offset-2 col-sm-10">
                 <div class="checkbox">

+ 50 - 16
data/web/inc/functions.mailbox.inc.php

@@ -213,24 +213,30 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
             return false;
           }
           $active  = intval($_data['active']);
-          $delete2duplicates = intval($_data['delete2duplicates']);
-          $delete1  = intval($_data['delete1']);
-          $delete2  = intval($_data['delete2']);
-          $port1            = $_data['port1'];
-          $host1            = strtolower($_data['host1']);
-          $password1        = $_data['password1'];
-          $exclude          = $_data['exclude'];
-          $maxage           = $_data['maxage'];
-          $subfolder2       = $_data['subfolder2'];
-          $user1            = $_data['user1'];
-          $mins_interval    = $_data['mins_interval'];
-          $enc1             = $_data['enc1'];
+          $delete2duplicates    = intval($_data['delete2duplicates']);
+          $delete1              = intval($_data['delete1']);
+          $delete2              = intval($_data['delete2']);
+          $skipcrossduplicates  = intval($_data['skipcrossduplicates']);
+          $automap              = intval($_data['automap']);
+          $port1                = $_data['port1'];
+          $host1                = strtolower($_data['host1']);
+          $password1            = $_data['password1'];
+          $exclude              = $_data['exclude'];
+          $maxage               = $_data['maxage'];
+          $maxbytespersecond    = $_data['maxbytespersecond'];
+          $subfolder2           = $_data['subfolder2'];
+          $user1                = $_data['user1'];
+          $mins_interval        = $_data['mins_interval'];
+          $enc1                = $_data['enc1'];
           if (empty($subfolder2)) {
             $subfolder2 = "";
           }
           if (!isset($maxage) || !filter_var($maxage, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32767)))) {
             $maxage = "0";
           }
+          if (!isset($maxbytespersecond) || !filter_var($maxbytespersecond, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 125000000)))) {
+            $maxbytespersecond = "0";
+          }
           if (!filter_var($port1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 65535)))) {
             $_SESSION['return'] = array(
               'type' => 'danger',
@@ -287,14 +293,17 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
             return false;
           }
           try {
-            $stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `delete1`, `delete2`, `maxage`, `subfolder2`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `active`)
-              VALUES (:user2, :exclude, :delete1, :delete2, :maxage, :subfolder2, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :active)");
+            $stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `delete1`, `delete2`, `automap`, `skipcrossduplicates`, `maxbytespersecond`, `maxage`, `subfolder2`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `active`)
+              VALUES (:user2, :exclude, :delete1, :delete2, :automap, :skipcrossduplicates, :maxbytespersecond, :maxage, :subfolder2, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :active)");
             $stmt->execute(array(
               ':user2' => $username,
               ':exclude' => $exclude,
               ':maxage' => $maxage,
               ':delete1' => $delete1,
               ':delete2' => $delete2,
+              ':automap' => $automap,
+              ':skipcrossduplicates' => $skipcrossduplicates,
+              ':maxbytespersecond' => $maxbytespersecond,
               ':subfolder2' => $subfolder2,
               ':host1' => $host1,
               ':authmech1' => 'PLAIN',
@@ -1444,6 +1453,8 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
               $delete2duplicates = (isset($_data['delete2duplicates'])) ? intval($_data['delete2duplicates']) : $is_now['delete2duplicates'];
               $delete1 = (isset($_data['delete1'])) ? intval($_data['delete1']) : $is_now['delete1'];
               $delete2 = (isset($_data['delete2'])) ? intval($_data['delete2']) : $is_now['delete2'];
+              $automap = (isset($_data['automap'])) ? intval($_data['automap']) : $is_now['automap'];
+              $skipcrossduplicates = (isset($_data['skipcrossduplicates'])) ? intval($_data['skipcrossduplicates']) : $is_now['skipcrossduplicates'];
               $port1 = (!empty($_data['port1'])) ? $_data['port1'] : $is_now['port1'];
               $password1 = (!empty($_data['password1'])) ? $_data['password1'] : $is_now['password1'];
               $host1 = (!empty($_data['host1'])) ? $_data['host1'] : $is_now['host1'];
@@ -1452,6 +1463,7 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
               $mins_interval = (!empty($_data['mins_interval'])) ? $_data['mins_interval'] : $is_now['mins_interval'];
               $exclude = (!empty($_data['exclude'])) ? $_data['exclude'] : $is_now['exclude'];
               $maxage = (isset($_data['maxage']) && $_data['maxage'] != "") ? intval($_data['maxage']) : $is_now['maxage'];
+              $maxbytespersecond = (isset($_data['maxbytespersecond']) && $_data['maxbytespersecond'] != "") ? intval($_data['maxbytespersecond']) : $is_now['maxbytespersecond'];
             }
             else {
               $_SESSION['return'] = array(
@@ -1466,6 +1478,9 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
             if (!isset($maxage) || !filter_var($maxage, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 32767)))) {
               $maxage = "0";
             }
+            if (!isset($maxbytespersecond) || !filter_var($maxbytespersecond, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 125000000)))) {
+              $maxbytespersecond = "0";
+            }
             if (!filter_var($port1, FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 65535)))) {
               $_SESSION['return'] = array(
                 'type' => 'danger',
@@ -1502,14 +1517,33 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
               return false;
             }
             try {
-              $stmt = $pdo->prepare("UPDATE `imapsync` SET `delete1` = :delete1, `delete2` = :delete2, `maxage` = :maxage, `subfolder2` = :subfolder2, `exclude` = :exclude, `host1` = :host1, `last_run` = :last_run, `user1` = :user1, `password1` = :password1, `mins_interval` = :mins_interval, `port1` = :port1, `enc1` = :enc1, `delete2duplicates` = :delete2duplicates, `active` = :active
-                WHERE `id` = :id");
+              $stmt = $pdo->prepare("UPDATE `imapsync` SET `delete1` = :delete1,
+                `delete2` = :delete2,
+                `automap` = :automap,
+                `skipcrossduplicates` = :skipcrossduplicates,
+                `maxage` = :maxage,
+                `maxbytespersecond` = :maxbytespersecond,
+                `subfolder2` = :subfolder2,
+                `exclude` = :exclude,
+                `host1` = :host1,
+                `last_run` = :last_run,
+                `user1` = :user1,
+                `password1` = :password1,
+                `mins_interval` = :mins_interval,
+                `port1` = :port1,
+                `enc1` = :enc1,
+                `delete2duplicates` = :delete2duplicates,
+                `active` = :active
+                  WHERE `id` = :id");
               $stmt->execute(array(
                 ':delete1' => $delete1,
                 ':delete2' => $delete2,
+                ':automap' => $automap,
+                ':skipcrossduplicates' => $skipcrossduplicates,
                 ':id' => $id,
                 ':exclude' => $exclude,
                 ':maxage' => $maxage,
+                ':maxbytespersecond' => $maxbytespersecond,
                 ':subfolder2' => $subfolder2,
                 ':host1' => $host1,
                 ':user1' => $user1,

+ 5 - 2
data/web/inc/init_db.inc.php

@@ -3,7 +3,7 @@ function init_db_schema() {
   try {
     global $pdo;
 
-    $db_version = "21012018_1317";
+    $db_version = "24012018_1219";
 
     $stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
     $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
@@ -354,12 +354,15 @@ function init_db_schema() {
           "password1" => "VARCHAR(255) NOT NULL",
           "exclude" => "VARCHAR(500) NOT NULL DEFAULT ''",
           "maxage" => "SMALLINT NOT NULL DEFAULT '0'",
-          "mins_interval" => "VARCHAR(50) NOT NULL",
+          "mins_interval" => "VARCHAR(50) NOT NULL DEFAULT '0'",
+          "maxbytespersecond" => "VARCHAR(50) NOT NULL DEFAULT '0'",
           "port1" => "SMALLINT NOT NULL",
           "enc1" => "ENUM('TLS','SSL','PLAIN') DEFAULT 'TLS'",
           "delete2duplicates" => "TINYINT(1) NOT NULL DEFAULT '1'",
           "delete1" => "TINYINT(1) NOT NULL DEFAULT '0'",
           "delete2" => "TINYINT(1) NOT NULL DEFAULT '0'",
+          "automap" => "TINYINT(1) NOT NULL DEFAULT '0'",
+          "skipcrossduplicates" => "TINYINT(1) NOT NULL DEFAULT '0'",
           "is_running" => "TINYINT(1) NOT NULL DEFAULT '0'",
           "returned_text" => "TEXT",
           "last_run" => "TIMESTAMP NULL DEFAULT NULL",

+ 6 - 0
data/web/lang/lang.de.php

@@ -308,6 +308,12 @@ $lang['edit']['encryption'] = 'Verschlüsselung';
 $lang['edit']['maxage'] = 'Maximales Alter in Tagen einer Nachricht, die kopiert werden soll</br ><small>(0 = alle Nachrichten kopieren)</small>';
 $lang['edit']['subfolder2'] = 'Ziel-Ordner<br><small>(leer = kein Unterordner)</small>';
 $lang['edit']['mins_interval'] = 'Intervall (min)';
+$lang['edit']['maxbytespersecond'] = 'Max. Übertragungsrate in Bytes/s (0 für unlimitiert)';
+$lang['edit']['automap'] = 'Ordner automatisch mappen ("Sent items", "Sent" => "Sent" etc.)';
+$lang['edit']['skipcrossduplicates'] = 'Duplikate auch über Ordner hinweg überspringen ("first come, first serve")';
+$lang['add']['maxbytespersecond'] = 'Max. Übertragungsrate in Bytes/s (0 für unlimitiert)';
+$lang['add']['automap'] = 'Ordner automatisch mappen ("Sent items", "Sent" => "Sent" etc.)';
+$lang['add']['skipcrossduplicates'] = 'Duplikate auch über Ordner hinweg überspringen ("first come, first serve")';
 $lang['edit']['exclude'] = 'Elemente ausschließen (Regex)';
 $lang['edit']['archive'] = 'Archiv-Zugriff';
 $lang['edit']['max_mailboxes'] = 'Max. Mailboxanzahl:';

+ 6 - 0
data/web/lang/lang.en.php

@@ -306,6 +306,12 @@ $lang['edit']['username'] = 'Username';
 $lang['edit']['hostname'] = 'Hostname';
 $lang['edit']['encryption'] = 'Encryption';
 $lang['edit']['maxage'] = 'Maximum age of messages in days that will be polled from remote<br><small>(0 = ignore age)</small>';
+$lang['edit']['maxbytespersecond'] = 'Max. bytes per second (0 equals to unlimited)';
+$lang['edit']['automap'] = 'Try to automap folders ("Sent items", "Sent" => "Sent" etc.)';
+$lang['edit']['skipcrossduplicates'] = 'Skip duplicate messages across folders (first come, first serve)';
+$lang['add']['maxbytespersecond'] = 'Max. bytes per second (0 equals to unlimited)';
+$lang['add']['automap'] = 'Try to automap folders ("Sent items", "Sent" => "Sent" etc.)';
+$lang['add']['skipcrossduplicates'] = 'Skip duplicate messages across folders (first come, first serve)';
 $lang['edit']['subfolder2'] = 'Sync into subfolder on destination<br><small>(empty = do not use subfolder)</small>';
 $lang['edit']['mins_interval'] = 'Interval (min)';
 $lang['edit']['exclude'] = 'Exclude objects (regex)';

+ 21 - 0
data/web/modals/mailbox.php

@@ -391,6 +391,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
             <small class="help-block">0-32000</small>
 						</div>
 					</div>
+					<div class="form-group">
+						<label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label>
+						<div class="col-sm-10">
+						<input type="number" class="form-control" name="maxbytespersecond" id="maxbytespersecond" min="0" max="125000000" value="0">
+            <small class="help-block">0-125000000</small>
+						</div>
+					</div>
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="exclude"><?=$lang['add']['exclude'];?></label>
 						<div class="col-sm-10">
@@ -418,6 +425,20 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
 							</div>
 						</div>
 					</div>
+          <div class="form-group">
+						<div class="col-sm-offset-2 col-sm-10">
+							<div class="checkbox">
+							<label><input type="checkbox" value="1" name="automap"> <?=$lang['add']['automap'];?></label>
+							</div>
+						</div>
+					</div>
+          <div class="form-group">
+						<div class="col-sm-offset-2 col-sm-10">
+							<div class="checkbox">
+							<label><input type="checkbox" value="1" name="skipcrossduplicates"> <?=$lang['add']['skipcrossduplicates'];?></label>
+							</div>
+						</div>
+					</div>
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">

+ 21 - 0
data/web/modals/user.php

@@ -70,6 +70,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
             <small class="help-block">0-32000</small>
 						</div>
 					</div>
+					<div class="form-group">
+						<label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label>
+						<div class="col-sm-10">
+						<input type="number" class="form-control" name="maxbytespersecond" id="maxbytespersecond" min="0" max="125000000" value="0">
+            <small class="help-block">0-125000000</small>
+						</div>
+					</div>
 					<div class="form-group">
 						<label class="control-label col-sm-2" for="exclude"><?=$lang['add']['exclude'];?></label>
 						<div class="col-sm-10">
@@ -97,6 +104,20 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
 							</div>
 						</div>
 					</div>
+          <div class="form-group">
+						<div class="col-sm-offset-2 col-sm-10">
+							<div class="checkbox">
+							<label><input type="checkbox" value="1" name="automap"> <?=$lang['add']['automap'];?></label>
+							</div>
+						</div>
+					</div>
+          <div class="form-group">
+						<div class="col-sm-offset-2 col-sm-10">
+							<div class="checkbox">
+							<label><input type="checkbox" value="1" name="skipcrossduplicates"> <?=$lang['add']['skipcrossduplicates'];?></label>
+							</div>
+						</div>
+					</div>
 					<div class="form-group">
 						<div class="col-sm-offset-2 col-sm-10">
 							<div class="checkbox">

+ 1 - 1
docker-compose.yml

@@ -148,7 +148,7 @@ services:
             - sogo
 
     dovecot-mailcow:
-      image: mailcow/dovecot:1.17
+      image: mailcow/dovecot:1.18
       build: ./data/Dockerfiles/dovecot
       cap_add:
         - NET_BIND_SERVICE