Merge remote-tracking branch 'upstream/dev' into dns
This commit is contained in:
53
data/web/inc/ajax/container_ctrl.php
Normal file
53
data/web/inc/ajax/container_ctrl.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != 'admin') {
|
||||
exit();
|
||||
}
|
||||
|
||||
if (preg_match('/^[a-z\-]{0,}-mailcow/', $_GET['service'])) {
|
||||
if ($_GET['action'] == "start") {
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
$retry = 0;
|
||||
while (docker($_GET['service'], 'info')['State']['Running'] != 1 && $retry <= 3) {
|
||||
$response = docker($_GET['service'], 'post', 'start');
|
||||
$response = json_decode($response, true);
|
||||
$last_response = ($response['type'] == "success") ? '<b><span class="pull-right text-success">OK</span></b>' : '<b><span class="pull-right text-danger">Error: ' . $response['msg'] . '</span></b>';
|
||||
if ($response['type'] == "success") {
|
||||
break;
|
||||
}
|
||||
usleep(1500000);
|
||||
$retry++;
|
||||
}
|
||||
echo (!isset($last_response)) ? '<b><span class="pull-right text-warning">Already running</span></b>' : $last_response;
|
||||
}
|
||||
if ($_GET['action'] == "stop") {
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
$retry = 0;
|
||||
while (docker($_GET['service'], 'info')['State']['Running'] == 1 && $retry <= 3) {
|
||||
$response = docker($_GET['service'], 'post', 'stop');
|
||||
$response = json_decode($response, true);
|
||||
$last_response = ($response['type'] == "success") ? '<b><span class="pull-right text-success">OK</span></b>' : '<b><span class="pull-right text-danger">Error: ' . $response['msg'] . '</span></b>';
|
||||
if ($response['type'] == "success") {
|
||||
break;
|
||||
}
|
||||
usleep(1500000);
|
||||
$retry++;
|
||||
}
|
||||
echo (!isset($last_response)) ? '<b><span class="pull-right text-warning">Not running</span></b>' : $last_response;
|
||||
}
|
||||
if ($_GET['action'] == "restart") {
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
$response = docker($_GET['service'], 'post', 'restart');
|
||||
$response = json_decode($response, true);
|
||||
$last_response = ($response['type'] == "success") ? '<b><span class="pull-right text-success">OK</span></b>' : '<b><span class="pull-right text-danger">Error: ' . $response['msg'] . '</span></b>';
|
||||
echo (!isset($last_response)) ? '<b><span class="pull-right text-warning">Cannot restart container</span></b>' : $last_response;
|
||||
}
|
||||
if ($_GET['action'] == "logs") {
|
||||
$lines = (empty($_GET['lines']) || !is_numeric($_GET['lines'])) ? 1000 : $_GET['lines'];
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
print_r(preg_split('/\n/', docker($_GET['service'], 'logs', $lines)));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
280
data/web/inc/ajax/dns_diagnostics.php
Normal file
280
data/web/inc/ajax/dns_diagnostics.php
Normal file
@@ -0,0 +1,280 @@
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/spf.inc.php';
|
||||
|
||||
define('state_good', '<span class="text-success">OK</span>');
|
||||
define('state_missing', "✗");
|
||||
define('state_nomatch', "?");
|
||||
define('state_optional', " <sup>2</sup>");
|
||||
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admin") {
|
||||
|
||||
$domains = mailbox('get', 'domains');
|
||||
foreach(mailbox('get', 'domains') as $dn) {
|
||||
$domains = array_merge($domains, mailbox('get', 'alias_domains', $dn));
|
||||
}
|
||||
|
||||
if (isset($_GET['domain'])) {
|
||||
if (is_valid_domain_name($_GET['domain'])) {
|
||||
if (in_array($_GET['domain'], $domains)) {
|
||||
$domain = $_GET['domain'];
|
||||
}
|
||||
else {
|
||||
echo "No such domain in context";
|
||||
die();
|
||||
}
|
||||
}
|
||||
else {
|
||||
echo "Invalid domain name";
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
$ch = curl_init('http://ip4.mailcow.email');
|
||||
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLOPT_HEADER, false);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
|
||||
$ip = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
$ch = curl_init('http://ip6.mailcow.email');
|
||||
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
|
||||
curl_setopt($ch, CURLOPT_VERBOSE, false);
|
||||
curl_setopt($ch, CURLOPT_HEADER, false);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
|
||||
$ip6 = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
$ptr = implode('.', array_reverse(explode('.', $ip))) . '.in-addr.arpa';
|
||||
if (!empty($ip6)) {
|
||||
$ip6_full = str_replace('::', str_repeat(':', 9-substr_count($ip6, ':')), $ip6);
|
||||
$ip6_full = str_replace('::', ':0:', $ip6_full);
|
||||
$ip6_full = str_replace('::', ':0:', $ip6_full);
|
||||
$ptr6 = '';
|
||||
foreach (explode(':', $ip6_full) as $part) {
|
||||
$ptr6 .= str_pad($part, 4, '0', STR_PAD_LEFT);
|
||||
}
|
||||
$ptr6 = implode('.', array_reverse(str_split($ptr6, 1))) . '.ip6.arpa';
|
||||
}
|
||||
|
||||
$https_port = strpos($_SERVER['HTTP_HOST'], ':');
|
||||
if ($https_port === FALSE) {
|
||||
$https_port = 443;
|
||||
} else {
|
||||
$https_port = substr($_SERVER['HTTP_HOST'], $https_port+1);
|
||||
}
|
||||
|
||||
$spf_link = '<a href="http://www.openspf.org/SPF_Record_Syntax" target="_blank">SPF Record Syntax</a>';
|
||||
$dmarc_link = '<a href="http://www.kitterman.com/dmarc/assistant.html" target="_blank">DMARC Assistant</a>';
|
||||
|
||||
$records = array();
|
||||
$records[] = array($mailcow_hostname, 'A', $ip);
|
||||
$records[] = array($ptr, 'PTR', $mailcow_hostname);
|
||||
if (!empty($ip6)) {
|
||||
$records[] = array($mailcow_hostname, 'AAAA', $ip6);
|
||||
$records[] = array($ptr6, 'PTR', $mailcow_hostname);
|
||||
}
|
||||
|
||||
if (!isset($autodiscover_config['sieve'])) {
|
||||
$autodiscover_config['sieve'] = array('server' => $mailcow_hostname, 'port' => array_pop(explode(':', getenv('SIEVE_PORT'))));
|
||||
}
|
||||
|
||||
$records[] = array('_25._tcp.' . $autodiscover_config['smtp']['server'], 'TLSA', generate_tlsa_digest($autodiscover_config['smtp']['server'], 25, 1));
|
||||
$records[] = array('_' . $https_port . '._tcp.' . $mailcow_hostname, 'TLSA', generate_tlsa_digest($mailcow_hostname, $https_port));
|
||||
$records[] = array('_' . $autodiscover_config['pop3']['tlsport'] . '._tcp.' . $autodiscover_config['pop3']['server'], 'TLSA', generate_tlsa_digest($autodiscover_config['pop3']['server'], $autodiscover_config['pop3']['tlsport'], 1));
|
||||
$records[] = array('_' . $autodiscover_config['imap']['tlsport'] . '._tcp.' . $autodiscover_config['imap']['server'], 'TLSA', generate_tlsa_digest($autodiscover_config['imap']['server'], $autodiscover_config['imap']['tlsport'], 1));
|
||||
$records[] = array('_' . $autodiscover_config['smtp']['port'] . '._tcp.' . $autodiscover_config['smtp']['server'], 'TLSA', generate_tlsa_digest($autodiscover_config['smtp']['server'], $autodiscover_config['smtp']['port']));
|
||||
$records[] = array('_' . $autodiscover_config['smtp']['tlsport'] . '._tcp.' . $autodiscover_config['smtp']['server'], 'TLSA', generate_tlsa_digest($autodiscover_config['smtp']['server'], $autodiscover_config['smtp']['tlsport'], 1));
|
||||
$records[] = array('_' . $autodiscover_config['imap']['port'] . '._tcp.' . $autodiscover_config['imap']['server'], 'TLSA', generate_tlsa_digest($autodiscover_config['imap']['server'], $autodiscover_config['imap']['port']));
|
||||
$records[] = array('_' . $autodiscover_config['pop3']['port'] . '._tcp.' . $autodiscover_config['pop3']['server'], 'TLSA', generate_tlsa_digest($autodiscover_config['pop3']['server'], $autodiscover_config['pop3']['port']));
|
||||
$records[] = array('_' . $autodiscover_config['sieve']['port'] . '._tcp.' . $autodiscover_config['sieve']['server'], 'TLSA', generate_tlsa_digest($autodiscover_config['sieve']['server'], $autodiscover_config['sieve']['port'], 1));
|
||||
$records[] = array($domain, 'MX', $mailcow_hostname);
|
||||
$records[] = array('autodiscover.' . $domain, 'CNAME', $mailcow_hostname);
|
||||
$records[] = array('_autodiscover._tcp.' . $domain, 'SRV', $mailcow_hostname . ' ' . $https_port);
|
||||
$records[] = array('autoconfig.' . $domain, 'CNAME', $mailcow_hostname);
|
||||
$records[] = array($domain, 'TXT', $spf_link, state_optional);
|
||||
$records[] = array('_dmarc.' . $domain, 'TXT', $dmarc_link, state_optional);
|
||||
|
||||
if (!empty($dkim = dkim('details', $domain))) {
|
||||
$records[] = array($dkim['dkim_selector'] . '._domainkey.' . $domain, 'TXT', $dkim['dkim_txt']);
|
||||
}
|
||||
|
||||
$current_records = dns_get_record('_pop3._tcp.' . $domain, DNS_SRV);
|
||||
if (count($current_records) == 0 || $current_records[0]['target'] != '') {
|
||||
if ($autodiscover_config['pop3']['tlsport'] != '110') {
|
||||
$records[] = array('_pop3._tcp.' . $domain, 'SRV', $autodiscover_config['pop3']['server'] . ' ' . $autodiscover_config['pop3']['tlsport']);
|
||||
}
|
||||
} else {
|
||||
$records[] = array('_pop3._tcp.' . $domain, 'SRV', '. 0');
|
||||
}
|
||||
$current_records = dns_get_record('_pop3s._tcp.' . $domain, DNS_SRV);
|
||||
if (count($current_records) == 0 || $current_records[0]['target'] != '') {
|
||||
if ($autodiscover_config['pop3']['port'] != '995') {
|
||||
$records[] = array('_pop3s._tcp.' . $domain, 'SRV', $autodiscover_config['pop3']['server'] . ' ' . $autodiscover_config['pop3']['port']);
|
||||
}
|
||||
} else {
|
||||
$records[] = array('_pop3s._tcp.' . $domain, 'SRV', '. 0');
|
||||
}
|
||||
if ($autodiscover_config['imap']['tlsport'] != '143') {
|
||||
$records[] = array('_imap._tcp.' . $domain, 'SRV', $autodiscover_config['imap']['server'] . ' ' . $autodiscover_config['imap']['tlsport']);
|
||||
}
|
||||
if ($autodiscover_config['imap']['port'] != '993') {
|
||||
$records[] = array('_imaps._tcp.' . $domain, 'SRV', $autodiscover_config['imap']['server'] . ' ' . $autodiscover_config['imap']['port']);
|
||||
}
|
||||
if ($autodiscover_config['smtp']['tlsport'] != '587') {
|
||||
$records[] = array('_submission._tcp.' . $domain, 'SRV', $autodiscover_config['smtp']['server'] . ' ' . $autodiscover_config['smtp']['tlsport']);
|
||||
}
|
||||
if ($autodiscover_config['smtp']['port'] != '465') {
|
||||
$records[] = array('_smtps._tcp.' . $domain, 'SRV', $autodiscover_config['smtp']['server'] . ' ' . $autodiscover_config['smtp']['port']);
|
||||
}
|
||||
if ($autodiscover_config['sieve']['port'] != '4190') {
|
||||
$records[] = array('_sieve._tcp.' . $domain, 'SRV', $autodiscover_config['sieve']['server'] . ' ' . $autodiscover_config['sieve']['port']);
|
||||
}
|
||||
|
||||
$record_types = array(
|
||||
'A' => DNS_A,
|
||||
'AAAA' => DNS_AAAA,
|
||||
'CNAME' => DNS_CNAME,
|
||||
'MX' => DNS_MX,
|
||||
'PTR' => DNS_PTR,
|
||||
'SRV' => DNS_SRV,
|
||||
'TXT' => DNS_TXT,
|
||||
);
|
||||
$data_field = array(
|
||||
'A' => 'ip',
|
||||
'AAAA' => 'ipv6',
|
||||
'CNAME' => 'target',
|
||||
'MX' => 'target',
|
||||
'PTR' => 'target',
|
||||
'SRV' => 'data',
|
||||
'TLSA' => 'data',
|
||||
'TXT' => 'txt',
|
||||
);
|
||||
?>
|
||||
<div class="table-responsive" id="dnstable">
|
||||
<table class="table table-striped">
|
||||
<tr> <th><?=$lang['diagnostics']['dns_records_name'];?></th> <th><?=$lang['diagnostics']['dns_records_type'];?></th> <th><?=$lang['diagnostics']['dns_records_data'];?></th ><th><?=$lang['diagnostics']['dns_records_status'];?></th> </tr>
|
||||
<?php
|
||||
foreach ($records as $record) {
|
||||
$record[1] = strtoupper($record[1]);
|
||||
$state = state_missing;
|
||||
if ($record[1] == 'TLSA') {
|
||||
$currents = dns_get_record($record[0], 52, $_, $_, TRUE);
|
||||
foreach ($currents as &$current) {
|
||||
$current['type'] = 'TLSA';
|
||||
$current['cert_usage'] = hexdec(bin2hex($current['data']{0}));
|
||||
$current['selector'] = hexdec(bin2hex($current['data']{1}));
|
||||
$current['match_type'] = hexdec(bin2hex($current['data']{2}));
|
||||
$current['cert_data'] = bin2hex(substr($current['data'], 3));
|
||||
$current['data'] = $current['cert_usage'] . ' ' . $current['selector'] . ' ' . $current['match_type'] . ' ' . $current['cert_data'];
|
||||
}
|
||||
unset($current);
|
||||
}
|
||||
else {
|
||||
$currents = dns_get_record($record[0], $record_types[$record[1]]);
|
||||
if ($record[1] == 'SRV') {
|
||||
foreach ($currents as &$current) {
|
||||
if ($current['target'] == '') {
|
||||
$current['target'] = '.';
|
||||
$current['port'] = '0';
|
||||
}
|
||||
$current['data'] = $current['target'] . ' ' . $current['port'];
|
||||
}
|
||||
unset($current);
|
||||
}
|
||||
elseif ($record[1] == 'TXT') {
|
||||
foreach ($currents as &$current) {
|
||||
if ($current['host'] != $record[0]) {
|
||||
$current['type'] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($record[1] == 'CNAME' && count($currents) == 0) {
|
||||
// A and AAAA are also valid instead of CNAME
|
||||
$a = dns_get_record($record[0], DNS_A);
|
||||
$cname = dns_get_record($record[2], DNS_A);
|
||||
if (count($a) > 0 && count($cname) > 0) {
|
||||
if ($a[0]['ip'] == $cname[0]['ip']) {
|
||||
$currents = array(array('host' => $record[0], 'class' => 'IN', 'type' => 'CNAME', 'target' => $record[2]));
|
||||
$aaaa = dns_get_record($record[0], DNS_AAAA);
|
||||
$cname = dns_get_record($record[2], DNS_AAAA);
|
||||
if (count($aaaa) == 0 || count($cname) == 0 || $aaaa[0]['ipv6'] != $cname[0]['ipv6']) {
|
||||
$currents[0]['target'] = $aaaa[0]['ipv6'] . ' <sup>1</sup>';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$currents = array(array('host' => $record[0], 'class' => 'IN', 'type' => 'CNAME', 'target' => $a[0]['ip'] . ' <sup>1</sup>'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($currents as &$current) {
|
||||
if ($current['type'] != $record[1]) {
|
||||
unset($current);
|
||||
continue;
|
||||
}
|
||||
elseif ($current['type'] == 'TXT' &&
|
||||
stripos($current['txt'], 'v=dmarc') === 0 &&
|
||||
$record[2] == $dmarc_link) {
|
||||
$current['txt'] = str_replace(' ', '', $current['txt']);
|
||||
$state = $current[$data_field[$current['type']]] . state_optional;
|
||||
}
|
||||
elseif ($current['type'] == 'TXT' &&
|
||||
stripos($current['txt'], 'v=spf' &&
|
||||
$record[2] == $spf_link) === 0) {
|
||||
$state = $current[$data_field[$current['type']]] . state_optional;
|
||||
}
|
||||
elseif ($current['type'] == 'TXT' &&
|
||||
stripos($current['txt'], 'v=dkim') === 0 &&
|
||||
stripos($record[2], 'v=dkim') === 0) {
|
||||
$current['txt'] = str_replace(' ', '', $current['txt']);
|
||||
if ($current[$data_field[$current['type']]] == $record[2]) {
|
||||
$state = state_good;
|
||||
}
|
||||
}
|
||||
elseif ($current['type'] != 'TXT' &&
|
||||
isset($data_field[$current['type']]) && $state != state_good) {
|
||||
$state = state_nomatch;
|
||||
if ($current[$data_field[$current['type']]] == $record[2]) {
|
||||
$state = state_good;
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($current);
|
||||
|
||||
if (isset($record[3]) && $record[3] == state_optional && ($state == state_missing || $state == state_nomatch)) {
|
||||
$state = state_optional;
|
||||
}
|
||||
|
||||
if ($state == state_nomatch) {
|
||||
$state = array();
|
||||
foreach ($currents as $current) {
|
||||
$state[] = $current[$data_field[$current['type']]];
|
||||
}
|
||||
$state = implode('<br />', $state);
|
||||
}
|
||||
echo sprintf('<tr>
|
||||
<td>%s</td>
|
||||
<td>%s</td>
|
||||
<td class="dns-found">%s</td>
|
||||
<td class="dns-recommended">%s</td>
|
||||
</tr>', $record[0], $record[1], $record[2], $state);
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
</div>
|
||||
<p class="help-block">
|
||||
<sup>1</sup> <?=$lang['diagnostics']['cname_from_a'];?><br />
|
||||
<sup>2</sup> <?=$lang['diagnostics']['optional'];?>
|
||||
</p>
|
||||
<?php
|
||||
} else {
|
||||
echo "Session invalid";
|
||||
die();
|
||||
}
|
||||
?>
|
12
data/web/inc/ajax/log_driver.php
Normal file
12
data/web/inc/ajax/log_driver.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
header('Content-Type: text/plain');
|
||||
if (!isset($_SESSION['mailcow_cc_role'])) {
|
||||
exit();
|
||||
}
|
||||
if (isset($_GET['type']) && isset($_GET['msg'])) {
|
||||
global $mailcow_hostname;
|
||||
//empty
|
||||
}
|
||||
?>
|
83
data/web/inc/ajax/qitem_details.php
Normal file
83
data/web/inc/ajax/qitem_details.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
session_start();
|
||||
header("Content-Type: application/json");
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
if (!isset($_SESSION['mailcow_cc_role'])) {
|
||||
exit();
|
||||
}
|
||||
function rrmdir($src) {
|
||||
$dir = opendir($src);
|
||||
while(false !== ( $file = readdir($dir)) ) {
|
||||
if (( $file != '.' ) && ( $file != '..' )) {
|
||||
$full = $src . '/' . $file;
|
||||
if ( is_dir($full) ) {
|
||||
rrmdir($full);
|
||||
}
|
||||
else {
|
||||
unlink($full);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($dir);
|
||||
rmdir($src);
|
||||
}
|
||||
if (!empty($_GET['id']) && ctype_alnum($_GET['id'])) {
|
||||
$tmpdir = '/tmp/' . $_GET['id'] . '/';
|
||||
$mailc = quarantaine('details', $_GET['id']);
|
||||
if (strlen($mailc['msg']) > 10485760) {
|
||||
echo json_encode(array('error' => 'Message size exceeds 10 MiB.'));
|
||||
exit;
|
||||
}
|
||||
if (!empty($mailc['msg'])) {
|
||||
// Init message array
|
||||
$data = array();
|
||||
// Init parser
|
||||
$mail_parser = new PhpMimeMailParser\Parser();
|
||||
// Load msg to parser
|
||||
$mail_parser->setText($mailc['msg']);
|
||||
// Get text/plain content
|
||||
$data['text_plain'] = $mail_parser->getMessageBody('text');
|
||||
// Get subject
|
||||
$data['subject'] = $mail_parser->getHeader('subject');
|
||||
// Get attachments
|
||||
if (is_dir($tmpdir)) {
|
||||
rrmdir($tmpdir);
|
||||
}
|
||||
mkdir('/tmp/' . $_GET['id']);
|
||||
$mail_parser->saveAttachments($tmpdir, true);
|
||||
$atts = $mail_parser->getAttachments(true);
|
||||
if (count($atts) > 0) {
|
||||
foreach ($atts as $key => $val) {
|
||||
$data['attachments'][$key] = array(
|
||||
// Index
|
||||
// 0 => file name
|
||||
// 1 => mime type
|
||||
// 2 => file size
|
||||
// 3 => vt link by sha256
|
||||
$val->getFilename(),
|
||||
$val->getContentType(),
|
||||
filesize($tmpdir . $val->getFilename()),
|
||||
'https://www.virustotal.com/file/' . hash_file('SHA256', $tmpdir . $val->getFilename()) . '/analysis/'
|
||||
);
|
||||
}
|
||||
}
|
||||
if (isset($_GET['att'])) {
|
||||
$dl_id = intval($_GET['att']);
|
||||
$dl_filename = $data['attachments'][$dl_id][0];
|
||||
if (!is_dir($tmpdir . $dl_filename) && file_exists($tmpdir . $dl_filename)) {
|
||||
header('Pragma: public');
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
|
||||
header('Cache-Control: private', false);
|
||||
header('Content-Type: ' . $data['attachments'][$dl_id][1]);
|
||||
header('Content-Disposition: attachment; filename="'. $dl_filename . '";');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header('Content-Length: ' . $data['attachments'][$dl_id][2]);
|
||||
readfile($tmpdir . $dl_filename);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
echo json_encode($data);
|
||||
}
|
||||
}
|
||||
?>
|
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != 'admin') {
|
||||
exit();
|
||||
}
|
||||
|
||||
if ($_GET['ACTION'] == "start") {
|
||||
$retry = 0;
|
||||
while (docker('sogo-mailcow', 'info')['State']['Running'] != 1 && $retry <= 3) {
|
||||
$response = docker('sogo-mailcow', 'post', 'start');
|
||||
$response = json_decode($response, true);
|
||||
$last_response = ($response['type'] == "success") ? '<b><span class="pull-right text-success">OK</span></b>' : '<b><span class="pull-right text-danger">Error: ' . $response['msg'] . '</span></b>';
|
||||
if ($response['type'] == "success") {
|
||||
break;
|
||||
}
|
||||
usleep(1500000);
|
||||
$retry++;
|
||||
}
|
||||
echo (!isset($last_response)) ? '<b><span class="pull-right text-warning">Already running</span></b>' : $last_response;
|
||||
}
|
||||
|
||||
if ($_GET['ACTION'] == "stop") {
|
||||
$retry = 0;
|
||||
while (docker('sogo-mailcow', 'info')['State']['Running'] == 1 && $retry <= 3) {
|
||||
$response = docker('sogo-mailcow', 'post', 'stop');
|
||||
$response = json_decode($response, true);
|
||||
$last_response = ($response['type'] == "success") ? '<b><span class="pull-right text-success">OK</span></b>' : '<b><span class="pull-right text-danger">Error: ' . $response['msg'] . '</span></b>';
|
||||
if ($response['type'] == "success") {
|
||||
break;
|
||||
}
|
||||
usleep(1500000);
|
||||
$retry++;
|
||||
}
|
||||
echo (!isset($last_response)) ? '<b><span class="pull-right text-warning">Not running</span></b>' : $last_response;
|
||||
}
|
||||
|
||||
?>
|
@@ -8,6 +8,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/modals/footer.php';
|
||||
<script src="/js/bootstrap-select.min.js"></script>
|
||||
<script src="/js/bootstrap-filestyle.min.js"></script>
|
||||
<script src="/js/notifications.min.js"></script>
|
||||
<script src="/js/formcache.min.js"></script>
|
||||
<script src="/js/numberedtextarea.min.js"></script>
|
||||
<script src="/js/u2f-api.js"></script>
|
||||
<script src="/js/api.js"></script>
|
||||
@@ -26,11 +27,19 @@ $(document).ready(function() {
|
||||
msg = $('<span/>').html(message).text();
|
||||
if (type == 'danger') {
|
||||
auto_hide = 0;
|
||||
$('#' + localStorage.getItem("add_modal")).modal('show');
|
||||
localStorage.removeItem("add_modal");
|
||||
} else {
|
||||
auto_hide = 5000;
|
||||
}
|
||||
$.ajax({
|
||||
url: '/inc/ajax/log_driver.php',
|
||||
data: {"type": type,"msg": msg},
|
||||
type: "GET"
|
||||
});
|
||||
$.notify({message: msg},{z_index: 20000, delay: auto_hide, type: type,placement: {from: "bottom",align: "right"},animate: {enter: 'animated fadeInUp',exit: 'animated fadeOutDown'}});
|
||||
}
|
||||
$('[data-cached-form="true"]').formcache({key: $(this).data('id')});
|
||||
<?php if (isset($_SESSION['return'])): ?>
|
||||
mailcow_alert_box(<?=json_encode($_SESSION['return']['msg']); ?>, "<?= $_SESSION['return']['type']; ?>");
|
||||
<?php endif; unset($_SESSION['return']); ?>
|
||||
@@ -40,6 +49,7 @@ $(document).ready(function() {
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
});
|
||||
$('#u2f_status_auth').html('<p><span class="glyphicon glyphicon-refresh glyphicon-spin"></span> Initializing, please wait...</p>');
|
||||
$('#ConfirmTFAModal').on('shown.bs.modal', function(){
|
||||
$(this).find('#token').focus();
|
||||
// If U2F
|
||||
@@ -49,20 +59,21 @@ $(document).ready(function() {
|
||||
cache: false,
|
||||
dataType: 'script',
|
||||
url: "/api/v1/get/u2f-authentication/<?= (isset($_SESSION['pending_mailcow_cc_username'])) ? $_SESSION['pending_mailcow_cc_username'] : null; ?>",
|
||||
success: function(data){
|
||||
complete: function(data){
|
||||
$('#u2f_status_auth').html('<?=$lang['tfa']['waiting_usb_auth'];?>');
|
||||
data;
|
||||
setTimeout(function() {
|
||||
console.log("Ready to authenticate");
|
||||
u2f.sign(appId, challenge, registeredKeys, function(data) {
|
||||
var form = document.getElementById('u2f_auth_form');
|
||||
var auth = document.getElementById('u2f_auth_data');
|
||||
console.log("Authenticate callback", data);
|
||||
auth.value = JSON.stringify(data);
|
||||
form.submit();
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
setTimeout(function() {
|
||||
console.log("sign: ", req);
|
||||
u2f.sign(req, function(data) {
|
||||
var form = document.getElementById('u2f_auth_form');
|
||||
var auth = document.getElementById('u2f_auth_data');
|
||||
console.log("Authenticate callback", data);
|
||||
auth.value = JSON.stringify(data);
|
||||
form.submit();
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
<?php endif; ?>
|
||||
@@ -81,32 +92,34 @@ $(document).ready(function() {
|
||||
if ($(this).val() == "u2f") {
|
||||
$('#U2FModal').modal('show');
|
||||
$("option:selected").prop("selected", false);
|
||||
$('#u2f_status_reg').html('<p><span class="glyphicon glyphicon-refresh glyphicon-spin"></span> Initializing, please wait...</p>');
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
cache: false,
|
||||
dataType: 'script',
|
||||
url: "/api/v1/get/u2f-registration/<?= (isset($_SESSION['mailcow_cc_username'])) ? $_SESSION['mailcow_cc_username'] : null; ?>",
|
||||
success: function(data){
|
||||
complete: function(data){
|
||||
data;
|
||||
setTimeout(function() {
|
||||
console.log("Ready to register");
|
||||
$('#u2f_status_reg').html('<?=$lang['tfa']['waiting_usb_register'];?>');
|
||||
u2f.register(appId, registerRequests, registeredKeys, function(deviceResponse) {
|
||||
var form = document.getElementById('u2f_reg_form');
|
||||
var reg = document.getElementById('u2f_register_data');
|
||||
console.log("Register callback: ", data);
|
||||
if (deviceResponse.errorCode && deviceResponse.errorCode != 0) {
|
||||
var u2f_return_code = document.getElementById('u2f_return_code');
|
||||
u2f_return_code.style.display = u2f_return_code.style.display === 'none' ? '' : null;
|
||||
if (deviceResponse.errorCode == "4") { deviceResponse.errorCode = "4 - The presented device is not eligible for this request. For a registration request this may mean that the token is already registered, and for a sign request it may mean that the token does not know the presented key handle"; }
|
||||
u2f_return_code.innerHTML = 'Error code: ' + deviceResponse.errorCode;
|
||||
return;
|
||||
}
|
||||
reg.value = JSON.stringify(deviceResponse);
|
||||
form.submit();
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
setTimeout(function() {
|
||||
console.log("Register: ", req);
|
||||
u2f.register([req], sigs, function(data) {
|
||||
var form = document.getElementById('u2f_reg_form');
|
||||
var reg = document.getElementById('u2f_register_data');
|
||||
console.log("Register callback", data);
|
||||
if (data.errorCode && data.errorCode != 0) {
|
||||
var u2f_return_code = document.getElementById('u2f_return_code');
|
||||
u2f_return_code.style.display = u2f_return_code.style.display === 'none' ? '' : null;
|
||||
if (data.errorCode == "4") { data.errorCode = "4 - The presented device is not eligible for this request. For a registration request this may mean that the token is already registered, and for a sign request it may mean that the token does not know the presented key handle"; }
|
||||
u2f_return_code.innerHTML = 'Error code: ' + data.errorCode;
|
||||
return;
|
||||
}
|
||||
reg.value = JSON.stringify(data);
|
||||
form.submit();
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
if ($(this).val() == "none") {
|
||||
$('#DisableTFAModal').modal('show');
|
||||
@@ -114,13 +127,8 @@ $(document).ready(function() {
|
||||
}
|
||||
});
|
||||
|
||||
// Activate tooltips
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
})
|
||||
// Hide alerts after n seconds
|
||||
$("#alert-fade").fadeTo(7000, 500).slideUp(500, function(){
|
||||
$("#alert-fade").alert('close');
|
||||
});
|
||||
|
||||
// Remember last navigation pill
|
||||
@@ -169,36 +177,32 @@ $(document).ready(function() {
|
||||
// Init Bootstrap Selectpicker
|
||||
$('select').selectpicker();
|
||||
|
||||
// Trigger SOGo restart
|
||||
$('#triggerRestartSogo').click(function(){
|
||||
$(this).prop("disabled",true);
|
||||
$(this).html('<span class="glyphicon glyphicon-refresh glyphicon-spin"></span> ');
|
||||
$('#statusTriggerRestartSogo').text('Stopping SOGo workers, this may take a while... ');
|
||||
$.ajax({
|
||||
method: 'get',
|
||||
url: '/inc/ajax/sogo_ctrl.php',
|
||||
data: {
|
||||
'ajax': true,
|
||||
'ACTION': 'stop'
|
||||
},
|
||||
success: function(data) {
|
||||
$('#statusTriggerRestartSogo').append(data);
|
||||
$('#statusTriggerRestartSogo').append('<br>Starting SOGo...');
|
||||
$.ajax({
|
||||
method: 'get',
|
||||
url: '/inc/ajax/sogo_ctrl.php',
|
||||
data: {
|
||||
'ajax': true,
|
||||
'ACTION': 'start'
|
||||
},
|
||||
success: function(data) {
|
||||
$('#statusTriggerRestartSogo').append(data);
|
||||
$('#triggerRestartSogo').html('<span class="glyphicon glyphicon-ok"></span> ');
|
||||
}
|
||||
});
|
||||
}
|
||||
// Trigger container restart
|
||||
$('#RestartContainer').on('show.bs.modal', function(e) {
|
||||
var container = $(e.relatedTarget).data('container');
|
||||
$('#containerName').text(container);
|
||||
$('#triggerRestartContainer').click(function(){
|
||||
$(this).prop("disabled",true);
|
||||
$(this).html('<span class="glyphicon glyphicon-refresh glyphicon-spin"></span> ');
|
||||
$('#statusTriggerRestartContainer').text('Restarting container, this may take a while... ');
|
||||
$.ajax({
|
||||
method: 'get',
|
||||
url: '/inc/ajax/container_ctrl.php',
|
||||
timeout: 10000,
|
||||
data: {
|
||||
'service': container,
|
||||
'action': 'restart'
|
||||
},
|
||||
error: function() {
|
||||
window.location = window.location.href.split("#")[0];
|
||||
},
|
||||
success: function(data) {
|
||||
$('#statusTriggerRestartContainer').append(data);
|
||||
$('#triggerRestartContainer').html('<span class="glyphicon glyphicon-ok"></span> ');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
// CSRF
|
||||
$('<input type="hidden" value="<?= $_SESSION['CSRF']['TOKEN']; ?>">').attr('id', 'csrf_token').attr('name', 'csrf_token').appendTo('form');
|
||||
|
292
data/web/inc/functions.bcc.inc.php
Normal file
292
data/web/inc/functions.bcc.inc.php
Normal file
@@ -0,0 +1,292 @@
|
||||
<?php
|
||||
function bcc($_action, $_data = null, $attr = null) {
|
||||
global $pdo;
|
||||
global $lang;
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
|
||||
return false;
|
||||
}
|
||||
switch ($_action) {
|
||||
case 'add':
|
||||
if (!isset($_SESSION['acl']['bcc_maps']) || $_SESSION['acl']['bcc_maps'] != "1" ) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$local_dest = strtolower(trim($_data['local_dest']));
|
||||
$bcc_dest = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['bcc_dest']));
|
||||
$active = intval($_data['active']);
|
||||
$type = $_data['type'];
|
||||
if ($type != 'sender' && $type != 'rcpt') {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Invalid BCC map type'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (empty($bcc_dest)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'BCC destination cannot be empty'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (is_valid_domain_name($local_dest)) {
|
||||
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $local_dest)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$domain = idn_to_ascii($local_dest);
|
||||
$local_dest_sane = '@' . idn_to_ascii($local_dest);
|
||||
}
|
||||
elseif (filter_var($local_dest, FILTER_VALIDATE_EMAIL)) {
|
||||
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $local_dest)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$domain = mailbox('get', 'mailbox_details', $local_dest)['domain'];
|
||||
if (empty($domain)) {
|
||||
return false;
|
||||
}
|
||||
$local_dest_sane = $local_dest;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
foreach ($bcc_dest as &$bcc_dest_e) {
|
||||
if (!filter_var($bcc_dest_e, FILTER_VALIDATE_EMAIL)) {
|
||||
$bcc_dest_e = null;;
|
||||
}
|
||||
$bcc_dest_e = strtolower($bcc_dest_e);
|
||||
}
|
||||
$bcc_dest = array_filter($bcc_dest);
|
||||
$bcc_dest = implode(",", $bcc_dest);
|
||||
if (empty($bcc_dest)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'BCC map destination cannot be empty'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT `id` FROM `bcc_maps`
|
||||
WHERE `local_dest` = :local_dest AND `type` = :type");
|
||||
$stmt->execute(array(':local_dest' => $local_dest_sane, ':type' => $type));
|
||||
$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 BCC map entry "' . htmlspecialchars($local_dest_sane) . '" exists for type "' . $type . '"'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("INSERT INTO `bcc_maps` (`local_dest`, `bcc_dest`, `domain`, `active`, `type`) VALUES
|
||||
(:local_dest, :bcc_dest, :domain, :active, :type)");
|
||||
$stmt->execute(array(
|
||||
':local_dest' => $local_dest_sane,
|
||||
':bcc_dest' => $bcc_dest,
|
||||
':domain' => $domain,
|
||||
':active' => $active,
|
||||
':type' => $type
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'MySQL: '.$e
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'success',
|
||||
'msg' => 'BCC map entry saved'
|
||||
);
|
||||
break;
|
||||
case 'edit':
|
||||
if (!isset($_SESSION['acl']['bcc_maps']) || $_SESSION['acl']['bcc_maps'] != "1" ) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$ids = (array)$_data['id'];
|
||||
foreach ($ids as $id) {
|
||||
$is_now = bcc('details', $id);
|
||||
if (!empty($is_now)) {
|
||||
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
|
||||
$bcc_dest = (!empty($_data['bcc_dest'])) ? $_data['bcc_dest'] : $is_now['bcc_dest'];
|
||||
$local_dest = $is_now['local_dest'];
|
||||
$type = (!empty($_data['type'])) ? $_data['type'] : $is_now['type'];
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$bcc_dest = array_map('trim', preg_split( "/( |,|;|\n)/", $bcc_dest));
|
||||
$active = intval($_data['active']);
|
||||
foreach ($bcc_dest as &$bcc_dest_e) {
|
||||
if (!filter_var($bcc_dest_e, FILTER_VALIDATE_EMAIL)) {
|
||||
$bcc_dest_e = null;;
|
||||
}
|
||||
$bcc_dest_e = strtolower($bcc_dest_e);
|
||||
}
|
||||
$bcc_dest = array_filter($bcc_dest);
|
||||
$bcc_dest = implode(",", $bcc_dest);
|
||||
if (empty($bcc_dest)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'BCC map destination cannot be empty'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT `id` FROM `bcc_maps`
|
||||
WHERE `local_dest` = :local_dest AND `type` = :type");
|
||||
$stmt->execute(array(':local_dest' => $local_dest, ':type' => $type));
|
||||
$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 BCC map entry ' . htmlspecialchars($local_dest) . ' exists for this type'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("UPDATE `bcc_maps` SET `bcc_dest` = :bcc_dest, `active` = :active, `type` = :type WHERE `id`= :id");
|
||||
$stmt->execute(array(
|
||||
':bcc_dest' => $bcc_dest,
|
||||
':active' => $active,
|
||||
':type' => $type,
|
||||
':id' => $id
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'MySQL: '.$e
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'success',
|
||||
'msg' => 'BCC map entry edited'
|
||||
);
|
||||
break;
|
||||
case 'details':
|
||||
$bccdata = array();
|
||||
$id = intval($_data);
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT `id`,
|
||||
`local_dest`,
|
||||
`bcc_dest`,
|
||||
`active` AS `active_int`,
|
||||
CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`,
|
||||
`type`,
|
||||
`created`,
|
||||
`domain`,
|
||||
`modified` FROM `bcc_maps`
|
||||
WHERE `id` = :id");
|
||||
$stmt->execute(array(':id' => $id));
|
||||
$bccdata = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
catch(PDOException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'MySQL: '.$e
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $bccdata['domain'])) {
|
||||
$bccdata = null;
|
||||
return false;
|
||||
}
|
||||
return $bccdata;
|
||||
break;
|
||||
case 'get':
|
||||
$bccdata = array();
|
||||
$all_items = array();
|
||||
$id = intval($_data);
|
||||
try {
|
||||
$stmt = $pdo->query("SELECT `id`, `domain` FROM `bcc_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) {
|
||||
if (hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $i['domain'])) {
|
||||
$bccdata[] = $i['id'];
|
||||
}
|
||||
}
|
||||
$all_items = null;
|
||||
return $bccdata;
|
||||
break;
|
||||
case 'delete':
|
||||
$ids = (array)$_data['id'];
|
||||
foreach ($ids as $id) {
|
||||
if (!is_numeric($id)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT `domain` FROM `bcc_maps` WHERE id = :id");
|
||||
$stmt->execute(array(':id' => $id));
|
||||
$domain = $stmt->fetch(PDO::FETCH_ASSOC)['domain'];
|
||||
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare("DELETE FROM `bcc_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 BCC map id/s ' . implode(', ', $ids)
|
||||
);
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
function customize($_action, $_item, $_data = null) {
|
||||
global $redis;
|
||||
global $lang;
|
||||
@@ -19,7 +18,7 @@ function customize($_action, $_item, $_data = null) {
|
||||
if (file_exists($_data['main_logo']['tmp_name']) !== true) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Cannot validate image file: Temporary file not found'
|
||||
'msg' => $lang['danger']['img_tmp_missing']
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@@ -27,7 +26,7 @@ function customize($_action, $_item, $_data = null) {
|
||||
if ($image->valid() !== true) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Cannot validate image file'
|
||||
'msg' => $lang['danger']['img_invalid']
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@@ -36,7 +35,7 @@ function customize($_action, $_item, $_data = null) {
|
||||
catch (ImagickException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Cannot validate image file'
|
||||
'msg' => $lang['danger']['img_invalid']
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@@ -44,7 +43,7 @@ function customize($_action, $_item, $_data = null) {
|
||||
else {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Invalid mime type'
|
||||
'msg' => $lang['danger']['invalid_mime_type']
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@@ -60,7 +59,7 @@ function customize($_action, $_item, $_data = null) {
|
||||
}
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'success',
|
||||
'msg' => 'File uploaded successfully'
|
||||
'msg' => $lang['success']['upload_success']
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -78,7 +77,7 @@ function customize($_action, $_item, $_data = null) {
|
||||
$apps = (array)$_data['app'];
|
||||
$links = (array)$_data['href'];
|
||||
$out = array();
|
||||
if (count($apps) == count($links)) {;
|
||||
if (count($apps) == count($links)) {
|
||||
for ($i = 0; $i < count($apps); $i++) {
|
||||
$out[] = array($apps[$i] => $links[$i]);
|
||||
}
|
||||
@@ -95,7 +94,28 @@ function customize($_action, $_item, $_data = null) {
|
||||
}
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'success',
|
||||
'msg' => 'Saved changes to app links'
|
||||
'msg' => $lang['success']['app_links']
|
||||
);
|
||||
break;
|
||||
case 'ui_texts':
|
||||
$main_name = $_data['main_name'];
|
||||
$apps_name = $_data['apps_name'];
|
||||
$help_text = $_data['help_text'];
|
||||
try {
|
||||
$redis->set('MAIN_NAME', htmlspecialchars($main_name));
|
||||
$redis->set('APPS_NAME', htmlspecialchars($apps_name));
|
||||
$redis->set('HELP_TEXT', $help_text);
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Redis: '.$e
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'success',
|
||||
'msg' => $lang['success']['ui_texts']
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -114,7 +134,7 @@ function customize($_action, $_item, $_data = null) {
|
||||
if ($redis->del('MAIN_LOGO')) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'success',
|
||||
'msg' => 'Reset default logo'
|
||||
'msg' => $lang['success']['reset_main_logo']
|
||||
);
|
||||
return true;
|
||||
}
|
||||
@@ -156,6 +176,21 @@ function customize($_action, $_item, $_data = null) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'ui_texts':
|
||||
try {
|
||||
$data['main_name'] = ($main_name = $redis->get('MAIN_NAME')) ? $main_name : 'mailcow UI';
|
||||
$data['apps_name'] = ($apps_name = $redis->get('APPS_NAME')) ? $apps_name : 'mailcow Apps';
|
||||
$data['help_text'] = ($help_text = $redis->get('HELP_TEXT')) ? $help_text : false;
|
||||
return $data;
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Redis: '.$e
|
||||
);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'main_logo_specs':
|
||||
try {
|
||||
$image = new Imagick();
|
||||
@@ -168,7 +203,7 @@ function customize($_action, $_item, $_data = null) {
|
||||
catch (ImagickException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Error: Imagick exception while reading image'
|
||||
'msg' => $lang['danger']['imagick_exception']
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
@@ -1,5 +1,12 @@
|
||||
<?php
|
||||
function docker($service_name, $action, $post_action = null, $post_fields = null) {
|
||||
function docker($service_name, $action, $attr1 = null, $attr2 = null, $extra_headers = null) {
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER,array( 'Content-Type: application/json' ));
|
||||
switch($action) {
|
||||
@@ -53,13 +60,16 @@ function docker($service_name, $action, $post_action = null, $post_fields = null
|
||||
}
|
||||
break;
|
||||
case 'post':
|
||||
if (!empty($post_action)) {
|
||||
if (!empty($attr1)) {
|
||||
$container_id = docker($service_name, 'get_id');
|
||||
if (ctype_xdigit($container_id) && ctype_alnum($post_action)) {
|
||||
curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/' . $container_id . '/' . $post_action);
|
||||
if (ctype_xdigit($container_id) && ctype_alnum($attr1)) {
|
||||
curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/' . $container_id . '/' . $attr1);
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
if (!empty($post_fields)) {
|
||||
curl_setopt( $curl, CURLOPT_POSTFIELDS, json_encode($post_fields));
|
||||
if (!empty($attr2)) {
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($attr2));
|
||||
}
|
||||
if (!empty($extra_headers) && is_array($extra_headers)) {
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $extra_headers);
|
||||
}
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
$response = curl_exec($curl);
|
||||
|
@@ -95,4 +95,4 @@ function fail2ban($_action, $_data = null) {
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -75,15 +75,15 @@ function generate_tlsa_digest($hostname, $port, $starttls = null) {
|
||||
}
|
||||
if (empty($starttls)) {
|
||||
$context = stream_context_create(array("ssl" => array("capture_peer_cert" => true, 'verify_peer' => false, 'allow_self_signed' => true)));
|
||||
$stream = stream_socket_client('tls://' . $hostname . ':' . $port, $error_nr, $error_msg, 5, STREAM_CLIENT_CONNECT, $context);
|
||||
// error_nr can be 0, so checking against error_msg
|
||||
if ($error_msg) {
|
||||
$stream = stream_socket_client('ssl://' . $hostname . ':' . $port, $error_nr, $error_msg, 5, STREAM_CLIENT_CONNECT, $context);
|
||||
if (!$stream) {
|
||||
$error_msg = isset($error_msg) ? $error_msg : '-';
|
||||
return $error_nr . ': ' . $error_msg;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$stream = stream_socket_client('tcp://' . $hostname . ':' . $port, $error_nr, $error_msg, 5);
|
||||
if ($error_msg) {
|
||||
if (!$stream) {
|
||||
return $error_nr . ': ' . $error_msg;
|
||||
}
|
||||
$banner = fread($stream, 512 );
|
||||
@@ -443,14 +443,31 @@ function user_get_alias_details($username) {
|
||||
}
|
||||
try {
|
||||
$data['address'] = $username;
|
||||
$stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '✘') AS `aliases` FROM `alias`
|
||||
$stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '✘') AS `shared_aliases` FROM `alias`
|
||||
WHERE `goto` REGEXP :username_goto
|
||||
AND `address` NOT LIKE '@%'
|
||||
AND `goto` != :username_goto2
|
||||
AND `address` != :username_address");
|
||||
$stmt->execute(array(':username_goto' => '(^|,)'.$username.'($|,)', ':username_address' => $username));
|
||||
$stmt->execute(array(
|
||||
':username_goto' => '(^|,)'.$username.'($|,)',
|
||||
':username_goto2' => $username,
|
||||
':username_address' => $username
|
||||
));
|
||||
$run = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
while ($row = array_shift($run)) {
|
||||
$data['aliases'] = $row['aliases'];
|
||||
$data['shared_aliases'] = $row['shared_aliases'];
|
||||
}
|
||||
$stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '✘') AS `direct_aliases` FROM `alias`
|
||||
WHERE `goto` = :username_goto
|
||||
AND `address` != :username_address");
|
||||
$stmt->execute(
|
||||
array(
|
||||
':username_goto' => $username,
|
||||
':username_address' => $username
|
||||
));
|
||||
$run = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
while ($row = array_shift($run)) {
|
||||
$data['direct_aliases'] = $row['direct_aliases'];
|
||||
}
|
||||
$stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(local_part, '@', alias_domain SEPARATOR ', '), '✘') AS `ad_alias` FROM `mailbox`
|
||||
LEFT OUTER JOIN `alias_domain` on `target_domain` = `domain`
|
||||
@@ -466,7 +483,7 @@ function user_get_alias_details($username) {
|
||||
while ($row = array_shift($run)) {
|
||||
$data['aliases_also_send_as'] = $row['send_as'];
|
||||
}
|
||||
$stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`send_as` SEPARATOR ', '), '✘') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :username AND `send_as` LIKE '@%';");
|
||||
$stmt = $pdo->prepare("SELECT IFNULL(CONCAT(GROUP_CONCAT(DISTINCT `send_as` SEPARATOR ', '), ', ', GROUP_CONCAT(DISTINCT CONCAT('@',`alias_domain`) SEPARATOR ', ')), '✘') AS `send_as` FROM `sender_acl` LEFT JOIN `alias_domain` ON `alias_domain`.`target_domain` = TRIM(LEADING '@' FROM `send_as`) WHERE `logged_in_as` = :username AND `send_as` LIKE '@%';");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$run = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
while ($row = array_shift($run)) {
|
||||
@@ -851,6 +868,135 @@ function verify_tfa_login($username, $token) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function admin_api($action, $data = null) {
|
||||
global $pdo;
|
||||
global $lang;
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
switch ($action) {
|
||||
case "edit":
|
||||
$regen_key = $data['admin_api_regen_key'];
|
||||
$active = (isset($data['active'])) ? 1 : 0;
|
||||
$allow_from = array_map('trim', preg_split( "/( |,|;|\n)/", $data['allow_from']));
|
||||
foreach ($allow_from as $key => $val) {
|
||||
if (!filter_var($val, FILTER_VALIDATE_IP)) {
|
||||
unset($allow_from[$key]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$allow_from = implode(',', array_unique(array_filter($allow_from)));
|
||||
if (empty($allow_from)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'List of allowed IPs cannot be empty'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$api_key = implode('-', array(
|
||||
strtoupper(bin2hex(random_bytes(3))),
|
||||
strtoupper(bin2hex(random_bytes(3))),
|
||||
strtoupper(bin2hex(random_bytes(3))),
|
||||
strtoupper(bin2hex(random_bytes(3))),
|
||||
strtoupper(bin2hex(random_bytes(3)))
|
||||
));
|
||||
$stmt = $pdo->prepare("INSERT INTO `api` (`username`, `api_key`, `active`, `allow_from`)
|
||||
SELECT `username`, :api_key, :active, :allow_from FROM `admin` WHERE `superadmin`='1' AND `active`='1'
|
||||
ON DUPLICATE KEY UPDATE `active` = :active_u, `allow_from` = :allow_from_u ;");
|
||||
$stmt->execute(array(
|
||||
':api_key' => $api_key,
|
||||
':active' => $active,
|
||||
':active_u' => $active,
|
||||
':allow_from' => $allow_from,
|
||||
':allow_from_u' => $allow_from
|
||||
));
|
||||
break;
|
||||
case "regen_key":
|
||||
$api_key = implode('-', array(
|
||||
strtoupper(bin2hex(random_bytes(3))),
|
||||
strtoupper(bin2hex(random_bytes(3))),
|
||||
strtoupper(bin2hex(random_bytes(3))),
|
||||
strtoupper(bin2hex(random_bytes(3))),
|
||||
strtoupper(bin2hex(random_bytes(3)))
|
||||
));
|
||||
$stmt = $pdo->prepare("UPDATE `api` SET `api_key` = :api_key WHERE `username` IN
|
||||
(SELECT `username` FROM `admin` WHERE `superadmin`='1' AND `active`='1')");
|
||||
$stmt->execute(array(
|
||||
':api_key' => $api_key
|
||||
));
|
||||
break;
|
||||
}
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'success',
|
||||
'msg' => sprintf($lang['success']['admin_modified'])
|
||||
);
|
||||
}
|
||||
function rspamd_ui($action, $data = null) {
|
||||
global $lang;
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
switch ($action) {
|
||||
case "edit":
|
||||
$rspamd_ui_pass = $data['rspamd_ui_pass'];
|
||||
$rspamd_ui_pass2 = $data['rspamd_ui_pass2'];
|
||||
if (empty($rspamd_ui_pass) || empty($rspamd_ui_pass2)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Password cannot be empty'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if ($rspamd_ui_pass != $rspamd_ui_pass2) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Passwords do not match'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (strlen($rspamd_ui_pass) < 6) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Please use at least 6 characters for your password'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$docker_return = docker('rspamd-mailcow', 'post', 'exec', array('cmd' => 'worker_password', 'raw' => $rspamd_ui_pass), array('Content-Type: application/json'));
|
||||
if ($docker_return_array = json_decode($docker_return, true)) {
|
||||
if ($docker_return_array['type'] == 'success') {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'success',
|
||||
'msg' => 'Rspamd UI password set successfully'
|
||||
);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => $docker_return_array['type'],
|
||||
'msg' => $docker_return_array['msg']
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Unknown error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
function get_admin_details() {
|
||||
// No parameter to be given, only one admin should exist
|
||||
global $pdo;
|
||||
@@ -860,8 +1006,10 @@ function get_admin_details() {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT `username`, `modified`, `created` FROM `admin` WHERE `superadmin`='1' AND active='1'");
|
||||
$stmt->execute();
|
||||
$stmt = $pdo->query("SELECT `admin`.`username`, `api`.`active` AS `api_active`, `api`.`api_key`, `api`.`allow_from` FROM `admin`
|
||||
INNER JOIN `api` ON `admin`.`username` = `api`.`username`
|
||||
WHERE `admin`.`superadmin`='1'
|
||||
AND `admin`.`active`='1'");
|
||||
$data = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
catch(PDOException $e) {
|
||||
@@ -932,6 +1080,51 @@ function get_logs($container, $lines = false) {
|
||||
return $data_array;
|
||||
}
|
||||
}
|
||||
if ($container == "watchdog-mailcow") {
|
||||
if (!is_numeric($lines)) {
|
||||
list ($from, $to) = explode('-', $lines);
|
||||
$data = $redis->lRange('WATCHDOG_LOG', intval($from), intval($to));
|
||||
}
|
||||
else {
|
||||
$data = $redis->lRange('WATCHDOG_LOG', 0, intval($lines));
|
||||
}
|
||||
if ($data) {
|
||||
foreach ($data as $json_line) {
|
||||
$data_array[] = json_decode($json_line, true);
|
||||
}
|
||||
return $data_array;
|
||||
}
|
||||
}
|
||||
if ($container == "acme-mailcow") {
|
||||
if (!is_numeric($lines)) {
|
||||
list ($from, $to) = explode('-', $lines);
|
||||
$data = $redis->lRange('ACME_LOG', intval($from), intval($to));
|
||||
}
|
||||
else {
|
||||
$data = $redis->lRange('ACME_LOG', 0, intval($lines));
|
||||
}
|
||||
if ($data) {
|
||||
foreach ($data as $json_line) {
|
||||
$data_array[] = json_decode($json_line, true);
|
||||
}
|
||||
return $data_array;
|
||||
}
|
||||
}
|
||||
if ($container == "api-mailcow") {
|
||||
if (!is_numeric($lines)) {
|
||||
list ($from, $to) = explode('-', $lines);
|
||||
$data = $redis->lRange('API_LOG', intval($from), intval($to));
|
||||
}
|
||||
else {
|
||||
$data = $redis->lRange('API_LOG', 0, intval($lines));
|
||||
}
|
||||
if ($data) {
|
||||
foreach ($data as $json_line) {
|
||||
$data_array[] = json_decode($json_line, true);
|
||||
}
|
||||
return $data_array;
|
||||
}
|
||||
}
|
||||
if ($container == "fail2ban-mailcow") {
|
||||
if (!is_numeric($lines)) {
|
||||
list ($from, $to) = explode('-', $lines);
|
||||
|
@@ -490,9 +490,20 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
||||
if (in_array($address, $gotos)) {
|
||||
continue;
|
||||
}
|
||||
$domain = idn_to_ascii(substr(strstr($address, '@'), 1));
|
||||
$local_part = strstr($address, '@', true);
|
||||
$address = $local_part.'@'.$domain;
|
||||
$stmt = $pdo->prepare("SELECT `address` FROM `alias`
|
||||
WHERE `address`= :address");
|
||||
$stmt->execute(array(':address' => $address));
|
||||
WHERE `address`= :address OR `address` IN (
|
||||
SELECT `username` FROM `mailbox`, `alias_domain`
|
||||
WHERE (
|
||||
`alias_domain`.`alias_domain` = :address_d
|
||||
AND `mailbox`.`username` = CONCAT(:address_l, '@', alias_domain.target_domain)))");
|
||||
$stmt->execute(array(
|
||||
':address' => $address,
|
||||
':address_l' => $local_part,
|
||||
':address_d' => $domain
|
||||
));
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
if ($num_results != 0) {
|
||||
$_SESSION['return'] = array(
|
||||
@@ -501,9 +512,6 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$domain = idn_to_ascii(substr(strstr($address, '@'), 1));
|
||||
$local_part = strstr($address, '@', true);
|
||||
$address = $local_part.'@'.$domain;
|
||||
$domaindata = mailbox('get', 'domain_details', $domain);
|
||||
if (is_array($domaindata) && $domaindata['aliases_left'] == "0") {
|
||||
$_SESSION['return'] = array(
|
||||
@@ -722,7 +730,7 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
||||
}
|
||||
$active = intval($_data['active']);
|
||||
$quota_b = ($quota_m * 1048576);
|
||||
$maildir = $domain."/".$local_part."/";
|
||||
$maildir = $domain . "/" . $local_part . "/";
|
||||
if (!is_valid_domain_name($domain)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
@@ -1405,7 +1413,7 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
||||
$subfolder2 = (isset($_data['subfolder2'])) ? $_data['subfolder2'] : $is_now['subfolder2'];
|
||||
$enc1 = (!empty($_data['enc1'])) ? $_data['enc1'] : $is_now['enc1'];
|
||||
$mins_interval = (!empty($_data['mins_interval'])) ? $_data['mins_interval'] : $is_now['mins_interval'];
|
||||
$exclude = (!empty($_data['exclude'])) ? $_data['exclude'] : '';
|
||||
$exclude = (!empty($_data['exclude'])) ? $_data['exclude'] : $is_now['exclude'];
|
||||
$maxage = (isset($_data['maxage']) && $_data['maxage'] != "") ? intval($_data['maxage']) : $is_now['maxage'];
|
||||
}
|
||||
else {
|
||||
@@ -2302,7 +2310,7 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND `domain` IN (SELECT `domain` FROM `domain_admins` WHERE `active` = '1' AND `username` = :username) OR 'admin' = :role");
|
||||
$stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `kind` NOT REGEXP 'location|thing|group' AND (`domain` IN (SELECT `domain` FROM `domain_admins` WHERE `active` = '1' AND `username` = :username) OR 'admin' = :role)");
|
||||
$stmt->execute(array(
|
||||
':username' => $_SESSION['mailcow_cc_username'],
|
||||
':role' => $_SESSION['mailcow_cc_role'],
|
||||
@@ -3103,10 +3111,6 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
||||
}
|
||||
foreach ($ids as $id) {
|
||||
if (!is_numeric($id)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => $id
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
@@ -3154,10 +3158,6 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
||||
}
|
||||
foreach ($ids as $id) {
|
||||
if (!is_numeric($id)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => $id
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
@@ -3366,6 +3366,10 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
||||
$stmt->execute(array(
|
||||
':domain' => '%@'.$domain,
|
||||
));
|
||||
$stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :domain");
|
||||
$stmt->execute(array(
|
||||
':domain' => $domain,
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
@@ -3486,6 +3490,10 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
||||
$stmt->execute(array(
|
||||
':alias_domain' => $alias_domain,
|
||||
));
|
||||
$stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :alias_domain");
|
||||
$stmt->execute(array(
|
||||
':alias_domain' => $alias_domain,
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
@@ -3580,6 +3588,10 @@ function mailbox($_action, $_type, $_data = null, $attr = null) {
|
||||
$stmt->execute(array(
|
||||
':username' => $username
|
||||
));
|
||||
$stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :username");
|
||||
$stmt->execute(array(
|
||||
':username' => $username
|
||||
));
|
||||
$stmt = $pdo->prepare("SELECT `address`, `goto` FROM `alias`
|
||||
WHERE `goto` REGEXP :username");
|
||||
$stmt->execute(array(':username' => '(^|,)'.$username.'($|,)'));
|
||||
|
282
data/web/inc/functions.quarantaine.inc.php
Normal file
282
data/web/inc/functions.quarantaine.inc.php
Normal file
@@ -0,0 +1,282 @@
|
||||
<?php
|
||||
function quarantaine($_action, $_data = null) {
|
||||
global $pdo;
|
||||
global $redis;
|
||||
global $lang;
|
||||
switch ($_action) {
|
||||
case 'delete':
|
||||
if (!is_array($_data['id'])) {
|
||||
$ids = array();
|
||||
$ids[] = $_data['id'];
|
||||
}
|
||||
else {
|
||||
$ids = $_data['id'];
|
||||
}
|
||||
if (!isset($_SESSION['acl']['quarantaine']) || $_SESSION['acl']['quarantaine'] != "1" ) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
foreach ($ids as $id) {
|
||||
if (!is_numeric($id)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare('SELECT `rcpt` FROM `quarantaine` WHERE `id` = :id');
|
||||
$stmt->execute(array(':id' => $id));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row['rcpt'])) {
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM `quarantaine` WHERE `id` = :id");
|
||||
$stmt->execute(array(
|
||||
':id' => $id
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'MySQL: '.$e
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch(PDOException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'MySQL: '.$e
|
||||
);
|
||||
}
|
||||
}
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'success',
|
||||
'msg' => sprintf($lang['success']['items_deleted'], implode(', ', $ids))
|
||||
);
|
||||
break;
|
||||
case 'edit':
|
||||
if (!isset($_SESSION['acl']['quarantaine']) || $_SESSION['acl']['quarantaine'] != "1" ) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// Edit settings
|
||||
if ($_data['action'] == 'settings') {
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$retention_size = $_data['retention_size'];
|
||||
$max_size = $_data['max_size'];
|
||||
$exclude_domains = (array)$_data['exclude_domains'];
|
||||
try {
|
||||
$redis->Set('Q_RETENTION_SIZE', intval($retention_size));
|
||||
$redis->Set('Q_MAX_SIZE', intval($max_size));
|
||||
$redis->Set('Q_EXCLUDE_DOMAINS', json_encode($exclude_domains));
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Redis: '.$e
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'success',
|
||||
'msg' => 'Saved settings'
|
||||
);
|
||||
}
|
||||
// Release item
|
||||
elseif ($_data['action'] == 'release') {
|
||||
if (!is_array($_data['id'])) {
|
||||
$ids = array();
|
||||
$ids[] = $_data['id'];
|
||||
}
|
||||
else {
|
||||
$ids = $_data['id'];
|
||||
}
|
||||
foreach ($ids as $id) {
|
||||
if (!is_numeric($id)) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare('SELECT `msg`, `qid`, `sender`, `rcpt` FROM `quarantaine` WHERE `id` = :id');
|
||||
$stmt->execute(array(':id' => $id));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row['rcpt'])) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch(PDOException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'MySQL: '.$e
|
||||
);
|
||||
}
|
||||
$sender = (isset($row['sender'])) ? $row['sender'] : 'sender-unknown@rspamd';
|
||||
try {
|
||||
$mail = new PHPMailer(true);
|
||||
$mail->isSMTP();
|
||||
$mail->SMTPDebug = 0;
|
||||
$mail->SMTPOptions = array(
|
||||
'ssl' => array(
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
'allow_self_signed' => true
|
||||
)
|
||||
);
|
||||
if (!empty(gethostbynamel('postfix-mailcow'))) {
|
||||
$postfix = 'postfix-mailcow';
|
||||
}
|
||||
if (!empty(gethostbynamel('postfix'))) {
|
||||
$postfix = 'postfix';
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'warning',
|
||||
'msg' => sprintf($lang['danger']['release_send_failed'], 'Cannot determine Postfix host')
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$mail->Host = $postfix;
|
||||
$mail->Port = 590;
|
||||
$mail->setFrom($sender);
|
||||
$mail->CharSet = 'UTF-8';
|
||||
$mail->Subject = sprintf($lang['quarantaine']['release_subject'], $row['qid']);
|
||||
$mail->addAddress($row['rcpt']);
|
||||
$mail->IsHTML(false);
|
||||
$msg_tmpf = tempnam("/tmp", $row['qid']);
|
||||
file_put_contents($msg_tmpf, $row['msg']);
|
||||
$mail->addAttachment($msg_tmpf, $row['qid'] . '.eml');
|
||||
$mail->Body = sprintf($lang['quarantaine']['release_body']);
|
||||
$mail->send();
|
||||
unlink($msg_tmpf);
|
||||
}
|
||||
catch (phpmailerException $e) {
|
||||
unlink($msg_tmpf);
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'warning',
|
||||
'msg' => sprintf($lang['danger']['release_send_failed'], $e->errorMessage())
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM `quarantaine` 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' => $lang['success']['items_released']
|
||||
);
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
case 'get':
|
||||
try {
|
||||
if ($_SESSION['mailcow_cc_role'] == "user") {
|
||||
$stmt = $pdo->prepare('SELECT `id`, `qid`, `rcpt`, `sender`, UNIX_TIMESTAMP(`created`) AS `created` FROM `quarantaine` WHERE `rcpt` = :mbox');
|
||||
$stmt->execute(array(':mbox' => $_SESSION['mailcow_cc_username']));
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
while($row = array_shift($rows)) {
|
||||
$q_meta[] = $row;
|
||||
}
|
||||
}
|
||||
else {
|
||||
foreach (mailbox('get', 'mailboxes') as $mbox) {
|
||||
$stmt = $pdo->prepare('SELECT `id`, `qid`, `rcpt`, `sender`, UNIX_TIMESTAMP(`created`) AS `created` FROM `quarantaine` WHERE `rcpt` = :mbox');
|
||||
$stmt->execute(array(':mbox' => $mbox));
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
while($row = array_shift($rows)) {
|
||||
$q_meta[] = $row;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(PDOException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'MySQL: '.$e
|
||||
);
|
||||
}
|
||||
return $q_meta;
|
||||
break;
|
||||
case 'settings':
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => sprintf($lang['danger']['access_denied'])
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$settings['exclude_domains'] = json_decode($redis->Get('Q_EXCLUDE_DOMAINS'), true);
|
||||
$settings['max_size'] = $redis->Get('Q_MAX_SIZE');
|
||||
$settings['retention_size'] = $redis->Get('Q_RETENTION_SIZE');
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Redis: '.$e
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return $settings;
|
||||
break;
|
||||
case 'details':
|
||||
if (!is_numeric($_data) || empty($_data)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare('SELECT `rcpt`, `symbols`, `msg`, `domain` FROM `quarantaine` WHERE `id`= :id');
|
||||
$stmt->execute(array(':id' => $_data));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $row['rcpt'])) {
|
||||
return $row;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch(PDOException $e) {
|
||||
$_SESSION['return'] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'MySQL: '.$e
|
||||
);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
@@ -56,8 +56,8 @@ function relayhost($_action, $_data = null) {
|
||||
$is_now = relayhost('details', $id);
|
||||
if (!empty($is_now)) {
|
||||
$hostname = (!empty($_data['hostname'])) ? trim($_data['hostname']) : $is_now['hostname'];
|
||||
$username = (!empty($_data['username'])) ? trim($_data['username']) : $is_now['username'];
|
||||
$password = (!empty($_data['password'])) ? trim($_data['password']) : $is_now['password'];
|
||||
$username = (isset($_data['username'])) ? trim($_data['username']) : $is_now['username'];
|
||||
$password = (isset($_data['password'])) ? trim($_data['password']) : $is_now['password'];
|
||||
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
|
||||
}
|
||||
else {
|
||||
|
@@ -15,6 +15,7 @@
|
||||
<?php else: ?>
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css">
|
||||
<?php endif; ?>
|
||||
<link rel="stylesheet" href="/css/breakpoint.min.css">
|
||||
<link rel="stylesheet" href="/css/bootstrap-select.min.css">
|
||||
<link rel="stylesheet" href="/css/bootstrap-slider.min.css">
|
||||
<link rel="stylesheet" href="/css/bootstrap-switch.min.css">
|
||||
@@ -27,6 +28,8 @@
|
||||
<?= (preg_match("/admin.php/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/admin.css">' : null; ?>
|
||||
<?= (preg_match("/user.php/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/user.css">' : null; ?>
|
||||
<?= (preg_match("/edit.php/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/edit.css">' : null; ?>
|
||||
<?= (preg_match("/quarantaine.php/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/quarantaine.css">' : null; ?>
|
||||
<?= (preg_match("/debug.php/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/debug.css">' : null; ?>
|
||||
<link rel="shortcut icon" href="/favicon.png" type="image/png">
|
||||
<link rel="icon" href="/favicon.png" type="image/png">
|
||||
</head>
|
||||
@@ -35,7 +38,6 @@
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
@@ -70,6 +72,7 @@
|
||||
if (isset($_SESSION['mailcow_cc_role'])) {
|
||||
if ($_SESSION['mailcow_cc_role'] == 'admin') {
|
||||
?>
|
||||
<li<?= (preg_match("/debug/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/debug.php"><?= $lang['header']['debug']; ?></a></li>
|
||||
<li<?= (preg_match("/admin/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/admin.php"><?= $lang['header']['administration']; ?></a></li>
|
||||
<?php
|
||||
}
|
||||
@@ -88,14 +91,19 @@
|
||||
</ul>
|
||||
</li>
|
||||
<?php
|
||||
if (isset($_SESSION['mailcow_cc_role'])) {
|
||||
?>
|
||||
<li<?= (preg_match("/quarantaine/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/quarantaine.php"><span style="font-size: 12px;" class="glyphicon glyphicon-briefcase"></span> <?= $lang['header']['quarantaine']; ?></a></li>
|
||||
<?php
|
||||
}
|
||||
if ($_SESSION['mailcow_cc_role'] == 'admin') {
|
||||
?>
|
||||
<li><a href data-toggle="modal" data-target="#RestartSOGo"><span style="font-size: 12px;" class="glyphicon glyphicon-refresh" aria-hidden="true"></span> <?= $lang['header']['restart_sogo']; ?></a></li>
|
||||
<li><a href data-toggle="modal" data-container="sogo-mailcow" data-target="#RestartContainer"><span style="font-size: 12px;" class="glyphicon glyphicon-refresh"></span> <?= $lang['header']['restart_sogo']; ?></a></li>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><span class="glyphicon glyphicon-link" aria-hidden="true"></span> Apps <span class="caret"></span></a>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><span class="glyphicon glyphicon-link"></span> Apps <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<?php
|
||||
foreach ($MAILCOW_APPS as $app):
|
||||
|
@@ -3,7 +3,7 @@ function init_db_schema() {
|
||||
try {
|
||||
global $pdo;
|
||||
|
||||
$db_version = "14112017_2103";
|
||||
$db_version = "02012018_1515";
|
||||
|
||||
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
@@ -103,6 +103,30 @@ function init_db_schema() {
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"api" => array(
|
||||
"cols" => array(
|
||||
"username" => "VARCHAR(255) NOT NULL",
|
||||
"api_key" => "VARCHAR(255) NOT NULL",
|
||||
"allow_from" => "VARCHAR(512) NOT NULL",
|
||||
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
|
||||
"modified" => "DATETIME ON UPDATE NOW(0)",
|
||||
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
|
||||
),
|
||||
"keys" => array(
|
||||
"primary" => array(
|
||||
"" => array("username")
|
||||
),
|
||||
"fkey" => array(
|
||||
"fk_username_api" => array(
|
||||
"col" => "username",
|
||||
"ref" => "admin.username",
|
||||
"delete" => "CASCADE",
|
||||
"update" => "NO ACTION"
|
||||
)
|
||||
)
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"sender_acl" => array(
|
||||
"cols" => array(
|
||||
"logged_in_as" => "VARCHAR(255) NOT NULL",
|
||||
@@ -133,6 +157,28 @@ function init_db_schema() {
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"quarantaine" => array(
|
||||
"cols" => array(
|
||||
"id" => "INT NOT NULL AUTO_INCREMENT",
|
||||
"qid" => "VARCHAR(30) NOT NULL",
|
||||
"score" => "FLOAT(8,2)",
|
||||
"ip" => "VARBINARY(16)",
|
||||
"action" => "CHAR(20) NOT NULL DEFAULT 'unknown'",
|
||||
"symbols" => "JSON",
|
||||
"sender" => "VARCHAR(255) NOT NULL DEFAULT 'unknown'",
|
||||
"rcpt" => "VARCHAR(255)",
|
||||
"msg" => "LONGTEXT",
|
||||
"domain" => "VARCHAR(255)",
|
||||
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
|
||||
"user" => "VARCHAR(255) NOT NULL DEFAULT 'unknown'",
|
||||
),
|
||||
"keys" => array(
|
||||
"primary" => array(
|
||||
"" => array("id")
|
||||
)
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"mailbox" => array(
|
||||
"cols" => array(
|
||||
"username" => "VARCHAR(255) NOT NULL",
|
||||
@@ -202,6 +248,8 @@ function init_db_schema() {
|
||||
"syncjobs" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"eas_reset" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"filters" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"quarantaine" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"bcc_maps" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
),
|
||||
"keys" => array(
|
||||
"fkey" => array(
|
||||
@@ -325,6 +373,27 @@ function init_db_schema() {
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"bcc_maps" => array(
|
||||
"cols" => array(
|
||||
"id" => "INT NOT NULL AUTO_INCREMENT",
|
||||
"local_dest" => "VARCHAR(255) NOT NULL",
|
||||
"bcc_dest" => "VARCHAR(255) NOT NULL",
|
||||
"domain" => "VARCHAR(255) NOT NULL",
|
||||
"type" => "ENUM('sender','rcpt')",
|
||||
"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("local_dest"),
|
||||
)
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"tfa" => array(
|
||||
"cols" => array(
|
||||
"id" => "INT NOT NULL AUTO_INCREMENT",
|
||||
@@ -471,12 +540,13 @@ function init_db_schema() {
|
||||
"c_sn" => "VARCHAR(255)",
|
||||
"c_screenname" => "VARCHAR(255)",
|
||||
"c_l" => "VARCHAR(255)",
|
||||
"c_mail" => "VARCHAR(255)",
|
||||
"c_mail" => "TEXT",
|
||||
"c_o" => "VARCHAR(255)",
|
||||
"c_ou" => "VARCHAR(255)",
|
||||
"c_telephonenumber" => "VARCHAR(255)",
|
||||
"c_categories" => "VARCHAR(255)",
|
||||
"c_component" => "VARCHAR(10) NOT NULL"
|
||||
"c_component" => "VARCHAR(10) NOT NULL",
|
||||
"c_hascertificate" => "INT4 DEFAULT 0"
|
||||
),
|
||||
"keys" => array(
|
||||
"primary" => array(
|
||||
@@ -519,8 +589,8 @@ function init_db_schema() {
|
||||
"sogo_user_profile" => array(
|
||||
"cols" => array(
|
||||
"c_uid" => "VARCHAR(255) NOT NULL",
|
||||
"c_defaults" => "TEXT",
|
||||
"c_settings" => "TEXT"
|
||||
"c_defaults" => "LONGTEXT",
|
||||
"c_settings" => "LONGTEXT"
|
||||
),
|
||||
"keys" => array(
|
||||
"primary" => array(
|
||||
@@ -686,6 +756,20 @@ function init_db_schema() {
|
||||
$pdo->query($create);
|
||||
}
|
||||
|
||||
// Create events to clean database
|
||||
$events[] = 'DROP EVENT IF EXISTS clean_spamalias;
|
||||
DELIMITER //
|
||||
CREATE EVENT clean_spamalias
|
||||
ON SCHEDULE EVERY 1 DAY DO
|
||||
BEGIN
|
||||
DELETE FROM spamalias WHERE validity < UNIX_TIMESTAMP();
|
||||
END;
|
||||
//
|
||||
DELIMITER ;';
|
||||
foreach ($events as $event) {
|
||||
$pdo->exec($event);
|
||||
}
|
||||
|
||||
// Inject admin if not exists
|
||||
$stmt = $pdo->query("SELECT NULL FROM `admin`");
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
|
@@ -2,6 +2,7 @@
|
||||
"require": {
|
||||
"robthree/twofactorauth": "^1.6",
|
||||
"yubico/u2flib-server": "^1.0",
|
||||
"phpmailer/phpmailer": "^5.2"
|
||||
"phpmailer/phpmailer": "^5.2",
|
||||
"php-mime-mail-parser/php-mime-mail-parser": "^2.9"
|
||||
}
|
||||
}
|
||||
|
82
data/web/inc/lib/composer.lock
generated
82
data/web/inc/lib/composer.lock
generated
@@ -4,8 +4,88 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "d51ef1712a74b0dfed729f2bdd85d1e3",
|
||||
"content-hash": "ee4c9e269c29282221ce88bc23f1bda9",
|
||||
"packages": [
|
||||
{
|
||||
"name": "php-mime-mail-parser/php-mime-mail-parser",
|
||||
"version": "2.9.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-mime-mail-parser/php-mime-mail-parser.git",
|
||||
"reference": "c6884c7bc77adbf55979db99841195b232fd30f1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/c6884c7bc77adbf55979db99841195b232fd30f1",
|
||||
"reference": "c6884c7bc77adbf55979db99841195b232fd30f1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mailparse": "*",
|
||||
"php": "^5.4.0 || ^7.0"
|
||||
},
|
||||
"replace": {
|
||||
"exorus/php-mime-mail-parser": "*",
|
||||
"messaged/php-mime-mail-parser": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/php-token-stream": "^1.3.0",
|
||||
"phpunit/phpunit": "^4.0 || ^5.0",
|
||||
"satooshi/php-coveralls": "0.*",
|
||||
"squizlabs/php_codesniffer": "2.*"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PhpMimeMailParser\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "bucabay",
|
||||
"email": "gabe@fijiwebdesign.com",
|
||||
"homepage": "http://www.fijiwebdesign.com",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "eXorus",
|
||||
"email": "exorus.spam@gmail.com",
|
||||
"homepage": "https://github.com/eXorus/",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "M.Valinskis",
|
||||
"email": "M.Valins@gmail.com",
|
||||
"homepage": "https://code.google.com/p/php-mime-mail-parser",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "eugene.emmett.wood",
|
||||
"email": "gene_w@cementhorizon.com",
|
||||
"homepage": "https://code.google.com/p/php-mime-mail-parser",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "alknetso",
|
||||
"email": "alkne@gmail.com",
|
||||
"homepage": "https://code.google.com/p/php-mime-mail-parser",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Fully Tested Mailparse Extension Wrapper for PHP 5.4+",
|
||||
"homepage": "https://github.com/php-mime-mail-parser/php-mime-mail-parser",
|
||||
"keywords": [
|
||||
"MimeMailParser",
|
||||
"mail",
|
||||
"mailparse",
|
||||
"mime"
|
||||
],
|
||||
"time": "2017-11-02T05:49:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpmailer/phpmailer",
|
||||
"version": "v5.2.25",
|
||||
|
@@ -7,4 +7,5 @@ $baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'RobThree\\Auth\\' => array($vendorDir . '/robthree/twofactorauth/lib'),
|
||||
'PhpMimeMailParser\\' => array($vendorDir . '/php-mime-mail-parser/php-mime-mail-parser/src'),
|
||||
);
|
||||
|
@@ -11,6 +11,10 @@ class ComposerStaticInit873464e4bd965a3168f133248b1b218b
|
||||
array (
|
||||
'RobThree\\Auth\\' => 14,
|
||||
),
|
||||
'P' =>
|
||||
array (
|
||||
'PhpMimeMailParser\\' => 18,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
@@ -18,6 +22,10 @@ class ComposerStaticInit873464e4bd965a3168f133248b1b218b
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/robthree/twofactorauth/lib',
|
||||
),
|
||||
'PhpMimeMailParser\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/php-mime-mail-parser/php-mime-mail-parser/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
|
82
data/web/inc/lib/vendor/composer/installed.json
vendored
82
data/web/inc/lib/vendor/composer/installed.json
vendored
@@ -167,5 +167,87 @@
|
||||
}
|
||||
],
|
||||
"description": "PHPMailer is a full-featured email creation and transfer class for PHP"
|
||||
},
|
||||
{
|
||||
"name": "php-mime-mail-parser/php-mime-mail-parser",
|
||||
"version": "2.9.3",
|
||||
"version_normalized": "2.9.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-mime-mail-parser/php-mime-mail-parser.git",
|
||||
"reference": "c6884c7bc77adbf55979db99841195b232fd30f1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/c6884c7bc77adbf55979db99841195b232fd30f1",
|
||||
"reference": "c6884c7bc77adbf55979db99841195b232fd30f1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mailparse": "*",
|
||||
"php": "^5.4.0 || ^7.0"
|
||||
},
|
||||
"replace": {
|
||||
"exorus/php-mime-mail-parser": "*",
|
||||
"messaged/php-mime-mail-parser": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/php-token-stream": "^1.3.0",
|
||||
"phpunit/phpunit": "^4.0 || ^5.0",
|
||||
"satooshi/php-coveralls": "0.*",
|
||||
"squizlabs/php_codesniffer": "2.*"
|
||||
},
|
||||
"time": "2017-11-02T05:49:00+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PhpMimeMailParser\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "bucabay",
|
||||
"email": "gabe@fijiwebdesign.com",
|
||||
"homepage": "http://www.fijiwebdesign.com",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "eXorus",
|
||||
"email": "exorus.spam@gmail.com",
|
||||
"homepage": "https://github.com/eXorus/",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "M.Valinskis",
|
||||
"email": "M.Valins@gmail.com",
|
||||
"homepage": "https://code.google.com/p/php-mime-mail-parser",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "eugene.emmett.wood",
|
||||
"email": "gene_w@cementhorizon.com",
|
||||
"homepage": "https://code.google.com/p/php-mime-mail-parser",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "alknetso",
|
||||
"email": "alkne@gmail.com",
|
||||
"homepage": "https://code.google.com/p/php-mime-mail-parser",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Fully Tested Mailparse Extension Wrapper for PHP 5.4+",
|
||||
"homepage": "https://github.com/php-mime-mail-parser/php-mime-mail-parser",
|
||||
"keywords": [
|
||||
"MimeMailParser",
|
||||
"mail",
|
||||
"mailparse",
|
||||
"mime"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
21
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/LICENSE
vendored
Normal file
21
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Vincent Dauce
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
167
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/README.md
vendored
Normal file
167
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/README.md
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
# php-mime-mail-parser
|
||||
|
||||
A fully tested mailparse extension wrapper for PHP 5.4+
|
||||
|
||||
[](https://github.com/php-mime-mail-parser/php-mime-mail-parser/releases)
|
||||
[](https://packagist.org/packages/php-mime-mail-parser/php-mime-mail-parser)
|
||||
[](LICENSE)
|
||||
|
||||
## Why?
|
||||
|
||||
This extension can be used to...
|
||||
* Parse and read email from Postfix
|
||||
* Create webmail
|
||||
* Store email information such a subject, HTML body, attachments, and etc. into a database
|
||||
|
||||
## Is it reliable?
|
||||
|
||||
Yes. All known issues have been reproduced, fixed and tested.
|
||||
|
||||
We use Travis CI to help ensure code quality. You can see real-time statistics below:
|
||||
|
||||
[](https://travis-ci.org/php-mime-mail-parser/php-mime-mail-parser)
|
||||
[](https://coveralls.io/r/php-mime-mail-parser/php-mime-mail-parser)
|
||||
[](https://scrutinizer-ci.com/g/php-mime-mail-parser/php-mime-mail-parser)
|
||||
|
||||
## How do I install it?
|
||||
|
||||
The easiest way is via [Composer](https://getcomposer.org/).
|
||||
|
||||
To install the latest version of PHP MIME Mail Parser, run the command below:
|
||||
|
||||
composer require php-mime-mail-parser/php-mime-mail-parser
|
||||
|
||||
## Requirements
|
||||
|
||||
The following versions of PHP are supported:
|
||||
|
||||
* PHP 5.4
|
||||
* PHP 5.5
|
||||
* PHP 5.6
|
||||
* PHP 7
|
||||
* HHVM
|
||||
|
||||
```
|
||||
sudo apt install php-cli php-pear php-dev php-mbstring
|
||||
```
|
||||
|
||||
Make sure you have the mailparse extension (http://php.net/manual/en/book.mailparse.php) properly installed. The command line `php -m | grep mailparse` need to return "mailparse" else install it:
|
||||
* PHP version > 7.0: mailparse
|
||||
* PHP version < 7.0: mailparse 2.1.6
|
||||
|
||||
Follow this steps to install mailparse:
|
||||
|
||||
* Compile in the temp folder the extension mailparse or mailparse-2.1.6 (workaround because pecl install doesn't work yet)
|
||||
```
|
||||
cd
|
||||
pecl download mailparse
|
||||
tar -xvf mailparse-3.0.2.tgz
|
||||
cd mailparse-3.0.2/
|
||||
phpize
|
||||
./configure
|
||||
sed -i 's/#if\s!HAVE_MBSTRING/#ifndef MBFL_MBFILTER_H/' ./mailparse.c
|
||||
make
|
||||
sudo mv modules/mailparse.so /usr/lib/php/20160303/
|
||||
```
|
||||
* Add the extension mailparse and activate it
|
||||
```
|
||||
echo "extension=mailparse.so" | sudo tee /etc/php/7.1/mods-available/mailparse.ini
|
||||
sudo phpenmod mailparse
|
||||
```
|
||||
|
||||
On Windows, you need to download mailparse DLL from http://pecl.php.net/package/mailparse and add the line "extension=php_mailparse.dll" to php.ini accordingly.
|
||||
|
||||
## How do I use it?
|
||||
|
||||
```php
|
||||
<?php
|
||||
// Include the library first
|
||||
require_once __DIR__.'/vendor/autoload.php';
|
||||
|
||||
$path = 'path/to/mail.txt';
|
||||
$Parser = new PhpMimeMailParser\Parser();
|
||||
|
||||
// There are four methods available to indicate which mime mail to parse.
|
||||
// You only need to use one of the following four:
|
||||
|
||||
// 1. Specify a file path to the mime mail.
|
||||
$Parser->setPath($path);
|
||||
|
||||
// 2. Specify a php file resource (stream) to the mime mail.
|
||||
$Parser->setStream(fopen($path, "r"));
|
||||
|
||||
// 3. Specify the raw mime mail text.
|
||||
$Parser->setText(file_get_contents($path));
|
||||
|
||||
// 4. Specify a stream to work with mail server
|
||||
$Parser->setStream(fopen("php://stdin", "r"));
|
||||
|
||||
// Once we've indicated where to find the mail, we can parse out the data
|
||||
$to = $Parser->getHeader('to'); // "test" <test@example.com>, "test2" <test2@example.com>
|
||||
$addressesTo = $Parser->getAddresses('to'); //Return an array : [[test, test@example.com, false],[test2, test2@example.com, false]]
|
||||
|
||||
$from = $Parser->getHeader('from'); // "test" <test@example.com>
|
||||
$addressesFrom = $Parser->getAddresses('from'); //Return an array : test, test@example.com, false
|
||||
|
||||
$subject = $Parser->getHeader('subject');
|
||||
|
||||
$text = $Parser->getMessageBody('text');
|
||||
|
||||
$html = $Parser->getMessageBody('html');
|
||||
$htmlEmbedded = $Parser->getMessageBody('htmlEmbedded'); //HTML Body included data
|
||||
|
||||
$stringHeaders = $Parser->getHeadersRaw(); // Get all headers as a string, no charset conversion
|
||||
$arrayHeaders = $Parser->getHeaders(); // Get all headers as an array, with charset conversion
|
||||
|
||||
// Pass in a writeable path to save attachments
|
||||
$attach_dir = '/path/to/save/attachments/'; // Be sure to include the trailing slash
|
||||
$include_inline = true; // Optional argument to include inline attachments (default: true)
|
||||
$Parser->saveAttachments($attach_dir [,$include_inline]);
|
||||
|
||||
// Get an array of Attachment items from $Parser
|
||||
$attachments = $Parser->getAttachments([$include_inline]);
|
||||
|
||||
// Loop through all the Attachments
|
||||
if (count($attachments) > 0) {
|
||||
foreach ($attachments as $attachment) {
|
||||
echo 'Filename : '.$attachment->getFilename().'<br />'; // logo.jpg
|
||||
echo 'Filesize : '.filesize($attach_dir.$attachment->getFilename()).'<br />'; // 1000
|
||||
echo 'Filetype : '.$attachment->getContentType().'<br />'; // image/jpeg
|
||||
echo 'MIME part string : '.$attachment->getMimePartStr().'<br />'; // (the whole MIME part of the attachment)
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
```
|
||||
|
||||
Next you need to forward emails to this script above. For that I'm using [Postfix](http://www.postfix.org/) like a mail server, you need to configure /etc/postfix/master.cf
|
||||
|
||||
Add this line at the end of the file (specify myhook to send all emails to the script test.php)
|
||||
```
|
||||
myhook unix - n n - - pipe
|
||||
flags=F user=www-data argv=php -c /etc/php5/apache2/php.ini -f /var/www/test.php ${sender} ${size} ${recipient}
|
||||
```
|
||||
|
||||
Edit this line (register myhook)
|
||||
```
|
||||
smtp inet n - - - - smtpd
|
||||
-o content_filter=myhook:dummy
|
||||
```
|
||||
|
||||
The php script must use the fourth method to work with this configuration.
|
||||
|
||||
|
||||
## Can I contribute?
|
||||
|
||||
Feel free to contribute!
|
||||
|
||||
git clone https://github.com/php-mime-mail-parser/php-mime-mail-parser
|
||||
cd php-mime-mail-parser
|
||||
composer install
|
||||
./vendor/bin/phpunit
|
||||
|
||||
If you report an issue, please provide the raw email that triggered it. This helps us reproduce the issue and fix it more quickly.
|
||||
|
||||
### License
|
||||
|
||||
The php-mime-mail-parser/php-mime-mail-parser is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
|
61
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/composer.json
vendored
Normal file
61
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/composer.json
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "php-mime-mail-parser/php-mime-mail-parser",
|
||||
"type": "library",
|
||||
"description": "Fully Tested Mailparse Extension Wrapper for PHP 5.4+",
|
||||
"keywords": ["mime", "mail", "mailparse", "MimeMailParser"],
|
||||
"homepage": "https://github.com/php-mime-mail-parser/php-mime-mail-parser",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name":"eXorus",
|
||||
"email":"exorus.spam@gmail.com",
|
||||
"homepage":"https://github.com/eXorus/",
|
||||
"role":"Developer"
|
||||
},
|
||||
{
|
||||
"name":"M.Valinskis",
|
||||
"email":"M.Valins@gmail.com",
|
||||
"homepage":"https://code.google.com/p/php-mime-mail-parser",
|
||||
"role":"Developer"
|
||||
},
|
||||
{
|
||||
"name":"eugene.emmett.wood",
|
||||
"email":"gene_w@cementhorizon.com",
|
||||
"homepage":"https://code.google.com/p/php-mime-mail-parser",
|
||||
"role":"Developer"
|
||||
},
|
||||
{
|
||||
"name":"alknetso",
|
||||
"email":"alkne@gmail.com",
|
||||
"homepage":"https://code.google.com/p/php-mime-mail-parser",
|
||||
"role":"Developer"
|
||||
},
|
||||
{
|
||||
"name":"bucabay",
|
||||
"email":"gabe@fijiwebdesign.com",
|
||||
"homepage":"http://www.fijiwebdesign.com",
|
||||
"role":"Developer"
|
||||
}
|
||||
],
|
||||
"repository":{
|
||||
"type":"git",
|
||||
"url":"https://github.com/php-mime-mail-parser/php-mime-mail-parser.git"
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.4.0 || ^7.0",
|
||||
"ext-mailparse": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.0 || ^5.0",
|
||||
"phpunit/php-token-stream": "^1.3.0",
|
||||
"satooshi/php-coveralls": "0.*",
|
||||
"squizlabs/PHP_CodeSniffer": "2.*"
|
||||
},
|
||||
"replace": {
|
||||
"exorus/php-mime-mail-parser": "*",
|
||||
"messaged/php-mime-mail-parser": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "PhpMimeMailParser\\": "src/" }
|
||||
}
|
||||
}
|
303
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/mailparse-stubs.php
vendored
Normal file
303
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/mailparse-stubs.php
vendored
Normal file
@@ -0,0 +1,303 @@
|
||||
<?php
|
||||
/**
|
||||
* @link http://php.net/manual/en/mailparse.constants.php
|
||||
*/
|
||||
define('MAILPARSE_EXTRACT_OUTPUT', 0);
|
||||
|
||||
/**
|
||||
* @link http://php.net/manual/en/mailparse.constants.php
|
||||
*/
|
||||
define('MAILPARSE_EXTRACT_STREAM', 1);
|
||||
|
||||
/**
|
||||
* @link http://php.net/manual/en/mailparse.constants.php
|
||||
*/
|
||||
define('MAILPARSE_EXTRACT_RETURN', 2);
|
||||
|
||||
/**
|
||||
* Parses a file. This is the optimal way of parsing a mail file that you have on
|
||||
* disk.
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-msg-parse-file.php
|
||||
*
|
||||
* @param string $filename Path to the file holding the message. The file is opened
|
||||
* and streamed through the parser
|
||||
*
|
||||
* @return resource Returns a MIME resource representing the structure, or false on error
|
||||
*/
|
||||
function mailparse_msg_parse_file($filename)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* .
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-msg-get-part.php
|
||||
*
|
||||
* @param resource $mimemail A valid MIME resource
|
||||
* @param string $mimesection
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
function mailparse_msg_get_part($mimemail, $mimesection)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* .
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-msg-get-structure.php
|
||||
*
|
||||
* @param resource $mimemail A valid MIME resource
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function mailparse_msg_get_structure($mimemail)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* .
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-msg-get-part-data.php
|
||||
*
|
||||
* @param resource $mimemail A valid MIME resource
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function mailparse_msg_get_part_data($mimemail)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* .
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-msg-extract-part.php
|
||||
*
|
||||
* @param resource $mimemail A valid MIME resource
|
||||
* @param string $msgbody
|
||||
* @param callable $callbackfunc
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function mailparse_msg_extract_part($mimemail, $msgbody, $callbackfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts/decodes a message section from the supplied filename.
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-msg-extract-part-file.php
|
||||
*
|
||||
* @param resource $mimemail A valid MIME resource, created with
|
||||
* mailparse_msg_create
|
||||
* @param mixed $filename Can be a file name or a valid stream resource
|
||||
* @param callable $callbackfunc If set, this must be either a valid callback that
|
||||
* will be passed the extracted section, or null to make this function return the
|
||||
* extracted section
|
||||
*
|
||||
* @return string If $callbackfunc is not null returns true on success
|
||||
*/
|
||||
function mailparse_msg_extract_part_file($mimemail, $filename, $callbackfunc = false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* .
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-msg-extract-whole-part-file.php
|
||||
*
|
||||
* @param resource $mimemail A valid MIME resource
|
||||
* @param string $filename
|
||||
* @param callable $callbackfunc
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function mailparse_msg_extract_whole_part_file($mimemail, $filename, $callbackfunc)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MIME mail resource.
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-msg-create.php
|
||||
* @return resource Returns a handle that can be used to parse a message
|
||||
*/
|
||||
function mailparse_msg_create()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees a MIME resource.
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-msg-free.php
|
||||
*
|
||||
* @param resource $mimemail A valid MIME resource allocated by
|
||||
* mailparse_msg_create or mailparse_msg_parse_file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function mailparse_msg_free($mimemail)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Incrementally parse data into the supplied mime mail resource.
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-msg-parse.php
|
||||
*
|
||||
* @param resource $mimemail A valid MIME resource
|
||||
* @param string $data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function mailparse_msg_parse($mimemail, $data)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a RFC 822 compliant recipient list, such as that found in the To: header.
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-rfc822-parse-addresses.php
|
||||
*
|
||||
* @param string $addresses A string containing addresses, like in: Wez Furlong
|
||||
* wez@example.com, doe@example.com
|
||||
*
|
||||
* @return array Returns an array of associative arrays with the following keys for each
|
||||
* recipient: display The recipient name, for display purpose. If this part is not
|
||||
* set for a recipient, this key will hold the same value as address. address The
|
||||
* email address is_group true if the recipient is a newsgroup, false otherwise
|
||||
*/
|
||||
function mailparse_rfc822_parse_addresses($addresses)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Figures out the best way of encoding the content read from the given file
|
||||
* pointer.
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-determine-best-xfer-encoding.php
|
||||
*
|
||||
* @param resource $fp A valid file pointer, which must be seek-able
|
||||
*
|
||||
* @return string Returns one of the character encodings supported by the mbstring module
|
||||
*/
|
||||
function mailparse_determine_best_xfer_encoding($fp)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Streams data from the source file pointer, apply $encoding and write to the
|
||||
* destination file pointer.
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-stream-encode.php
|
||||
*
|
||||
* @param resource $sourcefp A valid file handle. The file is streamed through the
|
||||
* parser
|
||||
* @param resource $destfp The destination file handle in which the encoded data
|
||||
* will be written
|
||||
* @param string $encoding One of the character encodings supported by the mbstring
|
||||
* module
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function mailparse_stream_encode($sourcefp, $destfp, $encoding)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the data from the given file pointer and extract each embedded uuencoded
|
||||
* file into a temporary file.
|
||||
*
|
||||
* @link http://php.net/manual/en/functions.mailparse-uudecode-all.php
|
||||
*
|
||||
* @param resource $fp A valid file pointer
|
||||
*
|
||||
* @return array Returns an array of associative arrays listing filename information.
|
||||
* filename Path to the temporary file name created origfilename The original
|
||||
* filename, for uuencoded parts only The first filename entry is the message body.
|
||||
* The next entries are the decoded uuencoded files
|
||||
*/
|
||||
function mailparse_uudecode_all($fp)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
function mailparse_test()
|
||||
{
|
||||
}
|
||||
|
||||
class mimemessage
|
||||
{
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public function mimemessage()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public function get_child()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public function get_child_count()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public function get_parent()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public function extract_headers()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public function extract_body()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public function enum_uue()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public function extract_uue()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public function remove()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public function add_child()
|
||||
{
|
||||
}
|
||||
}
|
6
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/phpunit.xml.dist
vendored
Normal file
6
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/phpunit.xml.dist
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit colors="true" bootstrap="vendor/autoload.php">
|
||||
<testsuite name="eXorus PhpMimeMailParser Test Suite">
|
||||
<directory suffix="Test.php">tests</directory>
|
||||
</testsuite>
|
||||
</phpunit>
|
183
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/src/Attachment.php
vendored
Normal file
183
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/src/Attachment.php
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
namespace PhpMimeMailParser;
|
||||
|
||||
/**
|
||||
* Attachment of php-mime-mail-parser
|
||||
*
|
||||
* Fully Tested Mailparse Extension Wrapper for PHP 5.4+
|
||||
*
|
||||
*/
|
||||
class Attachment
|
||||
{
|
||||
/**
|
||||
* @var string $filename Filename
|
||||
*/
|
||||
protected $filename;
|
||||
|
||||
/**
|
||||
* @var string $contentType Mime Type
|
||||
*/
|
||||
protected $contentType;
|
||||
|
||||
/**
|
||||
* @var string $content File Content
|
||||
*/
|
||||
protected $content;
|
||||
|
||||
/**
|
||||
* @var string $contentDisposition Content-Disposition (attachment or inline)
|
||||
*/
|
||||
protected $contentDisposition;
|
||||
|
||||
/**
|
||||
* @var string $contentId Content-ID
|
||||
*/
|
||||
protected $contentId;
|
||||
|
||||
/**
|
||||
* @var array $headers An Array of the attachment headers
|
||||
*/
|
||||
protected $headers;
|
||||
|
||||
/**
|
||||
* @var resource $stream
|
||||
*/
|
||||
protected $stream;
|
||||
|
||||
/**
|
||||
* @var string $mimePartStr
|
||||
*/
|
||||
protected $mimePartStr;
|
||||
|
||||
/**
|
||||
* Attachment constructor.
|
||||
*
|
||||
* @param string $filename
|
||||
* @param string $contentType
|
||||
* @param resource $stream
|
||||
* @param string $contentDisposition
|
||||
* @param string $contentId
|
||||
* @param array $headers
|
||||
* @param string $mimePartStr
|
||||
*/
|
||||
public function __construct(
|
||||
$filename,
|
||||
$contentType,
|
||||
$stream,
|
||||
$contentDisposition = 'attachment',
|
||||
$contentId = '',
|
||||
$headers = [],
|
||||
$mimePartStr = ''
|
||||
) {
|
||||
$this->filename = $filename;
|
||||
$this->contentType = $contentType;
|
||||
$this->stream = $stream;
|
||||
$this->content = null;
|
||||
$this->contentDisposition = $contentDisposition;
|
||||
$this->contentId = $contentId;
|
||||
$this->headers = $headers;
|
||||
$this->mimePartStr = $mimePartStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve the attachment filename
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFilename()
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Attachment Content-Type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContentType()
|
||||
{
|
||||
return $this->contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Attachment Content-Disposition
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContentDisposition()
|
||||
{
|
||||
return $this->contentDisposition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Attachment Content-ID
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContentID()
|
||||
{
|
||||
return $this->contentId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Attachment Headers
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a handle to the stream
|
||||
*
|
||||
* @return stream
|
||||
*/
|
||||
public function getStream()
|
||||
{
|
||||
return $this->stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the contents a few bytes at a time until completed
|
||||
* Once read to completion, it always returns false
|
||||
*
|
||||
* @param int $bytes (default: 2082)
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public function read($bytes = 2082)
|
||||
{
|
||||
return feof($this->stream) ? false : fread($this->stream, $bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the file content in one go
|
||||
* Once you retrieve the content you cannot use MimeMailParser_attachment::read()
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContent()
|
||||
{
|
||||
if ($this->content === null) {
|
||||
fseek($this->stream, 0);
|
||||
while (($buf = $this->read()) !== false) {
|
||||
$this->content .= $buf;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mime part string for this attachment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMimePartStr()
|
||||
{
|
||||
return $this->mimePartStr;
|
||||
}
|
||||
}
|
338
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/src/Charset.php
vendored
Normal file
338
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/src/Charset.php
vendored
Normal file
@@ -0,0 +1,338 @@
|
||||
<?php namespace PhpMimeMailParser;
|
||||
|
||||
use PhpMimeMailParser\Contracts\CharsetManager;
|
||||
|
||||
class Charset implements CharsetManager
|
||||
{
|
||||
/**
|
||||
* Charset Aliases
|
||||
*/
|
||||
private $charsetAlias = [
|
||||
'ascii' => 'us-ascii',
|
||||
'us-ascii' => 'us-ascii',
|
||||
'ansi_x3.4-1968' => 'us-ascii',
|
||||
'646' => 'us-ascii',
|
||||
'iso-8859-1' => 'ISO-8859-1',
|
||||
'iso-8859-2' => 'ISO-8859-2',
|
||||
'iso-8859-3' => 'ISO-8859-3',
|
||||
'iso-8859-4' => 'ISO-8859-4',
|
||||
'iso-8859-5' => 'ISO-8859-5',
|
||||
'iso-8859-6' => 'ISO-8859-6',
|
||||
'iso-8859-6-i' => 'ISO-8859-6-I',
|
||||
'iso-8859-6-e' => 'ISO-8859-6-E',
|
||||
'iso-8859-7' => 'ISO-8859-7',
|
||||
'iso-8859-8' => 'ISO-8859-8',
|
||||
'iso-8859-8-i' => 'ISO-8859-8',
|
||||
'iso-8859-8-e' => 'ISO-8859-8-E',
|
||||
'iso-8859-9' => 'ISO-8859-9',
|
||||
'iso-8859-10' => 'ISO-8859-10',
|
||||
'iso-8859-11' => 'ISO-8859-11',
|
||||
'iso-8859-13' => 'ISO-8859-13',
|
||||
'iso-8859-14' => 'ISO-8859-14',
|
||||
'iso-8859-15' => 'ISO-8859-15',
|
||||
'iso-8859-16' => 'ISO-8859-16',
|
||||
'iso-ir-111' => 'ISO-IR-111',
|
||||
'iso-2022-cn' => 'ISO-2022-CN',
|
||||
'iso-2022-cn-ext' => 'ISO-2022-CN',
|
||||
'iso-2022-kr' => 'ISO-2022-KR',
|
||||
'iso-2022-jp' => 'ISO-2022-JP',
|
||||
'utf-16be' => 'UTF-16BE',
|
||||
'utf-16le' => 'UTF-16LE',
|
||||
'utf-16' => 'UTF-16',
|
||||
'windows-1250' => 'windows-1250',
|
||||
'windows-1251' => 'windows-1251',
|
||||
'windows-1252' => 'windows-1252',
|
||||
'windows-1253' => 'windows-1253',
|
||||
'windows-1254' => 'windows-1254',
|
||||
'windows-1255' => 'windows-1255',
|
||||
'windows-1256' => 'windows-1256',
|
||||
'windows-1257' => 'windows-1257',
|
||||
'windows-1258' => 'windows-1258',
|
||||
'ibm866' => 'IBM866',
|
||||
'ibm850' => 'IBM850',
|
||||
'ibm852' => 'IBM852',
|
||||
'ibm855' => 'IBM855',
|
||||
'ibm857' => 'IBM857',
|
||||
'ibm862' => 'IBM862',
|
||||
'ibm864' => 'IBM864',
|
||||
'utf-8' => 'UTF-8',
|
||||
'utf-7' => 'UTF-7',
|
||||
'shift_jis' => 'Shift_JIS',
|
||||
'big5' => 'Big5',
|
||||
'euc-jp' => 'EUC-JP',
|
||||
'euc-kr' => 'EUC-KR',
|
||||
'gb2312' => 'GB2312',
|
||||
'gb18030' => 'gb18030',
|
||||
'viscii' => 'VISCII',
|
||||
'koi8-r' => 'KOI8-R',
|
||||
'koi8_r' => 'KOI8-R',
|
||||
'cskoi8r' => 'KOI8-R',
|
||||
'koi' => 'KOI8-R',
|
||||
'koi8' => 'KOI8-R',
|
||||
'koi8-u' => 'KOI8-U',
|
||||
'tis-620' => 'TIS-620',
|
||||
't.61-8bit' => 'T.61-8bit',
|
||||
'hz-gb-2312' => 'HZ-GB-2312',
|
||||
'big5-hkscs' => 'Big5-HKSCS',
|
||||
'gbk' => 'gbk',
|
||||
'cns11643' => 'x-euc-tw',
|
||||
'x-imap4-modified-utf7' => 'x-imap4-modified-utf7',
|
||||
'x-euc-tw' => 'x-euc-tw',
|
||||
'x-mac-ce' => 'x-mac-ce',
|
||||
'x-mac-turkish' => 'x-mac-turkish',
|
||||
'x-mac-greek' => 'x-mac-greek',
|
||||
'x-mac-icelandic' => 'x-mac-icelandic',
|
||||
'x-mac-croatian' => 'x-mac-croatian',
|
||||
'x-mac-romanian' => 'x-mac-romanian',
|
||||
'x-mac-cyrillic' => 'x-mac-cyrillic',
|
||||
'x-mac-ukrainian' => 'x-mac-cyrillic',
|
||||
'x-mac-hebrew' => 'x-mac-hebrew',
|
||||
'x-mac-arabic' => 'x-mac-arabic',
|
||||
'x-mac-farsi' => 'x-mac-farsi',
|
||||
'x-mac-devanagari' => 'x-mac-devanagari',
|
||||
'x-mac-gujarati' => 'x-mac-gujarati',
|
||||
'x-mac-gurmukhi' => 'x-mac-gurmukhi',
|
||||
'armscii-8' => 'armscii-8',
|
||||
'x-viet-tcvn5712' => 'x-viet-tcvn5712',
|
||||
'x-viet-vps' => 'x-viet-vps',
|
||||
'iso-10646-ucs-2' => 'UTF-16BE',
|
||||
'x-iso-10646-ucs-2-be' => 'UTF-16BE',
|
||||
'x-iso-10646-ucs-2-le' => 'UTF-16LE',
|
||||
'x-user-defined' => 'x-user-defined',
|
||||
'x-johab' => 'x-johab',
|
||||
'latin1' => 'ISO-8859-1',
|
||||
'iso_8859-1' => 'ISO-8859-1',
|
||||
'iso8859-1' => 'ISO-8859-1',
|
||||
'iso8859-2' => 'ISO-8859-2',
|
||||
'iso8859-3' => 'ISO-8859-3',
|
||||
'iso8859-4' => 'ISO-8859-4',
|
||||
'iso8859-5' => 'ISO-8859-5',
|
||||
'iso8859-6' => 'ISO-8859-6',
|
||||
'iso8859-7' => 'ISO-8859-7',
|
||||
'iso8859-8' => 'ISO-8859-8',
|
||||
'iso8859-9' => 'ISO-8859-9',
|
||||
'iso8859-10' => 'ISO-8859-10',
|
||||
'iso8859-11' => 'ISO-8859-11',
|
||||
'iso8859-13' => 'ISO-8859-13',
|
||||
'iso8859-14' => 'ISO-8859-14',
|
||||
'iso8859-15' => 'ISO-8859-15',
|
||||
'iso_8859-1:1987' => 'ISO-8859-1',
|
||||
'iso-ir-100' => 'ISO-8859-1',
|
||||
'l1' => 'ISO-8859-1',
|
||||
'ibm819' => 'ISO-8859-1',
|
||||
'cp819' => 'ISO-8859-1',
|
||||
'csisolatin1' => 'ISO-8859-1',
|
||||
'latin2' => 'ISO-8859-2',
|
||||
'iso_8859-2' => 'ISO-8859-2',
|
||||
'iso_8859-2:1987' => 'ISO-8859-2',
|
||||
'iso-ir-101' => 'ISO-8859-2',
|
||||
'l2' => 'ISO-8859-2',
|
||||
'csisolatin2' => 'ISO-8859-2',
|
||||
'latin3' => 'ISO-8859-3',
|
||||
'iso_8859-3' => 'ISO-8859-3',
|
||||
'iso_8859-3:1988' => 'ISO-8859-3',
|
||||
'iso-ir-109' => 'ISO-8859-3',
|
||||
'l3' => 'ISO-8859-3',
|
||||
'csisolatin3' => 'ISO-8859-3',
|
||||
'latin4' => 'ISO-8859-4',
|
||||
'iso_8859-4' => 'ISO-8859-4',
|
||||
'iso_8859-4:1988' => 'ISO-8859-4',
|
||||
'iso-ir-110' => 'ISO-8859-4',
|
||||
'l4' => 'ISO-8859-4',
|
||||
'csisolatin4' => 'ISO-8859-4',
|
||||
'cyrillic' => 'ISO-8859-5',
|
||||
'iso_8859-5' => 'ISO-8859-5',
|
||||
'iso_8859-5:1988' => 'ISO-8859-5',
|
||||
'iso-ir-144' => 'ISO-8859-5',
|
||||
'csisolatincyrillic' => 'ISO-8859-5',
|
||||
'arabic' => 'ISO-8859-6',
|
||||
'iso_8859-6' => 'ISO-8859-6',
|
||||
'iso_8859-6:1987' => 'ISO-8859-6',
|
||||
'iso-ir-127' => 'ISO-8859-6',
|
||||
'ecma-114' => 'ISO-8859-6',
|
||||
'asmo-708' => 'ISO-8859-6',
|
||||
'csisolatinarabic' => 'ISO-8859-6',
|
||||
'csiso88596i' => 'ISO-8859-6-I',
|
||||
'csiso88596e' => 'ISO-8859-6-E',
|
||||
'greek' => 'ISO-8859-7',
|
||||
'greek8' => 'ISO-8859-7',
|
||||
'sun_eu_greek' => 'ISO-8859-7',
|
||||
'iso_8859-7' => 'ISO-8859-7',
|
||||
'iso_8859-7:1987' => 'ISO-8859-7',
|
||||
'iso-ir-126' => 'ISO-8859-7',
|
||||
'elot_928' => 'ISO-8859-7',
|
||||
'ecma-118' => 'ISO-8859-7',
|
||||
'csisolatingreek' => 'ISO-8859-7',
|
||||
'hebrew' => 'ISO-8859-8',
|
||||
'iso_8859-8' => 'ISO-8859-8',
|
||||
'visual' => 'ISO-8859-8',
|
||||
'iso_8859-8:1988' => 'ISO-8859-8',
|
||||
'iso-ir-138' => 'ISO-8859-8',
|
||||
'csisolatinhebrew' => 'ISO-8859-8',
|
||||
'csiso88598i' => 'ISO-8859-8',
|
||||
'iso-8859-8i' => 'ISO-8859-8',
|
||||
'logical' => 'ISO-8859-8',
|
||||
'csiso88598e' => 'ISO-8859-8-E',
|
||||
'latin5' => 'ISO-8859-9',
|
||||
'iso_8859-9' => 'ISO-8859-9',
|
||||
'iso_8859-9:1989' => 'ISO-8859-9',
|
||||
'iso-ir-148' => 'ISO-8859-9',
|
||||
'l5' => 'ISO-8859-9',
|
||||
'csisolatin5' => 'ISO-8859-9',
|
||||
'unicode-1-1-utf-8' => 'UTF-8',
|
||||
'utf8' => 'UTF-8',
|
||||
'x-sjis' => 'Shift_JIS',
|
||||
'shift-jis' => 'Shift_JIS',
|
||||
'ms_kanji' => 'Shift_JIS',
|
||||
'csshiftjis' => 'Shift_JIS',
|
||||
'windows-31j' => 'Shift_JIS',
|
||||
'cp932' => 'Shift_JIS',
|
||||
'sjis' => 'Shift_JIS',
|
||||
'cseucpkdfmtjapanese' => 'EUC-JP',
|
||||
'x-euc-jp' => 'EUC-JP',
|
||||
'csiso2022jp' => 'ISO-2022-JP',
|
||||
'iso-2022-jp-2' => 'ISO-2022-JP',
|
||||
'csiso2022jp2' => 'ISO-2022-JP',
|
||||
'csbig5' => 'Big5',
|
||||
'cn-big5' => 'Big5',
|
||||
'x-x-big5' => 'Big5',
|
||||
'zh_tw-big5' => 'Big5',
|
||||
'cseuckr' => 'EUC-KR',
|
||||
'ks_c_5601-1987' => 'EUC-KR',
|
||||
'iso-ir-149' => 'EUC-KR',
|
||||
'ks_c_5601-1989' => 'EUC-KR',
|
||||
'ksc_5601' => 'EUC-KR',
|
||||
'ksc5601' => 'EUC-KR',
|
||||
'korean' => 'EUC-KR',
|
||||
'csksc56011987' => 'EUC-KR',
|
||||
'5601' => 'EUC-KR',
|
||||
'windows-949' => 'EUC-KR',
|
||||
'gb_2312-80' => 'GB2312',
|
||||
'iso-ir-58' => 'GB2312',
|
||||
'chinese' => 'GB2312',
|
||||
'csiso58gb231280' => 'GB2312',
|
||||
'csgb2312' => 'GB2312',
|
||||
'zh_cn.euc' => 'GB2312',
|
||||
'gb_2312' => 'GB2312',
|
||||
'x-cp1250' => 'windows-1250',
|
||||
'x-cp1251' => 'windows-1251',
|
||||
'x-cp1252' => 'windows-1252',
|
||||
'x-cp1253' => 'windows-1253',
|
||||
'x-cp1254' => 'windows-1254',
|
||||
'x-cp1255' => 'windows-1255',
|
||||
'x-cp1256' => 'windows-1256',
|
||||
'x-cp1257' => 'windows-1257',
|
||||
'x-cp1258' => 'windows-1258',
|
||||
'windows-874' => 'windows-874',
|
||||
'ibm874' => 'windows-874',
|
||||
'dos-874' => 'windows-874',
|
||||
'macintosh' => 'macintosh',
|
||||
'x-mac-roman' => 'macintosh',
|
||||
'mac' => 'macintosh',
|
||||
'csmacintosh' => 'macintosh',
|
||||
'cp866' => 'IBM866',
|
||||
'cp-866' => 'IBM866',
|
||||
'866' => 'IBM866',
|
||||
'csibm866' => 'IBM866',
|
||||
'cp850' => 'IBM850',
|
||||
'850' => 'IBM850',
|
||||
'csibm850' => 'IBM850',
|
||||
'cp852' => 'IBM852',
|
||||
'852' => 'IBM852',
|
||||
'csibm852' => 'IBM852',
|
||||
'cp855' => 'IBM855',
|
||||
'855' => 'IBM855',
|
||||
'csibm855' => 'IBM855',
|
||||
'cp857' => 'IBM857',
|
||||
'857' => 'IBM857',
|
||||
'csibm857' => 'IBM857',
|
||||
'cp862' => 'IBM862',
|
||||
'862' => 'IBM862',
|
||||
'csibm862' => 'IBM862',
|
||||
'cp864' => 'IBM864',
|
||||
'864' => 'IBM864',
|
||||
'csibm864' => 'IBM864',
|
||||
'ibm-864' => 'IBM864',
|
||||
't.61' => 'T.61-8bit',
|
||||
'iso-ir-103' => 'T.61-8bit',
|
||||
'csiso103t618bit' => 'T.61-8bit',
|
||||
'x-unicode-2-0-utf-7' => 'UTF-7',
|
||||
'unicode-2-0-utf-7' => 'UTF-7',
|
||||
'unicode-1-1-utf-7' => 'UTF-7',
|
||||
'csunicode11utf7' => 'UTF-7',
|
||||
'csunicode' => 'UTF-16BE',
|
||||
'csunicode11' => 'UTF-16BE',
|
||||
'iso-10646-ucs-basic' => 'UTF-16BE',
|
||||
'csunicodeascii' => 'UTF-16BE',
|
||||
'iso-10646-unicode-latin1' => 'UTF-16BE',
|
||||
'csunicodelatin1' => 'UTF-16BE',
|
||||
'iso-10646' => 'UTF-16BE',
|
||||
'iso-10646-j-1' => 'UTF-16BE',
|
||||
'latin6' => 'ISO-8859-10',
|
||||
'iso-ir-157' => 'ISO-8859-10',
|
||||
'l6' => 'ISO-8859-10',
|
||||
'csisolatin6' => 'ISO-8859-10',
|
||||
'iso_8859-15' => 'ISO-8859-15',
|
||||
'csisolatin9' => 'ISO-8859-15',
|
||||
'l9' => 'ISO-8859-15',
|
||||
'ecma-cyrillic' => 'ISO-IR-111',
|
||||
'csiso111ecmacyrillic' => 'ISO-IR-111',
|
||||
'csiso2022kr' => 'ISO-2022-KR',
|
||||
'csviscii' => 'VISCII',
|
||||
'zh_tw-euc' => 'x-euc-tw',
|
||||
'iso88591' => 'ISO-8859-1',
|
||||
'iso88592' => 'ISO-8859-2',
|
||||
'iso88593' => 'ISO-8859-3',
|
||||
'iso88594' => 'ISO-8859-4',
|
||||
'iso88595' => 'ISO-8859-5',
|
||||
'iso88596' => 'ISO-8859-6',
|
||||
'iso88597' => 'ISO-8859-7',
|
||||
'iso88598' => 'ISO-8859-8',
|
||||
'iso88599' => 'ISO-8859-9',
|
||||
'iso885910' => 'ISO-8859-10',
|
||||
'iso885911' => 'ISO-8859-11',
|
||||
'iso885912' => 'ISO-8859-12',
|
||||
'iso885913' => 'ISO-8859-13',
|
||||
'iso885914' => 'ISO-8859-14',
|
||||
'iso885915' => 'ISO-8859-15',
|
||||
'tis620' => 'TIS-620',
|
||||
'cp1250' => 'windows-1250',
|
||||
'cp1251' => 'windows-1251',
|
||||
'cp1252' => 'windows-1252',
|
||||
'cp1253' => 'windows-1253',
|
||||
'cp1254' => 'windows-1254',
|
||||
'cp1255' => 'windows-1255',
|
||||
'cp1256' => 'windows-1256',
|
||||
'cp1257' => 'windows-1257',
|
||||
'cp1258' => 'windows-1258',
|
||||
'x-gbk' => 'gbk',
|
||||
'windows-936' => 'gbk',
|
||||
'ansi-1251' => 'windows-1251',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function decodeCharset($encodedString, $charset)
|
||||
{
|
||||
if (strtolower($charset) == 'utf-8' || strtolower($charset) == 'us-ascii') {
|
||||
return $encodedString;
|
||||
} else {
|
||||
return iconv($this->getCharsetAlias($charset), 'UTF-8//TRANSLIT//IGNORE', $encodedString);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCharsetAlias($charset)
|
||||
{
|
||||
$charset = strtolower($charset);
|
||||
|
||||
if (array_key_exists($charset, $this->charsetAlias)) {
|
||||
return $this->charsetAlias[$charset];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
<?php namespace PhpMimeMailParser\Contracts;
|
||||
|
||||
interface CharsetManager
|
||||
{
|
||||
|
||||
/**
|
||||
* Decode the string from Charset
|
||||
*
|
||||
* @param string $encodedString The string in its original encoded state
|
||||
* @param string $charset The Charset header of the part.
|
||||
*
|
||||
* @return string The decoded string
|
||||
*/
|
||||
public function decodeCharset($encodedString, $charset);
|
||||
|
||||
/**
|
||||
* Get charset alias
|
||||
*
|
||||
* @param string $charset .
|
||||
*
|
||||
* @return string The charset alias
|
||||
*/
|
||||
public function getCharsetAlias($charset);
|
||||
}
|
8
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/src/Exception.php
vendored
Normal file
8
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/src/Exception.php
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace PhpMimeMailParser;
|
||||
|
||||
class Exception extends \RuntimeException
|
||||
{
|
||||
|
||||
}
|
893
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/src/Parser.php
vendored
Normal file
893
data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/src/Parser.php
vendored
Normal file
@@ -0,0 +1,893 @@
|
||||
<?php
|
||||
|
||||
namespace PhpMimeMailParser;
|
||||
|
||||
use PhpMimeMailParser\Contracts\CharsetManager;
|
||||
|
||||
/**
|
||||
* Parser of php-mime-mail-parser
|
||||
*
|
||||
* Fully Tested Mailparse Extension Wrapper for PHP 5.4+
|
||||
*
|
||||
*/
|
||||
class Parser
|
||||
{
|
||||
/**
|
||||
* Attachment filename argument option for ->saveAttachments().
|
||||
*/
|
||||
const ATTACHMENT_DUPLICATE_THROW = 'DuplicateThrow';
|
||||
const ATTACHMENT_DUPLICATE_SUFFIX = 'DuplicateSuffix';
|
||||
const ATTACHMENT_RANDOM_FILENAME = 'RandomFilename';
|
||||
|
||||
/**
|
||||
* PHP MimeParser Resource ID
|
||||
*
|
||||
* @var resource $resource
|
||||
*/
|
||||
protected $resource;
|
||||
|
||||
/**
|
||||
* A file pointer to email
|
||||
*
|
||||
* @var resource $stream
|
||||
*/
|
||||
protected $stream;
|
||||
|
||||
/**
|
||||
* A text of an email
|
||||
*
|
||||
* @var string $data
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* Parts of an email
|
||||
*
|
||||
* @var array $parts
|
||||
*/
|
||||
protected $parts;
|
||||
|
||||
/**
|
||||
* @var CharsetManager object
|
||||
*/
|
||||
protected $charset;
|
||||
|
||||
/**
|
||||
* Parser constructor.
|
||||
*
|
||||
* @param CharsetManager|null $charset
|
||||
*/
|
||||
public function __construct(CharsetManager $charset = null)
|
||||
{
|
||||
if ($charset == null) {
|
||||
$charset = new Charset();
|
||||
}
|
||||
|
||||
$this->charset = $charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Free the held resources
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
// clear the email file resource
|
||||
if (is_resource($this->stream)) {
|
||||
fclose($this->stream);
|
||||
}
|
||||
// clear the MailParse resource
|
||||
if (is_resource($this->resource)) {
|
||||
mailparse_msg_free($this->resource);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the file path we use to get the email text
|
||||
*
|
||||
* @param string $path File path to the MIME mail
|
||||
*
|
||||
* @return Parser MimeMailParser Instance
|
||||
*/
|
||||
public function setPath($path)
|
||||
{
|
||||
// should parse message incrementally from file
|
||||
$this->resource = mailparse_msg_parse_file($path);
|
||||
$this->stream = fopen($path, 'r');
|
||||
$this->parse();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Stream resource we use to get the email text
|
||||
*
|
||||
* @param resource $stream
|
||||
*
|
||||
* @return Parser MimeMailParser Instance
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setStream($stream)
|
||||
{
|
||||
// streams have to be cached to file first
|
||||
$meta = @stream_get_meta_data($stream);
|
||||
if (!$meta || !$meta['mode'] || $meta['mode'][0] != 'r' || $meta['eof']) {
|
||||
throw new Exception(
|
||||
'setStream() expects parameter stream to be readable stream resource.'
|
||||
);
|
||||
}
|
||||
|
||||
/** @var resource $tmp_fp */
|
||||
$tmp_fp = tmpfile();
|
||||
if ($tmp_fp) {
|
||||
while (!feof($stream)) {
|
||||
fwrite($tmp_fp, fread($stream, 2028));
|
||||
}
|
||||
fseek($tmp_fp, 0);
|
||||
$this->stream = &$tmp_fp;
|
||||
} else {
|
||||
throw new Exception(
|
||||
'Could not create temporary files for attachments. Your tmp directory may be unwritable by PHP.'
|
||||
);
|
||||
}
|
||||
fclose($stream);
|
||||
|
||||
$this->resource = mailparse_msg_create();
|
||||
// parses the message incrementally (low memory usage but slower)
|
||||
while (!feof($this->stream)) {
|
||||
mailparse_msg_parse($this->resource, fread($this->stream, 2082));
|
||||
}
|
||||
$this->parse();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the email text
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @return Parser MimeMailParser Instance
|
||||
*/
|
||||
public function setText($data)
|
||||
{
|
||||
if (!$data) {
|
||||
throw new Exception('You must not call MimeMailParser::setText with an empty string parameter');
|
||||
}
|
||||
$this->resource = mailparse_msg_create();
|
||||
// does not parse incrementally, fast memory hog might explode
|
||||
mailparse_msg_parse($this->resource, $data);
|
||||
$this->data = $data;
|
||||
$this->parse();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the Message into parts
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function parse()
|
||||
{
|
||||
$structure = mailparse_msg_get_structure($this->resource);
|
||||
$this->parts = [];
|
||||
foreach ($structure as $part_id) {
|
||||
$part = mailparse_msg_get_part($this->resource, $part_id);
|
||||
$this->parts[$part_id] = mailparse_msg_get_part_data($part);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a specific Email Header, without charset conversion.
|
||||
*
|
||||
* @param string $name Header name (case-insensitive)
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getRawHeader($name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
if (isset($this->parts[1])) {
|
||||
$headers = $this->getPart('headers', $this->parts[1]);
|
||||
|
||||
return (isset($headers[$name])) ? $headers[$name] : false;
|
||||
} else {
|
||||
throw new Exception(
|
||||
'setPath() or setText() or setStream() must be called before retrieving email headers.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a specific Email Header
|
||||
*
|
||||
* @param string $name Header name (case-insensitive)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHeader($name)
|
||||
{
|
||||
$rawHeader = $this->getRawHeader($name);
|
||||
if ($rawHeader === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->decodeHeader($rawHeader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all mail headers
|
||||
*
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getHeaders()
|
||||
{
|
||||
if (isset($this->parts[1])) {
|
||||
$headers = $this->getPart('headers', $this->parts[1]);
|
||||
foreach ($headers as $name => &$value) {
|
||||
if (is_array($value)) {
|
||||
foreach ($value as &$v) {
|
||||
$v = $this->decodeSingleHeader($v);
|
||||
}
|
||||
} else {
|
||||
$value = $this->decodeSingleHeader($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
} else {
|
||||
throw new Exception(
|
||||
'setPath() or setText() or setStream() must be called before retrieving email headers.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the raw mail headers as a string
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getHeadersRaw()
|
||||
{
|
||||
if (isset($this->parts[1])) {
|
||||
return $this->getPartHeader($this->parts[1]);
|
||||
} else {
|
||||
throw new Exception(
|
||||
'setPath() or setText() or setStream() must be called before retrieving email headers.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the raw Header of a MIME part
|
||||
*
|
||||
* @return String
|
||||
* @param $part Object
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function getPartHeader(&$part)
|
||||
{
|
||||
$header = '';
|
||||
if ($this->stream) {
|
||||
$header = $this->getPartHeaderFromFile($part);
|
||||
} elseif ($this->data) {
|
||||
$header = $this->getPartHeaderFromText($part);
|
||||
}
|
||||
return $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Header from a MIME part from file
|
||||
*
|
||||
* @return String Mime Header Part
|
||||
* @param $part Array
|
||||
*/
|
||||
protected function getPartHeaderFromFile(&$part)
|
||||
{
|
||||
$start = $part['starting-pos'];
|
||||
$end = $part['starting-pos-body'];
|
||||
fseek($this->stream, $start, SEEK_SET);
|
||||
$header = fread($this->stream, $end-$start);
|
||||
return $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Header from a MIME part from text
|
||||
*
|
||||
* @return String Mime Header Part
|
||||
* @param $part Array
|
||||
*/
|
||||
protected function getPartHeaderFromText(&$part)
|
||||
{
|
||||
$start = $part['starting-pos'];
|
||||
$end = $part['starting-pos-body'];
|
||||
$header = substr($this->data, $start, $end-$start);
|
||||
return $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a given part ID is a child of another part
|
||||
* eg. an RFC822 attachment may have one or more text parts
|
||||
*
|
||||
* @param string $partId
|
||||
* @param string $parentPartId
|
||||
* @return bool
|
||||
*/
|
||||
protected function partIdIsChildOfPart($partId, $parentPartId)
|
||||
{
|
||||
return substr($partId, 0, strlen($parentPartId)) == $parentPartId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the given part ID is a child of any attachment part in the message.
|
||||
*
|
||||
* @param string $checkPartId
|
||||
* @return bool
|
||||
*/
|
||||
protected function partIdIsChildOfAnAttachment($checkPartId)
|
||||
{
|
||||
foreach ($this->parts as $partId => $part) {
|
||||
if ($this->getPart('content-disposition', $part) == 'attachment') {
|
||||
if ($this->partIdIsChildOfPart($checkPartId, $partId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the email message body in the specified format
|
||||
*
|
||||
* @param string $type text, html or htmlEmbedded
|
||||
*
|
||||
* @return false|string Body or False if not found
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getMessageBody($type = 'text')
|
||||
{
|
||||
$body = false;
|
||||
$mime_types = [
|
||||
'text' => 'text/plain',
|
||||
'html' => 'text/html',
|
||||
'htmlEmbedded' => 'text/html',
|
||||
];
|
||||
|
||||
if (in_array($type, array_keys($mime_types))) {
|
||||
$part_type = $type === 'htmlEmbedded' ? 'html' : $type;
|
||||
$inline_parts = $this->getInlineParts($part_type);
|
||||
$body = empty($inline_parts) ? '' : $inline_parts[0];
|
||||
} else {
|
||||
throw new Exception(
|
||||
'Invalid type specified for getMessageBody(). Expected: text, html or htmlEmbeded.'
|
||||
);
|
||||
}
|
||||
|
||||
if ($type == 'htmlEmbedded') {
|
||||
$attachments = $this->getAttachments();
|
||||
foreach ($attachments as $attachment) {
|
||||
if ($attachment->getContentID() != '') {
|
||||
$body = str_replace(
|
||||
'"cid:'.$attachment->getContentID().'"',
|
||||
'"'.$this->getEmbeddedData($attachment->getContentID()).'"',
|
||||
$body
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the embedded data structure
|
||||
*
|
||||
* @param string $contentId Content-Id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getEmbeddedData($contentId)
|
||||
{
|
||||
foreach ($this->parts as $part) {
|
||||
if ($this->getPart('content-id', $part) == $contentId) {
|
||||
$embeddedData = 'data:';
|
||||
$embeddedData .= $this->getPart('content-type', $part);
|
||||
$embeddedData .= ';'.$this->getPart('transfer-encoding', $part);
|
||||
$embeddedData .= ','.$this->getPartBody($part);
|
||||
return $embeddedData;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array with the following keys display, address, is_group
|
||||
*
|
||||
* @param string $name Header name (case-insensitive)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAddresses($name)
|
||||
{
|
||||
$value = $this->getHeader($name);
|
||||
|
||||
return mailparse_rfc822_parse_addresses($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attachments contents in order of appearance
|
||||
*
|
||||
* @return Attachment[]
|
||||
*/
|
||||
public function getInlineParts($type = 'text')
|
||||
{
|
||||
$inline_parts = [];
|
||||
$dispositions = ['inline'];
|
||||
$mime_types = [
|
||||
'text' => 'text/plain',
|
||||
'html' => 'text/html',
|
||||
];
|
||||
|
||||
if (!in_array($type, array_keys($mime_types))) {
|
||||
throw new Exception('Invalid type specified for getInlineParts(). "type" can either be text or html.');
|
||||
}
|
||||
|
||||
foreach ($this->parts as $partId => $part) {
|
||||
if ($this->getPart('content-type', $part) == $mime_types[$type]
|
||||
&& $this->getPart('content-disposition', $part) != 'attachment'
|
||||
&& !$this->partIdIsChildOfAnAttachment($partId)
|
||||
) {
|
||||
$headers = $this->getPart('headers', $part);
|
||||
$encodingType = array_key_exists('content-transfer-encoding', $headers) ?
|
||||
$headers['content-transfer-encoding'] : '';
|
||||
if (is_array($encodingType)) {
|
||||
$encodingType = $encodingType[0];
|
||||
}
|
||||
$undecoded_body = $this->decodeContentTransfer($this->getPartBody($part), $encodingType);
|
||||
$inline_parts[] = $this->charset->decodeCharset($undecoded_body, $this->getPartCharset($part));
|
||||
}
|
||||
}
|
||||
|
||||
return $inline_parts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attachments contents in order of appearance
|
||||
*
|
||||
* @return Attachment[]
|
||||
*/
|
||||
public function getAttachments($include_inline = true)
|
||||
{
|
||||
$attachments = [];
|
||||
$dispositions = $include_inline ?
|
||||
['attachment', 'inline'] :
|
||||
['attachment'];
|
||||
$non_attachment_types = ['text/plain', 'text/html'];
|
||||
$nonameIter = 0;
|
||||
|
||||
foreach ($this->parts as $part) {
|
||||
$disposition = $this->getPart('content-disposition', $part);
|
||||
$filename = 'noname';
|
||||
|
||||
if (isset($part['disposition-filename'])) {
|
||||
$filename = $this->decodeHeader($part['disposition-filename']);
|
||||
// Escape all potentially unsafe characters from the filename
|
||||
$filename = preg_replace('((^\.)|\/|(\.$))', '_', $filename);
|
||||
} elseif (isset($part['content-name'])) {
|
||||
// if we have no disposition but we have a content-name, it's a valid attachment.
|
||||
// we simulate the presence of an attachment disposition with a disposition filename
|
||||
$filename = $this->decodeHeader($part['content-name']);
|
||||
// Escape all potentially unsafe characters from the filename
|
||||
$filename = preg_replace('((^\.)|\/|(\.$))', '_', $filename);
|
||||
$disposition = 'attachment';
|
||||
} elseif (in_array($part['content-type'], $non_attachment_types, true)
|
||||
&& $disposition !== 'attachment') {
|
||||
// it is a message body, no attachment
|
||||
continue;
|
||||
} elseif (substr($part['content-type'], 0, 10) !== 'multipart/') {
|
||||
// if we cannot get it by getMessageBody(), we assume it is an attachment
|
||||
$disposition = 'attachment';
|
||||
}
|
||||
|
||||
if (in_array($disposition, $dispositions) === true) {
|
||||
if ($filename == 'noname') {
|
||||
$nonameIter++;
|
||||
$filename = 'noname'.$nonameIter;
|
||||
}
|
||||
|
||||
$headersAttachments = $this->getPart('headers', $part);
|
||||
$contentidAttachments = $this->getPart('content-id', $part);
|
||||
|
||||
$mimePartStr = $this->getPartComplete($part);
|
||||
|
||||
$attachments[] = new Attachment(
|
||||
$filename,
|
||||
$this->getPart('content-type', $part),
|
||||
$this->getAttachmentStream($part),
|
||||
$disposition,
|
||||
$contentidAttachments,
|
||||
$headersAttachments,
|
||||
$mimePartStr
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save attachments in a folder
|
||||
*
|
||||
* @param string $attach_dir directory
|
||||
* @param bool $include_inline
|
||||
* @param string $filenameStrategy How to generate attachment filenames
|
||||
*
|
||||
* @return array Saved attachments paths
|
||||
* @throws Exception
|
||||
*/
|
||||
public function saveAttachments(
|
||||
$attach_dir,
|
||||
$include_inline = true,
|
||||
$filenameStrategy = self::ATTACHMENT_DUPLICATE_SUFFIX
|
||||
) {
|
||||
$attachments = $this->getAttachments($include_inline);
|
||||
if (empty($attachments)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_dir($attach_dir)) {
|
||||
mkdir($attach_dir);
|
||||
}
|
||||
|
||||
$attachments_paths = [];
|
||||
foreach ($attachments as $attachment) {
|
||||
// Determine filename
|
||||
switch ($filenameStrategy) {
|
||||
case self::ATTACHMENT_RANDOM_FILENAME:
|
||||
$attachment_path = tempnam($attach_dir, '');
|
||||
break;
|
||||
case self::ATTACHMENT_DUPLICATE_THROW:
|
||||
case self::ATTACHMENT_DUPLICATE_SUFFIX:
|
||||
$attachment_path = $attach_dir . $attachment->getFilename();
|
||||
break;
|
||||
default:
|
||||
throw new Exception('Invalid filename strategy argument provided.');
|
||||
}
|
||||
|
||||
// Handle duplicate filename
|
||||
if (file_exists($attachment_path)) {
|
||||
switch ($filenameStrategy) {
|
||||
case self::ATTACHMENT_DUPLICATE_THROW:
|
||||
throw new Exception('Could not create file for attachment: duplicate filename.');
|
||||
case self::ATTACHMENT_DUPLICATE_SUFFIX:
|
||||
$attachment_path = tempnam($attach_dir, $attachment->getFilename());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @var resource $fp */
|
||||
if ($fp = fopen($attachment_path, 'w')) {
|
||||
while ($bytes = $attachment->read()) {
|
||||
fwrite($fp, $bytes);
|
||||
}
|
||||
fclose($fp);
|
||||
$attachments_paths[] = realpath($attachment_path);
|
||||
} else {
|
||||
throw new Exception('Could not write attachments. Your directory may be unwritable by PHP.');
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments_paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the attachment Body and save temporary file resource
|
||||
*
|
||||
* @param array $part
|
||||
*
|
||||
* @return resource Mime Body Part
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function getAttachmentStream(&$part)
|
||||
{
|
||||
/** @var resource $temp_fp */
|
||||
$temp_fp = tmpfile();
|
||||
|
||||
$headers = $this->getPart('headers', $part);
|
||||
$encodingType = array_key_exists('content-transfer-encoding', $headers) ?
|
||||
$headers['content-transfer-encoding'] : '';
|
||||
|
||||
if ($temp_fp) {
|
||||
if ($this->stream) {
|
||||
$start = $part['starting-pos-body'];
|
||||
$end = $part['ending-pos-body'];
|
||||
fseek($this->stream, $start, SEEK_SET);
|
||||
$len = $end - $start;
|
||||
$written = 0;
|
||||
while ($written < $len) {
|
||||
$write = $len;
|
||||
$part = fread($this->stream, $write);
|
||||
fwrite($temp_fp, $this->decodeContentTransfer($part, $encodingType));
|
||||
$written += $write;
|
||||
}
|
||||
} elseif ($this->data) {
|
||||
$attachment = $this->decodeContentTransfer($this->getPartBodyFromText($part), $encodingType);
|
||||
fwrite($temp_fp, $attachment, strlen($attachment));
|
||||
}
|
||||
fseek($temp_fp, 0, SEEK_SET);
|
||||
} else {
|
||||
throw new Exception(
|
||||
'Could not create temporary files for attachments. Your tmp directory may be unwritable by PHP.'
|
||||
);
|
||||
}
|
||||
|
||||
return $temp_fp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the string from Content-Transfer-Encoding
|
||||
*
|
||||
* @param string $encodedString The string in its original encoded state
|
||||
* @param string $encodingType The encoding type from the Content-Transfer-Encoding header of the part.
|
||||
*
|
||||
* @return string The decoded string
|
||||
*/
|
||||
protected function decodeContentTransfer($encodedString, $encodingType)
|
||||
{
|
||||
$encodingType = strtolower($encodingType);
|
||||
if ($encodingType == 'base64') {
|
||||
return base64_decode($encodedString);
|
||||
} elseif ($encodingType == 'quoted-printable') {
|
||||
return quoted_printable_decode($encodedString);
|
||||
} else {
|
||||
return $encodedString; //8bit, 7bit, binary
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* $input can be a string or array
|
||||
*
|
||||
* @param string|array $input
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function decodeHeader($input)
|
||||
{
|
||||
//Sometimes we have 2 label From so we take only the first
|
||||
if (is_array($input)) {
|
||||
return $this->decodeSingleHeader($input[0]);
|
||||
}
|
||||
|
||||
return $this->decodeSingleHeader($input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a single header (= string)
|
||||
*
|
||||
* @param string $input
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function decodeSingleHeader($input)
|
||||
{
|
||||
// For each encoded-word...
|
||||
while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)((\s+)=\?)?/i', $input, $matches)) {
|
||||
$encoded = $matches[1];
|
||||
$charset = $matches[2];
|
||||
$encoding = $matches[3];
|
||||
$text = $matches[4];
|
||||
$space = isset($matches[6]) ? $matches[6] : '';
|
||||
|
||||
switch (strtolower($encoding)) {
|
||||
case 'b':
|
||||
$text = $this->decodeContentTransfer($text, 'base64');
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
$text = str_replace('_', ' ', $text);
|
||||
preg_match_all('/=([a-f0-9]{2})/i', $text, $matches);
|
||||
foreach ($matches[1] as $value) {
|
||||
$text = str_replace('='.$value, chr(hexdec($value)), $text);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$text = $this->charset->decodeCharset($text, $this->charset->getCharsetAlias($charset));
|
||||
$input = str_replace($encoded . $space, $text, $input);
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the charset of the MIME part
|
||||
*
|
||||
* @param array $part
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
protected function getPartCharset($part)
|
||||
{
|
||||
if (isset($part['charset'])) {
|
||||
return $this->charset->getCharsetAlias($part['charset']);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a specified MIME part
|
||||
*
|
||||
* @param string $type
|
||||
* @param array $parts
|
||||
*
|
||||
* @return string|array
|
||||
*/
|
||||
protected function getPart($type, $parts)
|
||||
{
|
||||
return (isset($parts[$type])) ? $parts[$type] : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Body of a MIME part
|
||||
*
|
||||
* @param array $part
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getPartBody(&$part)
|
||||
{
|
||||
$body = '';
|
||||
if ($this->stream) {
|
||||
$body = $this->getPartBodyFromFile($part);
|
||||
} elseif ($this->data) {
|
||||
$body = $this->getPartBodyFromText($part);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Body from a MIME part from file
|
||||
*
|
||||
* @param array $part
|
||||
*
|
||||
* @return string Mime Body Part
|
||||
*/
|
||||
protected function getPartBodyFromFile(&$part)
|
||||
{
|
||||
$start = $part['starting-pos-body'];
|
||||
$end = $part['ending-pos-body'];
|
||||
$body = '';
|
||||
if ($end - $start > 0) {
|
||||
fseek($this->stream, $start, SEEK_SET);
|
||||
$body = fread($this->stream, $end - $start);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Body from a MIME part from text
|
||||
*
|
||||
* @param array $part
|
||||
*
|
||||
* @return string Mime Body Part
|
||||
*/
|
||||
protected function getPartBodyFromText(&$part)
|
||||
{
|
||||
$start = $part['starting-pos-body'];
|
||||
$end = $part['ending-pos-body'];
|
||||
|
||||
return substr($this->data, $start, $end - $start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the content of a MIME part
|
||||
*
|
||||
* @param array $part
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getPartComplete(&$part)
|
||||
{
|
||||
$body = '';
|
||||
if ($this->stream) {
|
||||
$body = $this->getPartFromFile($part);
|
||||
} elseif ($this->data) {
|
||||
$body = $this->getPartFromText($part);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the content from a MIME part from file
|
||||
*
|
||||
* @param array $part
|
||||
*
|
||||
* @return string Mime Content
|
||||
*/
|
||||
protected function getPartFromFile(&$part)
|
||||
{
|
||||
$start = $part['starting-pos'];
|
||||
$end = $part['ending-pos'];
|
||||
$body = '';
|
||||
if ($end - $start > 0) {
|
||||
fseek($this->stream, $start, SEEK_SET);
|
||||
$body = fread($this->stream, $end - $start);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the content from a MIME part from text
|
||||
*
|
||||
* @param array $part
|
||||
*
|
||||
* @return string Mime Content
|
||||
*/
|
||||
protected function getPartFromText(&$part)
|
||||
{
|
||||
$start = $part['starting-pos'];
|
||||
$end = $part['ending-pos'];
|
||||
|
||||
return substr($this->data, $start, $end - $start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the resource
|
||||
*
|
||||
* @return resource resource
|
||||
*/
|
||||
public function getResource()
|
||||
{
|
||||
return $this->resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the file pointer to email
|
||||
*
|
||||
* @return resource stream
|
||||
*/
|
||||
public function getStream()
|
||||
{
|
||||
return $this->stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the text of an email
|
||||
*
|
||||
* @return string data
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the parts of an email
|
||||
*
|
||||
* @return array parts
|
||||
*/
|
||||
public function getParts()
|
||||
{
|
||||
return $this->parts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the charset manager object
|
||||
*
|
||||
* @return CharsetManager charset
|
||||
*/
|
||||
public function getCharset()
|
||||
{
|
||||
return $this->charset;
|
||||
}
|
||||
}
|
@@ -6,8 +6,6 @@ if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/inc/vars.local.inc.php')) {
|
||||
}
|
||||
$autodiscover_config = array_merge($default_autodiscover_config, $autodiscover_config);
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/sessions.inc.php';
|
||||
|
||||
header_remove("X-Powered-By");
|
||||
|
||||
// Yubi OTP API
|
||||
@@ -49,14 +47,26 @@ try {
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
?>
|
||||
<center style='font-family: "Lucida Sans Unicode", "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;'>Connection failed, database may be in warm-up state, please try again later.<br /><br />The following error was reported:<br/> <?=$e->getMessage();?></center>
|
||||
<center style='font-family: "Lucida Sans Unicode", "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;'>Connection to database failed.<br /><br />The following error was reported:<br/> <?=$e->getMessage();?></center>
|
||||
<?php
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/sessions.inc.php';
|
||||
|
||||
// Set language
|
||||
if (!isset($_SESSION['mailcow_locale'])) {
|
||||
$_SESSION['mailcow_locale'] = strtolower(trim($DEFAULT_LANG));
|
||||
if ($DETECT_LANGUAGE && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
|
||||
$header_lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
|
||||
foreach ($AVAILABLE_LANGUAGES as $available_lang) {
|
||||
if ($header_lang == $available_lang) {
|
||||
$_SESSION['mailcow_locale'] = strtolower(trim($header_lang));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$_SESSION['mailcow_locale'] = strtolower(trim($DEFAULT_LANG));
|
||||
}
|
||||
}
|
||||
if (isset($_GET['lang']) && in_array($_GET['lang'], $AVAILABLE_LANGUAGES)) {
|
||||
$_SESSION['mailcow_locale'] = $_GET['lang'];
|
||||
@@ -67,7 +77,9 @@ 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.mailbox.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.domain_admin.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.dkim.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fwdhost.inc.php';
|
||||
@@ -80,3 +92,4 @@ init_db_schema();
|
||||
if (isset($_SESSION['mailcow_cc_role'])) {
|
||||
set_acl();
|
||||
}
|
||||
$UI_TEXTS = customize('get', 'ui_texts');
|
||||
|
@@ -26,11 +26,29 @@ if (!isset($_SESSION['SESS_REMOTE_UA'])) {
|
||||
$_SESSION['SESS_REMOTE_UA'] = $_SERVER['HTTP_USER_AGENT'];
|
||||
}
|
||||
|
||||
// API
|
||||
if (!empty($_SERVER['HTTP_X_API_KEY'])) {
|
||||
$stmt = $pdo->prepare("SELECT `username`, `allow_from` FROM `api` WHERE `api_key` = :api_key AND `active` = '1';");
|
||||
$stmt->execute(array(
|
||||
':api_key' => preg_replace('/[^A-Z0-9-]/', '', $_SERVER['HTTP_X_API_KEY'])
|
||||
));
|
||||
$api_return = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!empty($api_return['username'])) {
|
||||
if (in_array($_SERVER['REMOTE_ADDR'], explode(',', $api_return['allow_from']))) {
|
||||
$_SESSION['mailcow_cc_username'] = $api_return['username'];
|
||||
$_SESSION['mailcow_cc_role'] = 'admin';
|
||||
$_SESSION['mailcow_cc_api'] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Update session cookie
|
||||
// setcookie(session_name() ,session_id(), time() + $SESSION_LIFETIME);
|
||||
|
||||
// Check session
|
||||
function session_check() {
|
||||
if ($_SESSION['mailcow_cc_api'] === true) {
|
||||
return true;
|
||||
}
|
||||
if (!isset($_SESSION['SESS_REMOTE_UA'])) {
|
||||
return false;
|
||||
}
|
||||
|
@@ -64,6 +64,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
||||
}
|
||||
}
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admin") {
|
||||
// TODO: Move file upload to API?
|
||||
if (isset($_POST["submit_main_logo"])) {
|
||||
if ($_FILES['main_logo']['error'] == 0) {
|
||||
customize('add', 'main_logo', $_FILES);
|
||||
@@ -72,5 +73,16 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admi
|
||||
if (isset($_POST["reset_main_logo"])) {
|
||||
customize('delete', 'main_logo');
|
||||
}
|
||||
// API cannot be controlled by API
|
||||
if (isset($_POST["admin_api"])) {
|
||||
admin_api('edit', $_POST);
|
||||
}
|
||||
if (isset($_POST["admin_api_regen_key"])) {
|
||||
admin_api('regen_key', $_POST);
|
||||
}
|
||||
// Not available via API
|
||||
if (isset($_POST["rspamd_ui"])) {
|
||||
rspamd_ui('edit', $_POST);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@@ -68,8 +68,12 @@ $autodiscover_config = array(
|
||||
);
|
||||
unset($https_port);
|
||||
|
||||
// If false, we will use DEFAULT_LANG
|
||||
// Uses HTTP_ACCEPT_LANGUAGE header
|
||||
$DETECT_LANGUAGE = true;
|
||||
|
||||
// Change default language, "de", "en", "es", "nl", "pt", "ru"
|
||||
$DEFAULT_LANG = 'en';
|
||||
$DEFAULT_LANG = 'de';
|
||||
|
||||
// Available languages
|
||||
$AVAILABLE_LANGUAGES = array('de', 'en', 'es', 'fr', 'nl', 'pl', 'pt', 'ru', 'it');
|
||||
@@ -92,13 +96,7 @@ $MAILCOW_APPS = array(
|
||||
array(
|
||||
'name' => 'SOGo',
|
||||
'link' => '/SOGo/',
|
||||
'description' => 'SOGo is a web-based client for email, address book and calendar.'
|
||||
),
|
||||
// array(
|
||||
// 'name' => 'Roundcube',
|
||||
// 'link' => '/rc/',
|
||||
// 'description' => 'Roundcube is a web-based email client.',
|
||||
// ),
|
||||
)
|
||||
);
|
||||
|
||||
// Rows until pagination begins
|
||||
@@ -118,3 +116,7 @@ $OTP_LABEL = "mailcow UI";
|
||||
|
||||
// Default "to" address in relay test tool
|
||||
$RELAY_TO = "null@hosted.mailcow.de";
|
||||
|
||||
// Quarantaine data age in days to keep
|
||||
$QUARANTAINE_AGE = 10;
|
||||
|
||||
|
Reference in New Issue
Block a user