From 5bf927cde6b6c9743a9ef1fe2ff669fac25204e4 Mon Sep 17 00:00:00 2001 From: "Misha M.-Kupriyanov" Date: Thu, 23 Oct 2025 17:31:19 +0200 Subject: [PATCH 1/5] IONOS(ionos-mail): add domain preference for IONOS mail configuration Signed-off-by: Misha M.-Kupriyanov --- lib/Controller/PageController.php | 8 +++- lib/Service/IONOS/IonosConfigService.php | 48 +++++++++++++++++++ src/components/ionos/NewEmailAddressTab.vue | 6 ++- src/init.js | 4 ++ tests/Unit/Controller/PageControllerTest.php | 10 +++- .../Service/IONOS/IonosConfigServiceTest.php | 45 +++++++++++++++++ 6 files changed, 118 insertions(+), 3 deletions(-) diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index df82aafb34..2ea0f62352 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -21,6 +21,7 @@ use OCA\Mail\Service\AliasesService; use OCA\Mail\Service\Classification\ClassificationSettingsService; use OCA\Mail\Service\InternalAddressService; +use OCA\Mail\Service\IONOS\IonosConfigService; use OCA\Mail\Service\OutboxService; use OCA\Mail\Service\QuickActionsService; use OCA\Mail\Service\SmimeService; @@ -74,7 +75,8 @@ class PageController extends Controller { private InternalAddressService $internalAddressService; private QuickActionsService $quickActionsService; - public function __construct(string $appName, + public function __construct( + string $appName, IRequest $request, IURLGenerator $urlGenerator, IConfig $config, @@ -97,6 +99,7 @@ public function __construct(string $appName, InternalAddressService $internalAddressService, IAvailabilityCoordinator $availabilityCoordinator, QuickActionsService $quickActionsService, + private IonosConfigService $ionosConfigService, ) { parent::__construct($appName, $request); @@ -208,9 +211,12 @@ public function index(): TemplateResponse { $user = $this->userSession->getUser(); $response = new TemplateResponse($this->appName, 'index'); + + $this->initialStateService->provideInitialState('preferences', [ 'attachment-size-limit' => $this->config->getSystemValue('app.mail.attachment-size-limit', 0), 'ionos-mailconfig-enabled' => $this->config->getAppValue('mail', 'ionos-mailconfig-enabled', 'no') === 'yes', + 'ionos-mailconfig-domain' => $this->ionosConfigService->getMailDomain(), 'app-version' => $this->config->getAppValue('mail', 'installed_version'), 'external-avatars' => $this->preferences->getPreference($this->currentUserId, 'external-avatars', 'true'), 'layout-mode' => $this->preferences->getPreference($this->currentUserId, 'layout-mode', 'vertical-split'), diff --git a/lib/Service/IONOS/IonosConfigService.php b/lib/Service/IONOS/IonosConfigService.php index a429972324..6606c510bb 100644 --- a/lib/Service/IONOS/IonosConfigService.php +++ b/lib/Service/IONOS/IonosConfigService.php @@ -13,7 +13,10 @@ use OCP\Exceptions\AppConfigException; use OCP\IAppConfig; use OCP\IConfig; +use Pdp\Domain; +use Pdp\Rules; use Psr\Log\LoggerInterface; +use Throwable; /** * Service for managing IONOS API configuration @@ -125,4 +128,49 @@ public function getApiConfig(): array { 'basicAuthPass' => $this->getBasicAuthPassword(), ]; } + + /** + * Get the mail domain from customer domain + * + * Extracts the registrable domain (mail domain) from the customer domain + * configured in system settings. + */ + public function getMailDomain(): string { + $customerDomain = $this->config->getSystemValue('ncw.customerDomain', ''); + return $this->extractMailDomain($customerDomain); + } + + /** + * Extract the registrable domain (mail domain) from a customer domain. + * + * Uses the Public Suffix List via Pdp library to properly extract the + * registrable domain, handling multi-level TLDs like .co.uk correctly. + * + * Examples: + * - foo.bar.lol -> bar.lol + * - mail.test.co.uk -> test.co.uk + * - sub.domain.example.com -> example.com + * + * @param string $customerDomain The full customer domain + * @return string The extracted mail domain, or empty string if input is empty + */ + private function extractMailDomain(string $customerDomain): string { + if (empty($customerDomain)) { + return ''; + } + + try { + $publicSuffixList = Rules::fromPath(__DIR__ . '/../../../resources/public_suffix_list.dat'); + $domain = Domain::fromIDNA2008($customerDomain); + $result = $publicSuffixList->resolve($domain); + return $result->registrableDomain()->toString(); + } catch (Throwable $e) { + // Fallback to simple extraction if Pdp fails + $parts = explode('.', $customerDomain); + if (count($parts) >= 2) { + return $parts[count($parts) - 2] . '.' . $parts[count($parts) - 1]; + } + return $customerDomain; + } + } } diff --git a/src/components/ionos/NewEmailAddressTab.vue b/src/components/ionos/NewEmailAddressTab.vue index d0b99e8a85..228889b600 100644 --- a/src/components/ionos/NewEmailAddressTab.vue +++ b/src/components/ionos/NewEmailAddressTab.vue @@ -23,7 +23,7 @@ - +