Expose Postfix's recipient_canonical_maps through web UI
parent
40c5566d0d
commit
e86565e283
|
@ -145,6 +145,16 @@ query = SELECT bcc_dest FROM bcc_maps
|
||||||
AND active='1';
|
AND active='1';
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
cat <<EOF > /opt/postfix/conf/sql/mysql_recipient_canonical_maps.cf
|
||||||
|
user = ${DBUSER}
|
||||||
|
password = ${DBPASS}
|
||||||
|
hosts = mysql
|
||||||
|
dbname = ${DBNAME}
|
||||||
|
query = SELECT new_dest FROM recipient_maps
|
||||||
|
WHERE old_dest='%s'
|
||||||
|
AND active='1';
|
||||||
|
EOF
|
||||||
|
|
||||||
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_domains_maps.cf
|
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_domains_maps.cf
|
||||||
user = ${DBUSER}
|
user = ${DBUSER}
|
||||||
password = ${DBPASS}
|
password = ${DBPASS}
|
||||||
|
|
|
@ -45,6 +45,7 @@ proxy_read_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_sender_acl.cf,
|
||||||
proxy:mysql:/opt/postfix/conf/sql/mysql_tls_enforce_in_policy.cf,
|
proxy:mysql:/opt/postfix/conf/sql/mysql_tls_enforce_in_policy.cf,
|
||||||
proxy:mysql:/opt/postfix/conf/sql/mysql_sender_bcc_maps.cf,
|
proxy:mysql:/opt/postfix/conf/sql/mysql_sender_bcc_maps.cf,
|
||||||
proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_bcc_maps.cf,
|
proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_bcc_maps.cf,
|
||||||
|
proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_canonical_maps.cf,
|
||||||
$local_recipient_maps,
|
$local_recipient_maps,
|
||||||
$mydestination,
|
$mydestination,
|
||||||
$virtual_alias_maps,
|
$virtual_alias_maps,
|
||||||
|
@ -108,6 +109,8 @@ virtual_mailbox_base = /var/vmail/
|
||||||
virtual_mailbox_domains = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_domains_maps.cf
|
virtual_mailbox_domains = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_domains_maps.cf
|
||||||
recipient_bcc_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_bcc_maps.cf
|
recipient_bcc_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_bcc_maps.cf
|
||||||
sender_bcc_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sender_bcc_maps.cf
|
sender_bcc_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sender_bcc_maps.cf
|
||||||
|
recipient_canonical_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_recipient_canonical_maps.cf
|
||||||
|
recipient_canonical_classes = envelope_recipient
|
||||||
virtual_mailbox_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_mailbox_maps.cf
|
virtual_mailbox_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_mailbox_maps.cf
|
||||||
virtual_minimum_uid = 104
|
virtual_minimum_uid = 104
|
||||||
virtual_transport = lmtp:inet:dovecot:24
|
virtual_transport = lmtp:inet:dovecot:24
|
||||||
|
|
|
@ -654,6 +654,43 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elseif (isset($_GET['recipient_map']) && !empty($_GET["recipient_map"])) {
|
||||||
|
$map = intval($_GET["recipient_map"]);
|
||||||
|
$result = recipient_map('details', $map);
|
||||||
|
if (!empty($result)) {
|
||||||
|
?>
|
||||||
|
<h4>Recipient map: <?=$result['recipient_map_old'];?></h4>
|
||||||
|
<br />
|
||||||
|
<form class="form-horizontal" data-id="editrecipient_map" role="form" method="post">
|
||||||
|
<input type="hidden" value="0" name="active">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-sm-2" for="recipient_map_new">New destination</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<textarea id="recipient_map_new" class="form-control" autocapitalize="none" autocorrect="off" rows="10" id="recipient_map_new" name="recipient_map_new" required><?=$result['recipient_map_new'];?></textarea>
|
||||||
|
<small>Recipient map destinations can only be valid email addresses. Separated by whitespace, semicolon, new line or comma.</small>
|
||||||
|
</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="active" <?php if (isset($result['active_int']) && $result['active_int']=="1") { echo "checked"; }; ?>> <?=$lang['edit']['active'];?></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<button class="btn btn-success" id="edit_selected" data-id="editrecipient_map" data-item="<?=$map;?>" data-api-url='edit/recipient_map' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
?>
|
||||||
|
<div class="alert alert-info" role="alert"><?=$lang['info']['no_action'];?></div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($_SESSION['mailcow_cc_role'] == "admin" || $_SESSION['mailcow_cc_role'] == "domainadmin" || $_SESSION['mailcow_cc_role'] == "user") {
|
if ($_SESSION['mailcow_cc_role'] == "admin" || $_SESSION['mailcow_cc_role'] == "domainadmin" || $_SESSION['mailcow_cc_role'] == "user") {
|
||||||
if (isset($_GET['syncjob']) &&
|
if (isset($_GET['syncjob']) &&
|
||||||
|
|
|
@ -290,3 +290,236 @@ function bcc($_action, $_data = null, $attr = null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function recipient_map($_action, $_data = null, $attr = null) {
|
||||||
|
global $pdo;
|
||||||
|
global $lang;
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch ($_action) {
|
||||||
|
case 'add':
|
||||||
|
$old_dest = strtolower(trim($_data['recipient_map_old']));
|
||||||
|
$new_dest = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['recipient_map_new']));
|
||||||
|
$active = intval($_data['active']);
|
||||||
|
if (empty($new_dest)) {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => 'Recipient map destination cannot be empty'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (is_valid_domain_name($old_dest)) {
|
||||||
|
$old_dest_sane = '@' . idn_to_ascii($old_dest);
|
||||||
|
}
|
||||||
|
elseif (filter_var($old_dest, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$old_dest_sane = $old_dest;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => 'Invalid original recipient specified: ' . $old_dest
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foreach ($new_dest as &$new_dest_e) {
|
||||||
|
if (!filter_var($new_dest_e, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$new_dest_e = null;;
|
||||||
|
}
|
||||||
|
$new_dest_e = strtolower($new_dest_e);
|
||||||
|
}
|
||||||
|
$new_dest = array_filter($new_dest);
|
||||||
|
$new_dest = implode(",", $new_dest);
|
||||||
|
if (empty($new_dest)) {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => 'Recipient map destination cannot be empty'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("SELECT `id` FROM `recipient_maps`
|
||||||
|
WHERE `old_dest` = :old_dest");
|
||||||
|
$stmt->execute(array(':old_dest' => $old_dest_sane));
|
||||||
|
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||||
|
}
|
||||||
|
catch(PDOException $e) {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => 'MySQL: '.$e
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($num_results != 0) {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => 'A Recipient map entry "' . htmlspecialchars($old_dest_sane) . '" exists'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO `recipient_maps` (`old_dest`, `new_dest`, `active`) VALUES
|
||||||
|
(:old_dest, :new_dest, :active)");
|
||||||
|
$stmt->execute(array(
|
||||||
|
':old_dest' => $old_dest_sane,
|
||||||
|
':new_dest' => $new_dest,
|
||||||
|
':active' => $active
|
||||||
|
));
|
||||||
|
}
|
||||||
|
catch (PDOException $e) {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => 'MySQL: '.$e
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'msg' => 'Recipient map entry saved'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'edit':
|
||||||
|
$ids = (array)$_data['id'];
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
$is_now = recipient_map('details', $id);
|
||||||
|
if (!empty($is_now)) {
|
||||||
|
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
|
||||||
|
$new_dest = (!empty($_data['recipient_map_new'])) ? $_data['recipient_map_new'] : $is_now['recipient_map_new'];
|
||||||
|
$old_dest = $is_now['old_dest'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => sprintf($lang['danger']['access_denied'])
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$new_dest = array_map('trim', preg_split( "/( |,|;|\n)/", $new_dest));
|
||||||
|
$active = intval($_data['active']);
|
||||||
|
foreach ($new_dest as &$new_dest_e) {
|
||||||
|
if (!filter_var($new_dest_e, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$new_dest_e = null;;
|
||||||
|
}
|
||||||
|
$new_dest_e = strtolower($new_dest_e);
|
||||||
|
}
|
||||||
|
$new_dest = array_filter($new_dest);
|
||||||
|
$new_dest = implode(",", $new_dest);
|
||||||
|
if (empty($new_dest)) {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => 'Recipient map destination cannot be empty'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("SELECT `id` FROM `recipient_maps`
|
||||||
|
WHERE `old_dest` = :old_dest");
|
||||||
|
$stmt->execute(array(':old_dest' => $old_dest));
|
||||||
|
$id_now = $stmt->fetch(PDO::FETCH_ASSOC)['id'];
|
||||||
|
}
|
||||||
|
catch(PDOException $e) {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => 'MySQL: '.$e
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isset($id_now) && $id_now != $id) {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => 'A Recipient map entry ' . htmlspecialchars($old_dest) . ' exists'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("UPDATE `recipient_maps` SET `new_dest` = :new_dest, `active` = :active WHERE `id`= :id");
|
||||||
|
$stmt->execute(array(
|
||||||
|
':new_dest' => $new_dest,
|
||||||
|
':active' => $active,
|
||||||
|
':id' => $id
|
||||||
|
));
|
||||||
|
}
|
||||||
|
catch (PDOException $e) {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => 'MySQL: '.$e
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'msg' => 'Recipient map entry edited'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'details':
|
||||||
|
$mapdata = array();
|
||||||
|
$id = intval($_data);
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("SELECT `id`,
|
||||||
|
`old_dest` AS `recipient_map_old`,
|
||||||
|
`new_dest` AS `recipient_map_new`,
|
||||||
|
`active` AS `active_int`,
|
||||||
|
CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`,
|
||||||
|
`created`,
|
||||||
|
`modified` FROM `recipient_maps`
|
||||||
|
WHERE `id` = :id");
|
||||||
|
$stmt->execute(array(':id' => $id));
|
||||||
|
$mapdata = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
}
|
||||||
|
catch(PDOException $e) {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => 'MySQL: '.$e
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $mapdata;
|
||||||
|
break;
|
||||||
|
case 'get':
|
||||||
|
$mapdata = array();
|
||||||
|
$all_items = array();
|
||||||
|
$id = intval($_data);
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->query("SELECT `id` FROM `recipient_maps`");
|
||||||
|
$all_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
}
|
||||||
|
catch(PDOException $e) {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => 'MySQL: '.$e
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foreach ($all_items as $i) {
|
||||||
|
$mapdata[] = $i['id'];
|
||||||
|
}
|
||||||
|
$all_items = null;
|
||||||
|
return $mapdata;
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
$ids = (array)$_data['id'];
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
if (!is_numeric($id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM `recipient_maps` WHERE `id`= :id");
|
||||||
|
$stmt->execute(array(':id' => $id));
|
||||||
|
}
|
||||||
|
catch (PDOException $e) {
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'msg' => 'MySQL: '.$e
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$_SESSION['return'] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'msg' => 'Deleted Recipient map id/s ' . implode(', ', $ids)
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ function init_db_schema() {
|
||||||
try {
|
try {
|
||||||
global $pdo;
|
global $pdo;
|
||||||
|
|
||||||
$db_version = "02012018_1515";
|
$db_version = "20012021_2202";
|
||||||
|
|
||||||
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
||||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||||
|
@ -394,6 +394,25 @@ function init_db_schema() {
|
||||||
),
|
),
|
||||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||||
),
|
),
|
||||||
|
"recipient_maps" => array(
|
||||||
|
"cols" => array(
|
||||||
|
"id" => "INT NOT NULL AUTO_INCREMENT",
|
||||||
|
"old_dest" => "VARCHAR(255) NOT NULL",
|
||||||
|
"new_dest" => "VARCHAR(255) NOT NULL",
|
||||||
|
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
|
||||||
|
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
|
||||||
|
"active" => "TINYINT(1) NOT NULL DEFAULT '0'"
|
||||||
|
),
|
||||||
|
"keys" => array(
|
||||||
|
"primary" => array(
|
||||||
|
"" => array("id")
|
||||||
|
),
|
||||||
|
"key" => array(
|
||||||
|
"local_dest" => array("old_dest"),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||||
|
),
|
||||||
"tfa" => array(
|
"tfa" => array(
|
||||||
"cols" => array(
|
"cols" => array(
|
||||||
"id" => "INT NOT NULL AUTO_INCREMENT",
|
"id" => "INT NOT NULL AUTO_INCREMENT",
|
||||||
|
|
|
@ -81,7 +81,7 @@ include $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.'.$_SESSION['mailcow_locale'].'.
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.mailbox.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.mailbox.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.customize.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.customize.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.bcc.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.address_rewriting.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.domain_admin.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.domain_admin.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.quarantaine.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.quarantaine.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.policy.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.policy.inc.php';
|
||||||
|
|
|
@ -383,6 +383,52 @@ jQuery(function($){
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function draw_recipient_map_table() {
|
||||||
|
ft_recipient_map_table = FooTable.init('#recipient_map_table', {
|
||||||
|
"columns": [
|
||||||
|
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
||||||
|
{"sorted": true,"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}},
|
||||||
|
{"name":"recipient_map_old","title":lang.recipient_map_old},
|
||||||
|
{"name":"recipient_map_new","title":lang.recipient_map_new},
|
||||||
|
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active},
|
||||||
|
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":(role == "admin" ? lang.action : ""),"breakpoints":"xs sm"}
|
||||||
|
],
|
||||||
|
"empty": lang.empty,
|
||||||
|
"rows": $.ajax({
|
||||||
|
dataType: 'json',
|
||||||
|
url: '/api/v1/get/recipient_map/all',
|
||||||
|
jsonp: false,
|
||||||
|
error: function () {
|
||||||
|
console.log('Cannot draw recipient map table');
|
||||||
|
},
|
||||||
|
success: function (data) {
|
||||||
|
if (role == "admin") {
|
||||||
|
$.each(data, function (i, item) {
|
||||||
|
item.action = '<div class="btn-group">' +
|
||||||
|
'<a href="/edit.php?recipient_map=' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||||
|
'<a href="#" id="delete_selected" data-id="single-recipient_map" data-api-url="delete/recipient_map" data-item="' + item.id + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||||
|
'</div>';
|
||||||
|
item.chkbox = '<input type="checkbox" data-id="recipient_map" name="multi_select" value="' + item.id + '" />';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
"paging": {
|
||||||
|
"enabled": true,
|
||||||
|
"limit": 5,
|
||||||
|
"size": pagination_size
|
||||||
|
},
|
||||||
|
"filtering": {
|
||||||
|
"enabled": true,
|
||||||
|
"position": "left",
|
||||||
|
"connectors": false,
|
||||||
|
"placeholder": lang.filter_table
|
||||||
|
},
|
||||||
|
"sorting": {
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
function draw_alias_table() {
|
function draw_alias_table() {
|
||||||
ft_alias_table = FooTable.init('#alias_table', {
|
ft_alias_table = FooTable.init('#alias_table', {
|
||||||
"columns": [
|
"columns": [
|
||||||
|
@ -609,5 +655,6 @@ jQuery(function($){
|
||||||
draw_sync_job_table();
|
draw_sync_job_table();
|
||||||
draw_filter_table();
|
draw_filter_table();
|
||||||
draw_bcc_table();
|
draw_bcc_table();
|
||||||
|
draw_recipient_map_table();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -595,6 +595,39 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "recipient_map":
|
||||||
|
if (isset($_POST['attr'])) {
|
||||||
|
$attr = (array)json_decode($_POST['attr'], true);
|
||||||
|
if (recipient_map('add', $attr) === false) {
|
||||||
|
if (isset($_SESSION['return'])) {
|
||||||
|
echo json_encode($_SESSION['return']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo json_encode(array(
|
||||||
|
'type' => 'error',
|
||||||
|
'msg' => 'Cannot add item'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (isset($_SESSION['return'])) {
|
||||||
|
echo json_encode($_SESSION['return']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo json_encode(array(
|
||||||
|
'type' => 'success',
|
||||||
|
'msg' => 'Task completed'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo json_encode(array(
|
||||||
|
'type' => 'error',
|
||||||
|
'msg' => 'Cannot find attributes in post data'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "get":
|
case "get":
|
||||||
|
@ -1191,6 +1224,41 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "recipient_map":
|
||||||
|
switch ($object) {
|
||||||
|
case "all":
|
||||||
|
$recipient_map_items = recipient_map('get');
|
||||||
|
if (!empty($recipient_map_items)) {
|
||||||
|
foreach ($recipient_map_items as $recipient_map_item) {
|
||||||
|
if ($details = recipient_map('details', $recipient_map_item)) {
|
||||||
|
$data[] = $details;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isset($data) || empty($data)) {
|
||||||
|
echo '{}';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$data = recipient_map('details', $object);
|
||||||
|
if (!empty($data)) {
|
||||||
|
$data[] = $details;
|
||||||
|
}
|
||||||
|
if (!isset($data) || empty($data)) {
|
||||||
|
echo '{}';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "policy_wl_mailbox":
|
case "policy_wl_mailbox":
|
||||||
switch ($object) {
|
switch ($object) {
|
||||||
default:
|
default:
|
||||||
|
@ -1739,6 +1807,47 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "recipient_map":
|
||||||
|
if (isset($_POST['items'])) {
|
||||||
|
$items = (array)json_decode($_POST['items'], true);
|
||||||
|
if (is_array($items)) {
|
||||||
|
if (recipient_map('delete', array('id' => $items)) === false) {
|
||||||
|
if (isset($_SESSION['return'])) {
|
||||||
|
echo json_encode($_SESSION['return']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo json_encode(array(
|
||||||
|
'type' => 'error',
|
||||||
|
'msg' => 'Deletion of items/s failed'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (isset($_SESSION['return'])) {
|
||||||
|
echo json_encode($_SESSION['return']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo json_encode(array(
|
||||||
|
'type' => 'success',
|
||||||
|
'msg' => 'Task completed'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo json_encode(array(
|
||||||
|
'type' => 'error',
|
||||||
|
'msg' => 'Cannot find id array in post data'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo json_encode(array(
|
||||||
|
'type' => 'error',
|
||||||
|
'msg' => 'Cannot find items in post data'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "fwdhost":
|
case "fwdhost":
|
||||||
if (isset($_POST['items'])) {
|
if (isset($_POST['items'])) {
|
||||||
$items = (array)json_decode($_POST['items'], true);
|
$items = (array)json_decode($_POST['items'], true);
|
||||||
|
@ -2238,6 +2347,50 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "recipient_map":
|
||||||
|
if (isset($_POST['items']) && isset($_POST['attr'])) {
|
||||||
|
$items = (array)json_decode($_POST['items'], true);
|
||||||
|
$attr = (array)json_decode($_POST['attr'], true);
|
||||||
|
$postarray = array_merge(array('id' => $items), $attr);
|
||||||
|
if (is_array($postarray['id'])) {
|
||||||
|
if (recipient_map('edit', $postarray) === false) {
|
||||||
|
if (isset($_SESSION['return'])) {
|
||||||
|
echo json_encode($_SESSION['return']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo json_encode(array(
|
||||||
|
'type' => 'error',
|
||||||
|
'msg' => 'Edit failed'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (isset($_SESSION['return'])) {
|
||||||
|
echo json_encode($_SESSION['return']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo json_encode(array(
|
||||||
|
'type' => 'success',
|
||||||
|
'msg' => 'Task completed'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo json_encode(array(
|
||||||
|
'type' => 'error',
|
||||||
|
'msg' => 'Incomplete post data'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
echo json_encode(array(
|
||||||
|
'type' => 'error',
|
||||||
|
'msg' => 'Incomplete post data'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "alias":
|
case "alias":
|
||||||
if (isset($_POST['items']) && isset($_POST['attr'])) {
|
if (isset($_POST['items']) && isset($_POST['attr'])) {
|
||||||
$items = (array)json_decode($_POST['items'], true);
|
$items = (array)json_decode($_POST['items'], true);
|
||||||
|
|
|
@ -648,5 +648,11 @@ $lang['mailbox']['bcc_maps'] = "BCC maps";
|
||||||
$lang['mailbox']['bcc_to_sender'] = "Switch to sender map type";
|
$lang['mailbox']['bcc_to_sender'] = "Switch to sender map type";
|
||||||
$lang['mailbox']['bcc_to_rcpt'] = "Switch to recipient map type";
|
$lang['mailbox']['bcc_to_rcpt'] = "Switch to recipient map type";
|
||||||
$lang['mailbox']['add_bcc_entry'] = "Add BCC map";
|
$lang['mailbox']['add_bcc_entry'] = "Add BCC map";
|
||||||
$lang['mailbox']['bcc_info'] = "A recipient map type entry is used, when the local destination acts as recipient of a mail. Sender maps conform to the same principle.<br/>
|
$lang['mailbox']['bcc_info'] = "BCC maps are used to silently forward copies of all messages to another address. A recipient map type entry is used, when the local destination acts as recipient of a mail. Sender maps conform to the same principle.<br/>
|
||||||
The local destination will not be informed about a failed delivery.";
|
The local destination will not be informed about a failed delivery.";
|
||||||
|
$lang['mailbox']['address_rewriting'] = 'Address rewriting';
|
||||||
|
$lang['mailbox']['recipient_maps'] = 'Recipient maps';
|
||||||
|
$lang['mailbox']['recipient_map_info'] = 'Recipient maps are used to replace the destination address on a message before it is delivered.';
|
||||||
|
$lang['mailbox']['recipient_map_old'] = 'Original recipient';
|
||||||
|
$lang['mailbox']['recipient_map_new'] = 'New recipient';
|
||||||
|
$lang['mailbox']['add_recipient_map_entry'] = 'Add recipient map';
|
|
@ -21,7 +21,7 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||||
</li>
|
</li>
|
||||||
<li role="presentation"><a href="#tab-syncjobs" aria-controls="tab-syncjobs" role="tab" data-toggle="tab"><?=$lang['mailbox']['sync_jobs'];?></a></li>
|
<li role="presentation"><a href="#tab-syncjobs" aria-controls="tab-syncjobs" role="tab" data-toggle="tab"><?=$lang['mailbox']['sync_jobs'];?></a></li>
|
||||||
<li role="presentation"><a href="#tab-filters" aria-controls="tab-filters" role="tab" data-toggle="tab"><?=$lang['mailbox']['filters'];?></a></li>
|
<li role="presentation"><a href="#tab-filters" aria-controls="tab-filters" role="tab" data-toggle="tab"><?=$lang['mailbox']['filters'];?></a></li>
|
||||||
<li role="presentation"><a href="#tab-bcc" aria-controls="tab-filters" role="tab" data-toggle="tab"><?=$lang['mailbox']['bcc_maps'];?></a></li>
|
<li role="presentation"><a href="#tab-bcc" aria-controls="tab-filters" role="tab" data-toggle="tab"><?=$lang['mailbox']['address_rewriting'];?></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -234,6 +234,34 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title"><?=$lang['mailbox']['recipient_maps'];?></h3>
|
||||||
|
</div>
|
||||||
|
<p style="margin:10px" class="help-block"><?=$lang['mailbox']['recipient_map_info'];?></p>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped" id="recipient_map_table"></table>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "admin"))
|
||||||
|
$display = 'block';
|
||||||
|
else
|
||||||
|
$display = 'none';
|
||||||
|
?>
|
||||||
|
<div class="mass-actions-mailbox" style="display: <?php echo $display; ?>">
|
||||||
|
<div class="btn-group">
|
||||||
|
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="recipient_map" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||||
|
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a id="edit_selected" data-id="recipient_map" data-api-url='edit/recipient_map' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||||
|
<li><a id="edit_selected" data-id="recipient_map" data-api-url='edit/recipient_map' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||||
|
<li role="separator" class="divider"></li>
|
||||||
|
<li><a id="delete_selected" data-id="recipient_map" data-api-url='delete/recipient_map' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||||
|
</ul>
|
||||||
|
<a class="btn btn-sm btn-success" href="#" data-toggle="modal" data-target="#addRecipientMapModalAdmin"><span class="glyphicon glyphicon-plus"></span> <?=$lang['mailbox']['add_recipient_map_entry'];?></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> <!-- /tab-content -->
|
</div> <!-- /tab-content -->
|
||||||
</div> <!-- /col-md-12 -->
|
</div> <!-- /col-md-12 -->
|
||||||
|
|
|
@ -574,6 +574,45 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div><!-- add add_bcc modal -->
|
</div><!-- add add_bcc modal -->
|
||||||
|
<!-- add add_recipient_map modal -->
|
||||||
|
<div class="modal fade" id="addRecipientMapModalAdmin" tabindex="-1" role="dialog" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
|
||||||
|
<h3 class="modal-title"><?=$lang['mailbox']['recipient_maps'];?></h3>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form class="form-horizontal" data-cached-form="true" role="form" data-id="add_recipient_map">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-sm-2" for="recipient_map_old"><?=$lang['mailbox']['recipient_map_old'];?>:</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control" rows="2" id="recipient_map_old" name="recipient_map_old" required></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-sm-2" for="recipient_map_new"><?=$lang['mailbox']['recipient_map_new'];?>:</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control" rows="2" id="recipient_map_new" name="recipient_map_new" required></textarea>
|
||||||
|
</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="active" checked> <?=$lang['add']['active'];?></label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<button class="btn btn-success" id="add_item" data-id="add_recipient_map" data-api-url='add/recipient_map' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!-- add add_recipient_map modal -->
|
||||||
<!-- log modal -->
|
<!-- log modal -->
|
||||||
<div class="modal fade" id="syncjobLogModal" tabindex="-1" role="dialog" aria-labelledby="syncjobLogModalLabel">
|
<div class="modal fade" id="syncjobLogModal" tabindex="-1" role="dialog" aria-labelledby="syncjobLogModalLabel">
|
||||||
<div class="modal-dialog modal-lg" role="document">
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
|
|
|
@ -184,7 +184,7 @@ services:
|
||||||
- dovecot
|
- dovecot
|
||||||
|
|
||||||
postfix-mailcow:
|
postfix-mailcow:
|
||||||
image: mailcow/postfix:1.11
|
image: mailcow/postfix:1.13
|
||||||
build: ./data/Dockerfiles/postfix
|
build: ./data/Dockerfiles/postfix
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/conf/postfix:/opt/postfix/conf
|
- ./data/conf/postfix:/opt/postfix/conf
|
||||||
|
|
Loading…
Reference in New Issue