diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php
index 25b931b6..90a5b638 100644
--- a/data/web/inc/functions.inc.php
+++ b/data/web/inc/functions.inc.php
@@ -552,8 +552,8 @@ function update_sogo_static_view() {
WHERE TABLE_NAME = 'sogo_view'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if ($num_results != 0) {
- $stmt = $pdo->query("REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `kind`, `multiple_bookings`)
- SELECT `c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `kind`, `multiple_bookings` from sogo_view");
+ $stmt = $pdo->query("REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings`)
+ SELECT `c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings` from sogo_view");
$stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');");
}
flush_memcached();
diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php
index d16c3a18..ad5f4156 100644
--- a/data/web/inc/functions.mailbox.inc.php
+++ b/data/web/inc/functions.mailbox.inc.php
@@ -409,6 +409,10 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
);
return false;
}
+ $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 1 AND `send_as` LIKE :domain");
+ $stmt->execute(array(
+ ':domain' => '%@' . $domain
+ ));
$stmt = $pdo->prepare("INSERT INTO `domain` (`domain`, `description`, `aliases`, `mailboxes`, `defquota`, `maxquota`, `quota`, `backupmx`, `gal`, `active`, `relay_all_recipients`)
VALUES (:domain, :description, :aliases, :mailboxes, :defquota, :maxquota, :quota, :backupmx, :gal, :active, :relay_all_recipients)");
$stmt->execute(array(
@@ -710,6 +714,18 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
);
continue;
}
+ $stmt = $pdo->prepare("SELECT `domain` FROM `domain`
+ WHERE `domain`= :target_domain AND `backupmx` = '1'");
+ $stmt->execute(array(':target_domain' => $target_domain));
+ $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
+ if ($num_results == 0) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => array('targetd_relay_domain', htmlspecialchars($target_domain))
+ );
+ continue;
+ }
$stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `alias_domain`= :alias_domain
UNION
SELECT `domain` FROM `domain` WHERE `domain`= :alias_domain_in_domain");
@@ -723,6 +739,10 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
);
continue;
}
+ $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 1 AND `send_as` LIKE :domain");
+ $stmt->execute(array(
+ ':domain' => '%@' . $domain
+ ));
$stmt = $pdo->prepare("INSERT INTO `alias_domain` (`alias_domain`, `target_domain`, `active`)
VALUES (:alias_domain, :target_domain, :active)");
$stmt->execute(array(
@@ -2093,6 +2113,75 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
);
continue;
}
+ $extra_acls = array();
+ if (isset($_data['extended_sender_acl'])) {
+ if (!isset($_SESSION['acl']['extend_sender_acl']) || $_SESSION['acl']['extend_sender_acl'] != "1" ) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => 'access_denied'
+ );
+ return false;
+ }
+ $extra_acls = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['extended_sender_acl']));
+ foreach ($extra_acls as $i => &$extra_acl) {
+ if (empty($extra_acl)) {
+ continue;
+ }
+ if (substr($extra_acl, 0, 1) === "@") {
+ $extra_acl = ltrim($extra_acl, '@');
+ }
+ if (!filter_var($extra_acl, FILTER_VALIDATE_EMAIL) && !is_valid_domain_name($extra_acl)) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => array('extra_acl_invalid', htmlspecialchars($extra_acl))
+ );
+ unset($extra_acls[$i]);
+ continue;
+ }
+ $domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains'));
+ if (filter_var($extra_acl, FILTER_VALIDATE_EMAIL)) {
+ $extra_acl_domain = idn_to_ascii(substr(strstr($extra_acl, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
+ if (in_array($extra_acl_domain, $domains)) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => array('extra_acl_invalid_domain', $extra_acl_domain)
+ );
+ unset($extra_acls[$i]);
+ continue;
+ }
+ }
+ else {
+ if (in_array($extra_acl, $domains)) {
+ $_SESSION['return'][] = array(
+ 'type' => 'danger',
+ 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
+ 'msg' => array('extra_acl_invalid_domain', $extra_acl_domain)
+ );
+ unset($extra_acls[$i]);
+ continue;
+ }
+ $extra_acl = '@' . $extra_acl;
+ }
+ }
+ $extra_acls = array_filter($extra_acls);
+ $extra_acls = array_values($extra_acls);
+ $extra_acls = array_unique($extra_acls);
+ $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 1 AND `logged_in_as` = :username");
+ $stmt->execute(array(
+ ':username' => $username
+ ));
+ foreach ($extra_acls as $sender_acl_external) {
+ $stmt = $pdo->prepare("INSERT INTO `sender_acl` (`send_as`, `logged_in_as`, `external`)
+ VALUES (:sender_acl, :username, 1)");
+ $stmt->execute(array(
+ ':sender_acl' => $sender_acl_external,
+ ':username' => $username
+ ));
+ }
+ }
if (isset($_data['sender_acl'])) {
// Get sender_acl items set by admin
$sender_acl_admin = array_merge(
@@ -2181,7 +2270,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$sender_acl_merged = array_merge($sender_acl_domain_admin, $sender_acl_admin);
// If merged array still contains "*", set it as only value
!in_array('*', $sender_acl_merged) ?: $sender_acl_merged = array('*');
- $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username");
+ $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 0 AND `logged_in_as` = :username");
$stmt->execute(array(
':username' => $username
));
@@ -2204,7 +2293,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
}
}
else {
- $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `logged_in_as` = :username");
+ $stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 0 AND `logged_in_as` = :username");
$stmt->execute(array(
':username' => $username
));
@@ -2359,6 +2448,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$data['sender_acl_addresses']['rw'] = array();
$data['sender_acl_addresses']['selectable'] = array();
$data['fixed_sender_aliases'] = array();
+ $data['external_sender_aliases'] = array();
// Fixed addresses
$stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `goto` REGEXP :goto AND `address` NOT LIKE '@%'");
$stmt->execute(array(':goto' => '(^|,)'.$_data.'($|,)'));
@@ -2376,9 +2466,18 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$data['fixed_sender_aliases'][] = $row['alias_domain_alias'];
}
}
+ // External addresses
+ $stmt = $pdo->prepare("SELECT `send_as` as `send_as_external` FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as AND `external` = '1'");
+ $stmt->execute(array(':logged_in_as' => $_data));
+ $exernal_rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ while ($row = array_shift($exernal_rows)) {
+ if (!empty($row['send_as_external'])) {
+ $data['external_sender_aliases'][] = $row['send_as_external'];
+ }
+ }
// Return array $data['sender_acl_domains/addresses']['ro'] with read-only objects
// Return array $data['sender_acl_domains/addresses']['rw'] with read-write objects (can be deleted)
- $stmt = $pdo->prepare("SELECT REPLACE(`send_as`, '@', '') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as AND (`send_as` LIKE '@%' OR `send_as` = '*')");
+ $stmt = $pdo->prepare("SELECT REPLACE(`send_as`, '@', '') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as AND `external` = '0' AND (`send_as` LIKE '@%' OR `send_as` = '*')");
$stmt->execute(array(':logged_in_as' => $_data));
$domain_rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($domain_row = array_shift($domain_rows)) {
@@ -2397,7 +2496,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$data['sender_acl_domains']['rw'][] = $domain_row['send_as'];
}
}
- $stmt = $pdo->prepare("SELECT `send_as` FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as AND (`send_as` NOT LIKE '@%' AND `send_as` != '*')");
+ $stmt = $pdo->prepare("SELECT `send_as` FROM `sender_acl` WHERE `logged_in_as` = :logged_in_as AND `external` = '0' AND (`send_as` NOT LIKE '@%' AND `send_as` != '*')");
$stmt->execute(array(':logged_in_as' => $_data));
$address_rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($address_row = array_shift($address_rows)) {
@@ -2414,12 +2513,14 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
WHERE `domain` NOT IN (
SELECT REPLACE(`send_as`, '@', '') FROM `sender_acl`
WHERE `logged_in_as` = :logged_in_as1
+ AND `external` = '0'
AND `send_as` LIKE '@%')
UNION
SELECT '*' FROM `domain`
WHERE '*' NOT IN (
SELECT `send_as` FROM `sender_acl`
WHERE `logged_in_as` = :logged_in_as2
+ AND `external` = '0'
)");
$stmt->execute(array(
':logged_in_as1' => $_data,
@@ -2441,6 +2542,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
AND `address` NOT IN (
SELECT `send_as` FROM `sender_acl`
WHERE `logged_in_as` = :logged_in_as
+ AND `external` = '0'
AND `send_as` NOT LIKE '@%')");
$stmt->execute(array(
':logged_in_as' => $_data,
@@ -2909,7 +3011,13 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
':aliasdomain' => $_data,
));
$row = $stmt->fetch(PDO::FETCH_ASSOC);
+ $stmt = $pdo->prepare("SELECT `backupmx` FROM `domain` WHERE `domain` = :target_domain");
+ $stmt->execute(array(
+ ':target_domain' => $row['target_domain']
+ ));
+ $row_parent = $stmt->fetch(PDO::FETCH_ASSOC);
$aliasdomaindata['alias_domain'] = $row['alias_domain'];
+ $aliasdomaindata['parent_is_backupmx'] = $row_parent['backupmx'];
$aliasdomaindata['target_domain'] = $row['target_domain'];
$aliasdomaindata['active'] = $row['active'];
$aliasdomaindata['rl'] = $rl;
diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php
index cd8ca1c7..019c1afb 100644
--- a/data/web/inc/init_db.inc.php
+++ b/data/web/inc/init_db.inc.php
@@ -3,7 +3,7 @@ function init_db_schema() {
try {
global $pdo;
- $db_version = "22082019_2140";
+ $db_version = "01092019_1240";
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
@@ -21,10 +21,16 @@ function init_db_schema() {
AND active = '1'
AND address NOT LIKE '@%'
GROUP BY goto;",
+ // Unused at the moment - we cannot allow to show a foreign mailbox as sender address in SOGo, as SOGo does not like this
+ // We need to create delegation in SOGo AND set a sender_acl in mailcow to allow to send as user X
"grouped_sender_acl" => "CREATE VIEW grouped_sender_acl (username, send_as_acl) AS
SELECT logged_in_as, IFNULL(GROUP_CONCAT(send_as SEPARATOR ' '), '') AS send_as_acl FROM sender_acl
WHERE send_as NOT LIKE '@%'
GROUP BY logged_in_as;",
+ "grouped_sender_acl_external" => "CREATE VIEW grouped_sender_acl_external (username, send_as_acl) AS
+ SELECT logged_in_as, IFNULL(GROUP_CONCAT(send_as SEPARATOR ' '), '') AS send_as_acl FROM sender_acl
+ WHERE send_as NOT LIKE '@%' AND external = '1'
+ GROUP BY logged_in_as;",
"grouped_domain_alias_address" => "CREATE VIEW grouped_domain_alias_address (username, ad_alias) AS
SELECT username, IFNULL(GROUP_CONCAT(local_part, '@', alias_domain SEPARATOR ' '), '') AS ad_alias FROM mailbox
LEFT OUTER JOIN alias_domain ON target_domain=domain
@@ -78,6 +84,7 @@ function init_db_schema() {
// TODO -> use TEXT and check if SOGo login breaks on empty aliases
"aliases" => "TEXT NOT NULL",
"ad_aliases" => "VARCHAR(6144) NOT NULL DEFAULT ''",
+ "ext_acl" => "VARCHAR(6144) NOT NULL DEFAULT ''",
"kind" => "VARCHAR(100) NOT NULL DEFAULT ''",
"multiple_bookings" => "INT NOT NULL DEFAULT -1"
),
@@ -174,7 +181,8 @@ function init_db_schema() {
"cols" => array(
"id" => "INT NOT NULL AUTO_INCREMENT",
"logged_in_as" => "VARCHAR(255) NOT NULL",
- "send_as" => "VARCHAR(255) NOT NULL"
+ "send_as" => "VARCHAR(255) NOT NULL",
+ "external" => "TINYINT(1) NOT NULL DEFAULT '0'"
),
"keys" => array(
"primary" => array(
@@ -466,6 +474,7 @@ function init_db_schema() {
"filters" => "TINYINT(1) NOT NULL DEFAULT '1'",
"ratelimit" => "TINYINT(1) NOT NULL DEFAULT '1'",
"spam_policy" => "TINYINT(1) NOT NULL DEFAULT '1'",
+ "extend_sender_acl" => "TINYINT(1) NOT NULL DEFAULT '0'",
"unlimited_quota" => "TINYINT(1) NOT NULL DEFAULT '0'",
"alias_domains" => "TINYINT(1) NOT NULL DEFAULT '0'",
),
diff --git a/data/web/js/build/014-mailcow.js b/data/web/js/build/014-mailcow.js
index b84272ef..66ff61ad 100644
--- a/data/web/js/build/014-mailcow.js
+++ b/data/web/js/build/014-mailcow.js
@@ -146,6 +146,10 @@ $(document).ready(function() {
$(this).find('button').each(function() {
$(this).attr("disabled", true);
});
+ } else if ($(this).hasClass('form-group')) {
+ $(this).find('input').each(function() {
+ $(this).attr("disabled", true);
+ });
} else if ($(this).hasClass('btn')) {
$(this).attr("disabled", true);
} else if ($(this).attr('data-provide') == 'slider') {
diff --git a/data/web/js/site/index.js b/data/web/js/site/index.js
index 568bbb8a..02de2068 100644
--- a/data/web/js/site/index.js
+++ b/data/web/js/site/index.js
@@ -1,3 +1,4 @@
$(document).ready(function() {
$('nav').hide();
+ localStorage.clear();
});
\ No newline at end of file
diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js
index 9a8e555e..5d18fc64 100644
--- a/data/web/js/site/mailbox.js
+++ b/data/web/js/site/mailbox.js
@@ -282,7 +282,7 @@ jQuery(function($){
},
"filtering": {
"enabled": true,
- "delay": 100,
+ "delay": 1200,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
@@ -401,7 +401,7 @@ jQuery(function($){
},
"filtering": {
"enabled": true,
- "delay": 100,
+ "delay": 1200,
"position": "left",
"connectors": false,
//"container": "#tab-mailboxes.panel",
@@ -475,7 +475,7 @@ jQuery(function($){
},
"filtering": {
"enabled": true,
- "delay": 100,
+ "delay": 1200,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
@@ -547,7 +547,7 @@ jQuery(function($){
},
"filtering": {
"enabled": true,
- "delay": 100,
+ "delay": 1200,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
@@ -611,7 +611,7 @@ jQuery(function($){
},
"filtering": {
"enabled": true,
- "delay": 100,
+ "delay": 1200,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
@@ -681,7 +681,7 @@ jQuery(function($){
},
"filtering": {
"enabled": true,
- "delay": 100,
+ "delay": 1200,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
@@ -749,7 +749,7 @@ jQuery(function($){
},
"filtering": {
"enabled": true,
- "delay": 100,
+ "delay": 1200,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
@@ -843,7 +843,7 @@ jQuery(function($){
},
"filtering": {
"enabled": true,
- "delay": 100,
+ "delay": 1200,
"position": "left",
"connectors": false,
"placeholder": lang.filter_table
@@ -874,7 +874,7 @@ jQuery(function($){
"columns": [
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
{"sorted": true,"name":"alias_domain","title":lang.alias,"style":{"width":"250px"}},
- {"name":"target_domain","title":lang.target_domain},
+ {"name":"target_domain","title":lang.target_domain,"type":"html"},
{"name":"active","filterable": false,"style":{"maxWidth":"50px","width":"70px"},"title":lang.active},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
],
@@ -894,6 +894,11 @@ jQuery(function($){
'
DNS