diff --git a/customer_email.php b/customer_email.php
index 02517fc1..efed543a 100644
--- a/customer_email.php
+++ b/customer_email.php
@@ -205,76 +205,13 @@ if ($page == 'overview') {
} elseif ($action == 'add') {
if ($userinfo['emails_used'] < $userinfo['emails'] || $userinfo['emails'] == '-1') {
if (isset($_POST['send']) && $_POST['send'] == 'send') {
- $email_part = $_POST['email_part'];
- // domain does not need idna encoding as the value of the select-box is already Punycode
- $domain = validate($_POST['domain'], 'domain');
- $stmt = Database::prepare("SELECT `id`, `domain`, `customerid` FROM `" . TABLE_PANEL_DOMAINS . "`
- WHERE `domain`= :domain
- AND `customerid`= :customerid
- AND `isemaildomain`='1' "
- );
- $domain_check = Database::pexecute_first($stmt, array("domain" => $domain, "customerid" => $userinfo['customerid']));
-
- if (isset($_POST['iscatchall']) && $_POST['iscatchall'] == '1') {
- $iscatchall = '1';
- $email = '@' . $domain;
- } else {
- $iscatchall = '0';
- $email = $email_part . '@' . $domain;
- }
-
- $email_full = $email_part . '@' . $domain;
-
- if (!validateEmail($email_full)) {
- standard_error('emailiswrong', $email_full);
- }
-
- $stmt = Database::prepare("SELECT `id`, `email`, `email_full`, `iscatchall`, `destination`, `customerid` FROM `" . TABLE_MAIL_VIRTUAL . "`
- WHERE (`email` = :email
- OR `email_full` = :emailfull )
- AND `customerid`= :cid"
- );
- $params = array(
- "email" => $email,
- "emailfull" => $email_full,
- "cid" => $userinfo['customerid']
- );
- $email_check = Database::pexecute_first($stmt, $params);
-
- if ($email == '' || $email_full == '' || $email_part == '') {
- standard_error(array('stringisempty', 'emailadd'));
- } elseif ($domain == '') {
- standard_error('domaincantbeempty');
- } elseif ($domain_check['domain'] != $domain) {
- standard_error('maindomainnonexist', $domain);
- } elseif (strtolower($email_check['email_full']) == strtolower($email_full)) {
- standard_error('emailexistalready', $email_full);
- } elseif ($email_check['email'] == $email) {
- standard_error('youhavealreadyacatchallforthisdomain');
- } else {
- $stmt = Database::prepare("INSERT INTO `" . TABLE_MAIL_VIRTUAL . "`
- (`customerid`, `email`, `email_full`, `iscatchall`, `domainid`)
- VALUES (:cid, :email, :email_full, :iscatchall, :domainid)"
- );
- $params = array(
- "cid" => $userinfo['customerid'],
- "email" => $email,
- "email_full" => $email_full,
- "iscatchall" => $iscatchall,
- "domainid" => $domain_check['id']
- );
- Database::pexecute($stmt, $params);
-
- $address_id = Database::lastInsertId();
- $stmt = Database::prepare("UPDATE " . TABLE_PANEL_CUSTOMERS . "
- SET `emails_used` = `emails_used` + 1
- WHERE `customerid`= :cid"
- );
- Database::pexecute($stmt, array("cid" => $userinfo['customerid']));
-
- $log->logAction(USR_ACTION, LOG_INFO, "added email address '" . $email_full . "'");
- redirectTo($filename, array('page' => $page, 'action' => 'edit', 'id' => $address_id, 's' => $s));
+ try {
+ $json_result = Emails::getLocal($userinfo, $_POST)->add();
+ } catch (Exception $e) {
+ dynamic_error($e->getMessage());
}
+ $result = json_decode($json_result, true)['data'];
+ redirectTo($filename, array('page' => $page, 'action' => 'edit', 'id' => $result['id'], 's' => $s));
} else {
$result_stmt = Database::prepare("SELECT `id`, `domain`, `customerid` FROM `" . TABLE_PANEL_DOMAINS . "`
WHERE `customerid`= :cid
diff --git a/lib/classes/api/commands/class.Emails.php b/lib/classes/api/commands/class.Emails.php
new file mode 100644
index 00000000..ce45ab72
--- /dev/null
+++ b/lib/classes/api/commands/class.Emails.php
@@ -0,0 +1,230 @@
+ (2010-)
+ * @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
+ * @package API
+ * @since 0.10.0
+ *
+ */
+class Emails extends ApiCommand implements ResourceEntity
+{
+
+ /**
+ * add a new email address
+ *
+ * @access admin, customer
+ * @throws Exception
+ * @return array
+ */
+ public function add()
+ {
+ if ($this->isAdmin() == false && Settings::IsInList('panel.customer_hide_options', 'email')) {
+ throw new Exception("You cannot access this resource", 405);
+ }
+
+ if ($this->getUserDetail('emails_used') < $this->getUserDetail('emails') || $this->getUserDetail('emails') == '-1') {
+
+ // required parameters
+ $email_part = $this->getParam('email_part');
+ $domain = $this->getParam('domain');
+
+ // parameters
+ $iscatchall = $this->getParam('iscatchall', true, 0);
+
+ // validation
+ if (substr($domain, 0, 4) != 'xn--') {
+ $idna_convert = new idna_convert_wrapper();
+ $domain = $idna_convert->encode(validate($domain, 'domain', '', '', array(), true));
+ }
+
+ // check domain and whether it's an email-enabled domain
+ $domain_check = $this->apiCall('SubDomains.get', array(
+ 'domainname' => $domain
+ ));
+ if ($domain_check['isemaildomain'] == 0) {
+ standard_error('maindomainnonexist', $domain, true);
+ }
+
+ // check for catchall-flag
+ if ($iscatchall) {
+ $iscatchall = '1';
+ $email = '@' . $domain;
+ } else {
+ $iscatchall = '0';
+ $email = $email_part . '@' . $domain;
+ }
+
+ // full email value
+ $email_full = $email_part . '@' . $domain;
+
+ // validate it
+ if (!validateEmail($email_full)) {
+ standard_error('emailiswrong', $email_full, true);
+ }
+
+ // get needed customer info to reduce the email-address-counter by one
+ if ($this->isAdmin()) {
+ // get customer id
+ $customer_id = $this->getParam('customer_id');
+ $customer = $this->apiCall('Customers.get', array(
+ 'id' => $customer_id
+ ));
+ // check whether the customer has enough resources to get the ftp-user added
+ if ($customer['emails_used'] >= $customer['emails'] && $customer['emails'] != '-1') {
+ throw new Exception("Customer has no more resources available", 406);
+ }
+ } else {
+ $customer_id = $this->getUserDetail('customerid');
+ $customer = $this->getUserData();
+ }
+
+ // duplicate check
+ $stmt = Database::prepare("
+ SELECT `id`, `email`, `email_full`, `iscatchall`, `destination`, `customerid` FROM `" . TABLE_MAIL_VIRTUAL . "`
+ WHERE (`email` = :email OR `email_full` = :emailfull )
+ AND `customerid`= :cid
+ ");
+ $params = array(
+ "email" => $email,
+ "emailfull" => $email_full,
+ "cid" => $customer['customerid']
+ );
+ $email_check = Database::pexecute_first($stmt, $params, true, true);
+
+ if (strtolower($email_check['email_full']) == strtolower($email_full)) {
+ standard_error('emailexistalready', $email_full, true);
+ } elseif ($email_check['email'] == $email) {
+ standard_error('youhavealreadyacatchallforthisdomain', '', true);
+ }
+
+ $stmt = Database::prepare("
+ INSERT INTO `" . TABLE_MAIL_VIRTUAL . "` SET
+ `customerid` = :cid,
+ `email` = :email,
+ `email_full` = :email_full,
+ `iscatchall` = :iscatchall,
+ `domainid` = :domainid
+ ");
+ $params = array(
+ "cid" => $customer['customerid'],
+ "email" => $email,
+ "email_full" => $email_full,
+ "iscatchall" => $iscatchall,
+ "domainid" => $domain_check['id']
+ );
+ Database::pexecute($stmt, $params, true, true);
+ $address_id = Database::lastInsertId();
+
+ // update customer usage
+ Customers::increaseUsage($customer_id, 'emails_used');
+
+ // update admin usage
+ Admins::increaseUsage($customer['adminid'], 'emails_used');
+
+ $this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_INFO, "[API] added email address '" . $email_full . "'");
+
+ $result = $this->apiCall('Emails.get', array(
+ 'emailaddr' => $email_full
+ ));
+ return $this->response(200, "successfull", $result);
+ }
+ throw new Exception("No more resources available", 406);
+ }
+
+ /**
+ * return a email-address entry by either id or email-address
+ *
+ * @param int $id
+ * optional, the customer-id
+ * @param string $emailaddr
+ * optional, the email-address
+ *
+ * @access admin, customer
+ * @throws Exception
+ * @return array
+ */
+ public function get()
+ {
+ $id = $this->getParam('id', true, 0);
+ $ea_optional = ($id <= 0 ? false : true);
+ $emailaddr = $this->getParam('emailaddr', $ea_optional, '');
+
+ $params = array();
+ $customer_ids = $this->getAllowedCustomerIds('email');
+ $params['customerid'] = implode(", ", $customer_ids);
+ $params['idea'] = ($id <= 0 ? $emailaddr : $id);
+
+ $result_stmt = Database::prepare("SELECT v.`id`, v.`email`, v.`email_full`, v.`iscatchall`, v.`destination`, v.`customerid`, v.`popaccountid`, u.`quota`
+ FROM `" . TABLE_MAIL_VIRTUAL . "` v
+ LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON v.`popaccountid` = u.`id`
+ WHERE v.`customerid` IN (:customerid)
+ AND (v.`id`= :idea OR (v.`email` = :idea OR v.`email_full` = :idea))
+ ");
+ $result = Database::pexecute_first($result_stmt, $params, true, true);
+ if ($result) {
+ $this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] get email address '" . $result['email_full'] . "'");
+ return $this->response(200, "successfull", $result);
+ }
+ $key = ($id > 0 ? "id #" . $id : "emailaddr '" . $emailaddr . "'");
+ throw new Exception("Email address with " . $key . " could not be found", 404);
+ }
+
+ public function update()
+ {
+ }
+
+ /**
+ * list all email addresses, if called from an admin, list all email addresses of all customers you are allowed to view, or specify id or loginname for one specific customer
+ *
+ * @param int $customerid
+ * optional, admin-only, select ftp-users of a specific customer by id
+ * @param string $loginname
+ * optional, admin-only, select ftp-users of a specific customer by loginname
+ *
+ * @access admin, customer
+ * @throws Exception
+ * @return array count|list
+ */
+ public function listing()
+ {
+ $customer_ids = $this->getAllowedCustomerIds('email');
+ $result = array();
+ $params['customerid'] = implode(", ", $customer_ids);
+ $result_stmt = Database::prepare("
+ SELECT m.`id`, m.`domainid`, m.`email`, m.`email_full`, m.`iscatchall`, u.`quota`, m.`destination`, m.`popaccountid`, d.`domain`, u.`mboxsize`
+ FROM `" . TABLE_MAIL_VIRTUAL . "` m
+ LEFT JOIN `" . TABLE_PANEL_DOMAINS . "` d ON (m.`domainid` = d.`id`)
+ LEFT JOIN `" . TABLE_MAIL_USERS . "` u ON (m.`popaccountid` = u.`id`)
+ WHERE m.`customerid` IN (:customerid)
+ ");
+ Database::pexecute($result_stmt, $params, true, true);
+ while ($row = $result_stmt->fetch(PDO::FETCH_ASSOC)) {
+ $result[] = $row;
+ }
+ $this->logger()->logAction($this->isAdmin() ? ADM_ACTION : USR_ACTION, LOG_NOTICE, "[API] list email-addresses");
+ return $this->response(200, "successfull", array(
+ 'count' => count($result),
+ 'list' => $result
+ ));
+ }
+
+ /**
+ * delete an email address by either id or username
+ *
+ * @access admin, customer
+ * @throws Exception
+ * @return array
+ */
+ public function delete()
+ {
+ }
+}
diff --git a/lib/classes/api/commands/class.Ftps.php b/lib/classes/api/commands/class.Ftps.php
index 6f3223be..56ef099b 100644
--- a/lib/classes/api/commands/class.Ftps.php
+++ b/lib/classes/api/commands/class.Ftps.php
@@ -75,8 +75,10 @@ class Ftps extends ApiCommand implements ResourceEntity
if (Settings::Get('customer.ftpatdomain') == '1') {
$ftpusername = validate(trim($ftpusername), 'username', '/^[a-zA-Z0-9][a-zA-Z0-9\-_]+\$?$/', '', array(), true);
- $idna_convert = new idna_convert_wrapper();
- $ftpdomain = $idna_convert->encode(validate($ftpdomain, 'domain', '', '', array(), true));
+ if (substr($ftpdomain, 0, 4) != 'xn--') {
+ $idna_convert = new idna_convert_wrapper();
+ $ftpdomain = $idna_convert->encode(validate($ftpdomain, 'domain', '', '', array(), true));
+ }
}
$params = array();
diff --git a/phpunit.xml b/phpunit.xml
index efedaf51..f1754d3b 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -16,6 +16,7 @@
tests/SubDomains
tests/Certificates
tests/Ftps
+ tests/Emails
diff --git a/tests/Emails/EmailsTest.php b/tests/Emails/EmailsTest.php
new file mode 100644
index 00000000..5a07bc1e
--- /dev/null
+++ b/tests/Emails/EmailsTest.php
@@ -0,0 +1,44 @@
+ 'test1'
+ ))->get();
+ $customer_userdata = json_decode($json_result, true)['data'];
+
+ $data = [
+ 'email_part' => 'info',
+ 'domain' => 'test2.local'
+ ];
+ $json_result = Emails::getLocal($customer_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals("info@test2.local", $result['email_full']);
+ $this->assertEquals(0, $result['iscatchall']);
+ }
+
+ public function testAdminEmailsAdd()
+ {
+ global $admin_userdata;
+ $data = [
+ 'email_part' => 'catchall',
+ 'domain' => 'test2.local',
+ 'iscatchall' => 1,
+ 'customer_id' => 1
+ ];
+ $json_result = Emails::getLocal($admin_userdata, $data)->add();
+ $result = json_decode($json_result, true)['data'];
+ $this->assertEquals("catchall@test2.local", $result['email_full']);
+ $this->assertEquals(1, $result['iscatchall']);
+ }
+}