rcmail = rcube::get_instance(); $this->load_config(); if ($dsn = $this->rcmail->config->get('postfixadmin_db_dsn')) { $this->postfixadmin_db = rcube_db::factory($dsn, '', false); } else { throw new \Exception('cannot connect ot postfix db'); } if ($this->rcmail->task == "settings") { $this->add_hook("settings_actions", [$this, "hookSettingsActions"]); $this->register_action('plugin.aliasmanager', [$this, "onShowSettingsPage"]); switch ($this->rcmail->action) { case 'plugin.aliasmanager-get-alias-list': $this->onGetAliasList(); break; case 'plugin.aliasmanager-add-alias': $this->onAddAlias(); break; case 'plugin.aliasmanager-toggle-alias': $this->onToggleAlias(); break; case 'plugin.aliasmanager-delete-alias': $this->onDeleteAlias(); break; } } } public function hookSettingsActions($arg): array { // add the menu item to the settings sidebar $arg['actions'][] = [ 'action' => 'plugin.aliasmanager', 'class' => 'aliasmanager', 'label' => 'plugin_aliasmanager', 'title' => 'plugin_aliasmanager', ]; return $arg; } /** * Renders and returns the settings.html view. * @return mixed */ public function settingsPageHandler() { $this->include_script('assets/scripts/app.js'); $this->include_stylesheet('assets/styles/app.css'); $this->rcmail->output->add_label("plugin_aliasmanager"); return $this->view("elastic", "aliasmanager.settings", []); } /** * Creates and outputs the settings page. */ public function onShowSettingsPage() { $this->register_handler('plugin.body', [$this, 'settingsPageHandler']); $this->rcmail->output->set_pagetitle($this->gettext('aliasmanager')); $this->rcmail->output->send('plugin'); } public function onGetAliasList() { $alias_list = []; $result = $this->postfixadmin_db->query('SELECT address as email, goto as users, active FROM alias WHERE address != goto AND goto = ? AND domain = ?', $this->rcmail->user->get_username(), $this->rcmail->config->get('alias_email_domain')); foreach ($result as $row) { $alias_list[] = [ 'email' => $row['email'], 'active' => $row['active'], ]; } $this->sendResponse(true, [ 'data' => [ 'alias_list' => $alias_list, ], ]); } public function onAddAlias() { $email = $_POST['email'] ?? null; if (empty($email)) { $this->sendResponse(false, [ 'msg' => 'Email not set', ]); return; } $email_alias_domain = $this->rcmail->config->get('alias_email_domain'); $email = $email.'-'.$this->generateRandomEmailAliasHash($this->rcmail->config->get('alias_email_hash_len', 7)).'@'.$email_alias_domain; $error = $this->postfixadmin_db->query('INSERT INTO alias (address, goto, domain, created, modified, active) VALUES (?, ?, ?, NOW(), NOW(), 1)', [$email, $this->rcmail->user->get_username(), $email_alias_domain]); if (!$error) { $this->sendResponse(false, [ 'msg' => 'failed to add alias', // $this->postfixadmin_db->is_error() ]); return; } $this->sendResponse(true, []); } public function onToggleAlias() { $state = $_POST['state'] == 'true' ? 1 : 0; $email = $_POST['email']; if (empty($email)) { $this->sendResponse(false, [ 'msg' => 'Email not set', ]); return; } $email_alias_domain = $this->rcmail->config->get('alias_email_domain'); $error = $this->postfixadmin_db->query('UPDATE alias SET active = ? WHERE address = ? AND goto = ? AND domain = ?', [$state, $email, $this->rcmail->user->get_username(), $email_alias_domain]); if (!$error) { $this->sendResponse(false, [ 'msg' => 'failed to toggle alias', // $this->postfixadmin_db->is_error() ]); return; } $this->sendResponse(true, []); } public function onDeleteAlias() { $email = $_POST['email']; if (empty($email)) { $this->sendResponse(false, [ 'msg' => 'Email not set', ]); return; } $email_alias_domain = $this->rcmail->config->get('alias_email_domain'); $error = $this->postfixadmin_db->query('DELETE FROM alias WHERE address = ? AND goto = ? AND domain = ?', [$email, $this->rcmail->user->get_username(), $email_alias_domain]); if (!$error) { $this->sendResponse(false, [ 'msg' => 'failed to toggle alias', // $this->postfixadmin_db->is_error() ]); return; } $this->sendResponse(true, []); } /** * Sends ajax response in json format. * * IMPORTANT: When sending an error with an error message, use this format: * sendResponse(true, array('success' => false, 'errorMessage' => $message, 'other data'...) * This is because the standard way of setting $success and $errorMessage won't work properly with non-English * character sets (when the error is sent using http/1.0 500) * * @param bool $success * @param array $data */ private function sendResponse($success, $data = [], $errorMessage = false) { if ($this->unitTest) { return ["success" => $success, "data" => $data, "errorMessage" => $data['errorMessage']]; } if (ob_get_contents()) { @ob_end_clean(); } if (!is_array($data)) { $data = []; } if (!isset($data['success'])) { $data['success'] = (bool)$success; } if ($success) { exit(json_encode($data)); } if (empty($errorMessage)) { $errorMessage = empty($data['errorMessage']) ? "Server error" : $data['errorMessage']; } exit(@header("HTTP/1.0 500 ".$errorMessage)); } private function view($skin, $view, $data = false) { if (empty($data) || !is_array($data)) { $data = []; } $parts = explode(".", $view); $plugin = $parts[0]; unset($parts[0]); $html = file_get_contents(__DIR__."/../$plugin/skins/$skin/templates/".implode(".", $parts).".html"); while (($i = strrpos($html, "[+")) !== false && ($j = strrpos($html, "+]")) !== false) { $html = substr_replace($html, xrc()->gettext(substr($html, $i + 2, $j - $i - 2)), $i, $j - $i + 2); } // replace our custom tags that can contain html tags foreach ($data as $key => $val) { if (is_string($val)) { $html = str_replace("[~".$key."~]", $val, $html); } else if (is_array($val)) { $html = str_replace("[~".$key."~]", @json_encode($val), $html); } } return $html; } private function generateRandomEmailAliasHash($length = 10) { $characters = '0123456789abcdefghijklmnopqrstuvwxyz'; $charactersLength = strlen($characters); $randomString = ''; for ($i = 0; $i < $length; $i++) { $randomString .= $characters[rand(0, $charactersLength - 1)]; } return $randomString; } }