diff --git a/customer_email.php b/customer_email.php index 0ea4daa8..9ce29598 100644 --- a/customer_email.php +++ b/customer_email.php @@ -26,9 +26,10 @@ const AREA = 'customer'; require __DIR__ . '/lib/init.php'; -use Froxlor\Api\Commands\EmailAccounts as EmailAccounts; -use Froxlor\Api\Commands\EmailForwarders as EmailForwarders; -use Froxlor\Api\Commands\Emails as Emails; +use Froxlor\Api\Commands\EmailAccounts; +use Froxlor\Api\Commands\EmailForwarders; +use Froxlor\Api\Commands\Emails; +use Froxlor\Api\Commands\EmailDomains; use Froxlor\Database\Database; use Froxlor\FroxlorLogger; use Froxlor\PhpHelper; @@ -50,13 +51,49 @@ if (Settings::IsInList('panel.customer_hide_options', 'email') || $userinfo['ema $id = (int)Request::any('id'); if ($page == 'overview' || $page == 'emails') { + $result_stmt = Database::prepare(" + SELECT COUNT(DISTINCT `domainid`) as maildomains FROM `" . TABLE_MAIL_VIRTUAL . "` WHERE `customerid`= :cid + "); + $domain_count = Database::pexecute_first($result_stmt, [ + "cid" => $userinfo['customerid'] + ]); + if ($domain_count['maildomains'] && $domain_count['maildomains'] > 1) { + try { + $emaildomain_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.emails_overview.php'; + $collection = (new Collection(EmailDomains::class, $userinfo)) + ->withPagination($emaildomain_list_data['emaildomain_list']['columns'], $emaildomain_list_data['emaildomain_list']['default_sorting']); + } catch (Exception $e) { + Response::dynamicError($e->getMessage()); + } + + UI::view('user/table.html.twig', [ + 'listing' => Listing::format($collection, $emaildomain_list_data, 'emaildomain_list'), + 'actions_links' => CurrentUser::canAddResource('emails') ? [ + [ + 'href' => $linker->getLink(['section' => 'email', 'page' => $page, 'action' => 'add']), + 'label' => lng('emails.emails_add') + ] + ] : null, + ]); + } else { + // only emails for one domain -> show email address listing directly + $page = 'email_domain'; + } +} +if ($page == 'email_domain') { + $email_domainid = Request::any('domainid', 0); if ($action == '') { $log->logAction(FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed customer_email::emails"); + $sql_search = []; + if ($email_domainid > 0) { + $sql_search = ['sql_search' => ['m.domainid' => ['op' => '=', 'value' => $email_domainid]]]; + } try { $email_list_data = include_once dirname(__FILE__) . '/lib/tablelisting/customer/tablelisting.emails.php'; - $collection = (new Collection(Emails::class, $userinfo)) - ->withPagination($email_list_data['email_list']['columns'], $email_list_data['email_list']['default_sorting']); + $collection = (new Collection(Emails::class, $userinfo, $sql_search)) + ->withPagination($email_list_data['email_list']['columns'], + $email_list_data['email_list']['default_sorting']); } catch (Exception $e) { Response::dynamicError($e->getMessage()); } @@ -71,15 +108,21 @@ if ($page == 'overview' || $page == 'emails') { ]); $emaildomains_count = $result2['emaildomains']; - $actions_links = false; - if (CurrentUser::canAddResource('emails')) { - $actions_links = [ - [ - 'href' => $linker->getLink(['section' => 'email', 'page' => $page, 'action' => 'add']), - 'label' => lng('emails.emails_add') - ] - ]; - } + $actions_links = [ + [ + 'class' => 'btn-outline-primary', + 'href' => $linker->getLink([ + 'section' => 'email', + 'page' => 'emails', + ]), + 'label' => 'back to domain overview', + 'icon' => 'fa-solid fa-reply' + ], + CurrentUser::canAddResource('emails') ? [ + 'href' => $linker->getLink(['section' => 'email', 'page' => 'email_domain', 'action' => 'add']), + 'label' => lng('emails.emails_add') + ] : null + ]; UI::view('user/table.html.twig', [ 'listing' => Listing::format($collection, $email_list_data, 'email_list'), @@ -249,6 +292,7 @@ if ($page == 'overview' || $page == 'emails') { ]); } } elseif ($page == 'accounts') { + $email_domainid = Request::any('domainid', 0); if ($action == 'add' && $id != 0) { if ($userinfo['email_accounts'] == '-1' || ($userinfo['email_accounts_used'] < $userinfo['email_accounts'])) { try { @@ -267,7 +311,8 @@ if ($page == 'overview' || $page == 'emails') { Response::dynamicError($e->getMessage()); } Response::redirectTo($filename, [ - 'page' => 'emails', + 'page' => 'email_domain', + 'domainid' => $email_domainid, 'action' => 'edit', 'id' => $id ]); @@ -292,7 +337,8 @@ if ($page == 'overview' || $page == 'emails') { 'class' => 'btn-secondary', 'href' => $linker->getLink([ 'section' => 'email', - 'page' => 'emails', + 'page' => 'email_domain', + 'domainid' => $email_domainid, 'action' => 'edit', 'id' => $id ]), @@ -301,7 +347,7 @@ if ($page == 'overview' || $page == 'emails') { ], [ 'class' => 'btn-secondary', - 'href' => $linker->getLink(['section' => 'email', 'page' => 'emails']), + 'href' => $linker->getLink(['section' => 'email', 'page' => 'email_domain', 'domainid' => $email_domainid]), 'label' => lng('menue.email.emails'), 'icon' => 'fa-solid fa-envelope' ] @@ -332,7 +378,8 @@ if ($page == 'overview' || $page == 'emails') { Response::dynamicError($e->getMessage()); } Response::redirectTo($filename, [ - 'page' => 'emails', + 'page' => 'email_domain', + 'domainid' => $email_domainid, 'action' => 'edit', 'id' => $id ]); @@ -350,7 +397,8 @@ if ($page == 'overview' || $page == 'emails') { 'class' => 'btn-secondary', 'href' => $linker->getLink([ 'section' => 'email', - 'page' => 'emails', + 'page' => 'email_domain', + 'domainid' => $email_domainid, 'action' => 'edit', 'id' => $id ]), @@ -359,7 +407,7 @@ if ($page == 'overview' || $page == 'emails') { ], [ 'class' => 'btn-secondary', - 'href' => $linker->getLink(['section' => 'email', 'page' => 'emails']), + 'href' => $linker->getLink(['section' => 'email', 'page' => 'email_domain', 'domainid' => $email_domainid]), 'label' => lng('menue.email.emails'), 'icon' => 'fa-solid fa-envelope' ] @@ -385,7 +433,8 @@ if ($page == 'overview' || $page == 'emails') { Response::dynamicError($e->getMessage()); } Response::redirectTo($filename, [ - 'page' => 'emails', + 'page' => 'email_domain', + 'domainid' => $email_domainid, 'action' => 'edit', 'id' => $id ]); @@ -403,7 +452,8 @@ if ($page == 'overview' || $page == 'emails') { 'class' => 'btn-secondary', 'href' => $linker->getLink([ 'section' => 'email', - 'page' => 'emails', + 'page' => 'email_domain', + 'domainid' => $email_domainid, 'action' => 'edit', 'id' => $id ]), @@ -412,7 +462,7 @@ if ($page == 'overview' || $page == 'emails') { ], [ 'class' => 'btn-secondary', - 'href' => $linker->getLink(['section' => 'email', 'page' => 'emails']), + 'href' => $linker->getLink(['section' => 'email', 'page' => 'email_domain', 'domainid' => $email_domainid]), 'label' => lng('menue.email.emails'), 'icon' => 'fa-solid fa-envelope' ] @@ -438,7 +488,8 @@ if ($page == 'overview' || $page == 'emails') { Response::dynamicError($e->getMessage()); } Response::redirectTo($filename, [ - 'page' => 'emails', + 'page' => 'email_domain', + 'domainid' => $email_domainid, 'action' => 'edit', 'id' => $id ]); @@ -446,12 +497,14 @@ if ($page == 'overview' || $page == 'emails') { HTML::askYesNoWithCheckbox('email_reallydelete_account', 'admin_customer_alsoremovemail', $filename, [ 'id' => $id, 'page' => $page, + 'domainid' => $email_domainid, 'action' => $action ], $idna_convert->decode($result['email_full'])); } } } } elseif ($page == 'forwarders') { + $email_domainid = Request::any('domainid', 0); if ($action == 'add' && $id != 0) { if ($userinfo['email_forwarders_used'] < $userinfo['email_forwarders'] || $userinfo['email_forwarders'] == '-1') { try { @@ -471,7 +524,8 @@ if ($page == 'overview' || $page == 'emails') { Response::dynamicError($e->getMessage()); } Response::redirectTo($filename, [ - 'page' => 'emails', + 'page' => 'email_domain', + 'domainid' => $email_domainid, 'action' => 'edit', 'id' => $id ]); @@ -489,7 +543,8 @@ if ($page == 'overview' || $page == 'emails') { 'class' => 'btn-secondary', 'href' => $linker->getLink([ 'section' => 'email', - 'page' => 'emails', + 'page' => 'email_domain', + 'domainid' => $email_domainid, 'action' => 'edit', 'id' => $id ]), @@ -498,7 +553,7 @@ if ($page == 'overview' || $page == 'emails') { ], [ 'class' => 'btn-secondary', - 'href' => $linker->getLink(['section' => 'email', 'page' => 'emails']), + 'href' => $linker->getLink(['section' => 'email', 'page' => 'email_domain', 'domainid' => $email_domainid]), 'label' => lng('menue.email.emails'), 'icon' => 'fa-solid fa-envelope' ] @@ -540,7 +595,8 @@ if ($page == 'overview' || $page == 'emails') { Response::dynamicError($e->getMessage()); } Response::redirectTo($filename, [ - 'page' => 'emails', + 'page' => 'email_domain', + 'domainid' => $email_domainid, 'action' => 'edit', 'id' => $id ]); @@ -549,6 +605,7 @@ if ($page == 'overview' || $page == 'emails') { 'id' => $id, 'forwarderid' => $forwarderid, 'page' => $page, + 'domainid' => $email_domainid, 'action' => $action ], $idna_convert->decode($result['email_full']) . ' -> ' . $idna_convert->decode($forwarder)); } diff --git a/lib/Froxlor/Ajax/GlobalSearch.php b/lib/Froxlor/Ajax/GlobalSearch.php index 43bcc932..d1517364 100644 --- a/lib/Froxlor/Ajax/GlobalSearch.php +++ b/lib/Froxlor/Ajax/GlobalSearch.php @@ -28,6 +28,7 @@ namespace Froxlor\Ajax; use Froxlor\Api\Commands\Admins; use Froxlor\Api\Commands\Customers; use Froxlor\Api\Commands\Domains; +use Froxlor\Api\Commands\EmailDomains; use Froxlor\Api\Commands\Emails; use Froxlor\Api\Commands\FpmDaemons; use Froxlor\Api\Commands\Ftps; @@ -267,7 +268,20 @@ class GlobalSearch 'result_format' => [ 'title' => ['self', 'getFieldFromResult'], 'title_args' => 'email', - 'href' => 'customer_email.php?page=emails&searchfield=m.email&searchtext=' + 'href' => 'customer_email.php?page=email_domain&domainid={domainid}&searchfield=m.email&searchtext=' + ] + ], + // email-domains + 'email_domains' => [ + 'class' => EmailDomains::class, + 'searchfields' => [ + 'd.domain', + ], + 'result_key' => 'domain', + 'result_format' => [ + 'title' => ['self', 'getFieldFromResult'], + 'title_args' => 'domain', + 'href' => 'customer_email.php?page=emails&searchfield=d.domain&searchtext=' ] ], // databases @@ -326,6 +340,14 @@ class GlobalSearch if (!isset($result[$entity])) { $result[$entity] = []; } + // replacer from result in href + $href_replacer = []; + if (preg_match_all('/\{([a-z]+)\}/', $edata['result_format']['href'], $href_replacer) !== false) { + foreach ($href_replacer[1] as $href_field) { + $href_field_value = self::getFieldFromResult($cresult, $href_field); + $edata['result_format']['href'] = str_replace('{'.$href_field.'}', $href_field_value, $edata['result_format']['href']); + } + } $result[$entity][] = [ 'title' => call_user_func($edata['result_format']['title'], $cresult, ($edata['result_format']['title_args'] ?? null)), 'href' => $edata['result_format']['href'] . $cresult[$edata['result_key']] @@ -335,7 +357,7 @@ class GlobalSearch } } // foreach entity - } // foreach splitted search-term + } // foreach split search-term } return $result; } diff --git a/lib/Froxlor/Api/Commands/EmailDomains.php b/lib/Froxlor/Api/Commands/EmailDomains.php new file mode 100644 index 00000000..89fcffd6 --- /dev/null +++ b/lib/Froxlor/Api/Commands/EmailDomains.php @@ -0,0 +1,182 @@ + + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + +namespace Froxlor\Api\Commands; + +use Exception; +use Froxlor\Api\ApiCommand; +use Froxlor\Api\ResourceEntity; +use Froxlor\Database\Database; +use Froxlor\FroxlorLogger; +use Froxlor\Idna\IdnaWrapper; +use Froxlor\Settings; +use Froxlor\UI\Response; +use Froxlor\Validate\Validate; +use PDO; + +/** + * @since 2.0 + */ +class EmailDomains extends ApiCommand implements ResourceEntity +{ + /** + * list all domains with email addresses connected to it. + * If called from an admin, list all domains with email addresses + * connected to it from all customers you are allowed to view, or + * specify id or loginname for one specific customer + * + * @param int $customerid + * optional, admin-only, select email addresses of a specific customer by id + * @param string $loginname + * optional, admin-only, select email addresses of a specific customer by loginname + * @param array $sql_search + * optional array with index = fieldname, and value = array with 'op' => operator (one of <, > or =), + * LIKE is used if left empty and 'value' => searchvalue + * @param int $sql_limit + * optional specify number of results to be returned + * @param int $sql_offset + * optional specify offset for resultset + * @param array $sql_orderby + * optional array with index = fieldname and value = ASC|DESC to order the resultset by one or more + * fields + * + * @access admin, customer + * @return string json-encoded array count|list + * @throws Exception + */ + public function listing() + { + $customer_ids = $this->getAllowedCustomerIds('email'); + $result = []; + $query_fields = []; + $result_stmt = Database::prepare(" + SELECT DISTINCT d.domain, e.domainid, + COUNT(e.email) as addresses, + IFNULL(SUM(CASE WHEN e.popaccountid > 0 THEN 1 ELSE 0 END), 0) as accounts, + IFNULL(SUM( + CASE + WHEN LENGTH(REPLACE(e.destination, CONCAT(e.email_full, ' '), '')) - LENGTH(REPLACE(REPLACE(e.destination, CONCAT(e.email_full, ' '), ''), ' ', '')) > 0 + THEN LENGTH(REPLACE(e.destination, CONCAT(e.email_full, ' '), '')) - LENGTH(REPLACE(REPLACE(e.destination, CONCAT(e.email_full, ' '), ''), ' ', '')) + WHEN e.destination <> e.email_full THEN 1 + ELSE 0 + END + ), 0) as forwarder + FROM `" . TABLE_MAIL_VIRTUAL . "` e + LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON d.id = e.domainid + WHERE e.customerid IN (" . implode(", ", $customer_ids) . ") AND d.domain IS NOT NULL " . + $this->getSearchWhere($query_fields, true) . " GROUP BY e.domainid " . $this->getOrderBy() . $this->getLimit()); + Database::pexecute($result_stmt, $query_fields, true, true); + while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) { + $result[] = $row; + } + $this->logger()->logAction($this->isAdmin() ? FroxlorLogger::ADM_ACTION : FroxlorLogger::USR_ACTION, LOG_NOTICE, "[API] list email-domains"); + return $this->response([ + 'count' => count($result), + 'list' => $result + ]); + } + + /** + * returns the total number of accessible domains with email addresses connected to + * + * @param int $customerid + * optional, admin-only, select email addresses of a specific customer by id + * @param string $loginname + * optional, admin-only, select email addresses of a specific customer by loginname + * + * @access admin, customer + * @return string json-encoded response message + * @throws Exception + */ + public function listingCount() + { + $customer_ids = $this->getAllowedCustomerIds('email'); + $result_stmt = Database::prepare(" + SELECT COUNT(DISTINCT d.domain) as num_emaildomains + FROM `" . TABLE_MAIL_VIRTUAL . "` e + LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON d.id = e.domainid + WHERE e.customerid IN (" . implode(", ", $customer_ids) . ") AND d.domain IS NOT NULL + "); + $result = Database::pexecute_first($result_stmt, null, true, true); + if ($result) { + return $this->response($result['num_emaildomains']); + } + return $this->response(0); + } + + /** + * @access admin, customer + * @return string json-encoded array + * @throws Exception + */ + public function get() + { + if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { + throw new Exception("You cannot access this resource", 405); + } + throw new Exception('You cannot directly access this resource.', 303); + } + + /** + * @access admin, customer + * @return string json-encoded array + * @throws Exception + */ + public function add() + { + if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { + throw new Exception("You cannot access this resource", 405); + } + throw new Exception('You cannot directly add this resource.', 303); + } + + /** + * toggle catchall flag of given email address either by id or email-address + * @access admin, customer + * @return string json-encoded array + * @throws Exception + */ + public function update() + { + if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { + throw new Exception("You cannot access this resource", 405); + } + throw new Exception('You cannot directly update this resource.', 303); + } + + /** + * @access admin, customer + * @return string json-encoded array + * @throws Exception + */ + public function delete() + { + if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) { + throw new Exception("You cannot access this resource", 405); + } + throw new Exception('You cannot directly delete this resource.', 303); + } + +} diff --git a/lib/formfields/customer/email/formfield.emails_add.php b/lib/formfields/customer/email/formfield.emails_add.php index e1bb927e..7d676c47 100644 --- a/lib/formfields/customer/email/formfield.emails_add.php +++ b/lib/formfields/customer/email/formfield.emails_add.php @@ -27,7 +27,7 @@ return [ 'emails_add' => [ 'title' => lng('emails.emails_add'), 'image' => 'fa-solid fa-plus', - 'self_overview' => ['section' => 'email', 'page' => 'emails'], + 'self_overview' => ['section' => 'email', 'page' => 'email_domain', 'domainid' => $email_domainid ?: 0], 'sections' => [ 'section_a' => [ 'title' => lng('emails.emails_add'), diff --git a/lib/formfields/customer/email/formfield.emails_edit.php b/lib/formfields/customer/email/formfield.emails_edit.php index 52af6402..c6e1d9c6 100644 --- a/lib/formfields/customer/email/formfield.emails_edit.php +++ b/lib/formfields/customer/email/formfield.emails_edit.php @@ -29,7 +29,7 @@ return [ 'emails_edit' => [ 'title' => lng('emails.emails_edit'), 'image' => 'fa-solid fa-pen', - 'self_overview' => ['section' => 'email', 'page' => 'emails'], + 'self_overview' => ['section' => 'email', 'page' => 'email_domain', 'domainid' => $email_domainid ?: 1], 'sections' => [ 'section_a' => [ 'title' => lng('emails.emails_edit'), @@ -48,13 +48,13 @@ return [ 'next_to' => [ 'edit_link' => [ 'type' => 'link', - 'href' => $filename . '?page=accounts&action=changepw&id=' . $result['id'], + 'href' => $filename . '?page=accounts&domainid=' . $result['domainid'] . '&action=changepw&id=' . $result['id'], 'label' => lng('menue.main.changepassword'), 'classes' => 'btn btn-sm btn-secondary' ], 'del_link' => [ 'type' => 'link', - 'href' => $filename . '?page=accounts&action=delete&id=' . $result['id'], + 'href' => $filename . '?page=accounts&domainid=' . $result['domainid'] . '&action=delete&id=' . $result['id'], 'label' => lng('emails.account_delete'), 'classes' => 'btn btn-sm btn-danger' ] @@ -68,7 +68,7 @@ return [ 'next_to' => [ 'add_link' => [ 'type' => 'link', - 'href' => $filename . '?page=accounts&action=add&id=' . $result['id'], + 'href' => $filename . '?page=accounts&domainid=' . $result['domainid'] . '&action=add&id=' . $result['id'], 'label' => lng('emails.account_add'), 'classes' => 'btn btn-sm btn-primary' ] @@ -83,7 +83,7 @@ return [ 'add_link' => [ 'visible' => ((int)$result['popaccountid'] != 0 && Settings::Get('system.mail_quota_enabled')), 'type' => 'link', - 'href' => $filename . '?page=accounts&action=changequota&id=' . $result['id'], + 'href' => $filename . '?page=accounts&domainid=' . $result['domainid'] . '&action=changequota&id=' . $result['id'], 'label' => lng('emails.quota_edit'), 'classes' => 'btn btn-sm btn-secondary' ] @@ -96,7 +96,7 @@ return [ 'next_to' => [ 'add_link' => [ 'type' => 'link', - 'href' => $filename . '?page=' . $page . '&action=togglecatchall&id=' . $result['id'], + 'href' => $filename . '?page=' . $page . '&domainid=' . $result['domainid'] . '&action=togglecatchall&id=' . $result['id'], 'label' => ' ' . lng('panel.toggle'), 'classes' => 'btn btn-sm btn-secondary' ] @@ -109,7 +109,7 @@ return [ 'next_to' => [ 'add_link' => [ 'type' => 'link', - 'href' => $filename . '?page=forwarders&action=add&id=' . $result['id'], + 'href' => $filename . '?page=forwarders&domainid=' . $result['domainid'] . '&action=add&id=' . $result['id'], 'label' => lng('emails.forwarder_add'), 'classes' => 'btn btn-sm btn-primary' ] diff --git a/lib/tablelisting/customer/tablelisting.emails.php b/lib/tablelisting/customer/tablelisting.emails.php index 59f45818..0fd340c5 100644 --- a/lib/tablelisting/customer/tablelisting.emails.php +++ b/lib/tablelisting/customer/tablelisting.emails.php @@ -32,7 +32,7 @@ return [ 'email_list' => [ 'title' => lng('menue.email.emails'), 'icon' => 'fa-solid fa-envelope', - 'self_overview' => ['section' => 'email', 'page' => 'emails'], + 'self_overview' => ['section' => 'email', 'page' => 'email_domain'], 'default_sorting' => ['m.email_full' => 'asc'], 'columns' => [ 'm.email_full' => [ @@ -74,7 +74,8 @@ return [ 'title' => lng('panel.edit'), 'href' => [ 'section' => 'email', - 'page' => 'emails', + 'page' => 'email_domain', + 'domainid' => ':domainid', 'action' => 'edit', 'id' => ':id' ], @@ -85,7 +86,8 @@ return [ 'class' => 'btn-danger', 'href' => [ 'section' => 'email', - 'page' => 'emails', + 'page' => 'email_domain', + 'domainid' => ':domainid', 'action' => 'delete', 'id' => ':id' ], diff --git a/lib/tablelisting/customer/tablelisting.emails_overview.php b/lib/tablelisting/customer/tablelisting.emails_overview.php new file mode 100644 index 00000000..cd492165 --- /dev/null +++ b/lib/tablelisting/customer/tablelisting.emails_overview.php @@ -0,0 +1,76 @@ + + * @license https://files.froxlor.org/misc/COPYING.txt GPLv2 + */ + +use Froxlor\UI\Callbacks\Impersonate; +use Froxlor\UI\Callbacks\Style; +use Froxlor\UI\Callbacks\Text; +use Froxlor\UI\Listing; + +return [ + 'emaildomain_list' => [ + 'title' => lng('menue.email.emailsoverview'), + 'icon' => 'fa-solid fa-envelope', + 'self_overview' => ['section' => 'email', 'page' => 'overview'], + 'default_sorting' => ['d.domain' => 'asc'], + 'columns' => [ + 'd.domain' => [ + 'label' => 'Domain', + 'field' => 'domain', + ], + 'addresses' => [ + 'label' => '# Adresses', + 'field' => 'addresses', + 'searchable' => false, + ], + 'accounts' => [ + 'label' => '# Accounts', + 'field' => 'accounts', + 'searchable' => false, + ], + 'forwarder' => [ + 'label' => '# Forwarders', + 'field' => 'forwarder', + 'searchable' => false, + ], + ], + 'visible_columns' => Listing::getVisibleColumnsForListing('emaildomain_list', [ + 'd.domain', + 'addresses', + 'accounts', + 'forwarder', + ]), + 'actions' => [ + 'show' => [ + 'icon' => 'fa-solid fa-eye', + 'title' => lng('apikeys.clicktoview'), + 'href' => [ + 'section' => 'email', + 'page' => 'email_domain', + 'domainid' => ':domainid' + ], + ], + ], + ] +]; diff --git a/lng/de.lng.php b/lng/de.lng.php index 19389bae..fcdba178 100644 --- a/lng/de.lng.php +++ b/lng/de.lng.php @@ -1073,6 +1073,7 @@ Vielen Dank, Ihr Administrator', 'email' => 'E-Mail', 'emails' => 'Adressen', 'webmail' => 'Webmail', + 'emailsoverview' => 'E-Mail Domain Übersicht', ], 'mysql' => [ 'mysql' => 'MySQL', diff --git a/lng/en.lng.php b/lng/en.lng.php index 400da4b5..fa69091a 100644 --- a/lng/en.lng.php +++ b/lng/en.lng.php @@ -1142,6 +1142,7 @@ Yours sincerely, your administrator', 'email' => 'Email', 'emails' => 'Addresses', 'webmail' => 'Webmail', + 'emailsoverview' => 'Email domains overview', ], 'mysql' => [ 'mysql' => 'MySQL',