From 265d2c3f875f07719794a92f4a18df87c7d0595a Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Wed, 14 Jan 2026 12:34:41 +0100 Subject: [PATCH] refactor(settings): migrate mail settings to Vue Signed-off-by: Ferdinand Thiessen --- .../lib/Controller/MailSettingsController.php | 17 +- apps/settings/lib/Settings/Admin/Mail.php | 66 +++-- apps/settings/src/admin-settings-mail.ts | 10 + apps/settings/src/admin-settings-sharing.ts | 3 +- apps/settings/src/admin.js | 95 ------- .../src/views/AdminSettingsMailServer.vue | 259 ++++++++++++++++++ .../settings/admin/additional-mail.php | 148 +--------- apps/settings/templates/settings/frame.php | 1 - build/frontend-legacy/webpack.modules.cjs | 2 +- 9 files changed, 326 insertions(+), 275 deletions(-) create mode 100644 apps/settings/src/admin-settings-mail.ts delete mode 100644 apps/settings/src/admin.js create mode 100644 apps/settings/src/views/AdminSettingsMailServer.vue diff --git a/apps/settings/lib/Controller/MailSettingsController.php b/apps/settings/lib/Controller/MailSettingsController.php index 69c43ecb5aa..95e60c72496 100644 --- a/apps/settings/lib/Controller/MailSettingsController.php +++ b/apps/settings/lib/Controller/MailSettingsController.php @@ -56,7 +56,7 @@ class MailSettingsController extends Controller { string $mail_smtpmode, string $mail_smtpsecure, string $mail_smtphost, - ?string $mail_smtpauth, + ?bool $mail_smtpauth, string $mail_smtpport, string $mail_sendmailmode, ): DataResponse { @@ -91,23 +91,18 @@ class MailSettingsController extends Controller { /** * Store the credentials used for SMTP in the config - * - * @param string $mail_smtpname - * @param string $mail_smtppassword - * @return DataResponse */ #[AuthorizedAdminSetting(settings: Overview::class)] #[PasswordConfirmationRequired] - public function storeCredentials($mail_smtpname, $mail_smtppassword) { + public function storeCredentials(string $mail_smtpname, ?string $mail_smtppassword): DataResponse { if ($mail_smtppassword === '********') { return new DataResponse($this->l10n->t('Invalid SMTP password.'), Http::STATUS_BAD_REQUEST); } - $this->config->setSystemValues([ - 'mail_smtpname' => $mail_smtpname, - 'mail_smtppassword' => $mail_smtppassword, - ]); - + if ($mail_smtppassword !== null) { + $this->config->setSystemValue('mail_smtppassword', $mail_smtppassword); + } + $this->config->setSystemValue('mail_smtpname', $mail_smtpname); $this->config->setAppValue('core', 'emailTestSuccessful', '0'); return new DataResponse(); diff --git a/apps/settings/lib/Settings/Admin/Mail.php b/apps/settings/lib/Settings/Admin/Mail.php index 8bf2342a59c..92dc9a340e4 100644 --- a/apps/settings/lib/Settings/Admin/Mail.php +++ b/apps/settings/lib/Settings/Admin/Mail.php @@ -7,20 +7,22 @@ namespace OCA\Settings\Settings\Admin; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IInitialState; use OCP\IBinaryFinder; use OCP\IConfig; use OCP\IL10N; +use OCP\IURLGenerator; use OCP\Server; use OCP\Settings\IDelegatedSettings; +use OCP\Util; class Mail implements IDelegatedSettings { - /** - * @param IConfig $config - * @param IL10N $l - */ + public function __construct( private IConfig $config, private IL10N $l, + private IInitialState $initialState, + private IURLGenerator $urlGenerator, ) { } @@ -30,30 +32,56 @@ class Mail implements IDelegatedSettings { public function getForm() { $finder = Server::get(IBinaryFinder::class); - $parameters = [ - // Mail - 'sendmail_is_available' => $finder->findBinaryPath('sendmail') !== false, + $smtpModeOptions = [ + ['label' => 'SMTP', 'id' => 'smtp'], + ]; + if ($finder->findBinaryPath('sendmail') !== false) { + $smtpModeOptions[] = ['label' => 'Sendmail', 'id' => 'sendmail']; + } + if ($finder->findBinaryPath('qmail') !== false) { + $smtpModeOptions[] = ['label' => 'qmail', 'id' => 'qmail']; + } + + $this->initialState->provideInitialState('settingsAdminMail', [ + 'configIsReadonly' => $this->config->getSystemValueBool('config_is_read_only', false), + 'docUrl' => $this->urlGenerator->linkToDocs('admin-email'), + + 'smtpModeOptions' => $smtpModeOptions, + 'smtpEncryptionOptions' => [ + ['label' => $this->l->t('None / STARTTLS'), 'id' => ''], + ['label' => 'SSL/TLS', 'id' => 'ssl'], + ], + 'smtpSendmailModeOptions' => [ + ['label' => 'smtp (-bs)', 'id' => 'smtp'], + ['label' => 'pipe (-t -i)', 'id' => 'pipe'], + ], + ]); + + $smtpPassword = $this->config->getSystemValue('mail_smtppassword', ''); + if ($smtpPassword !== '') { + $smtpPassword = '********'; + } + + $smtpMode = $this->config->getSystemValue('mail_smtpmode', ''); + if ($smtpMode === '' || $smtpMode === 'php') { + $smtpMode = 'smtp'; + } + + $this->initialState->provideInitialState('settingsAdminMailConfig', [ 'mail_domain' => $this->config->getSystemValue('mail_domain', ''), 'mail_from_address' => $this->config->getSystemValue('mail_from_address', ''), - 'mail_smtpmode' => $this->config->getSystemValue('mail_smtpmode', ''), + 'mail_smtpmode' => $smtpMode, 'mail_smtpsecure' => $this->config->getSystemValue('mail_smtpsecure', ''), 'mail_smtphost' => $this->config->getSystemValue('mail_smtphost', ''), 'mail_smtpport' => $this->config->getSystemValue('mail_smtpport', ''), 'mail_smtpauth' => $this->config->getSystemValue('mail_smtpauth', false), 'mail_smtpname' => $this->config->getSystemValue('mail_smtpname', ''), - 'mail_smtppassword' => $this->config->getSystemValue('mail_smtppassword', ''), + 'mail_smtppassword' => $smtpPassword, 'mail_sendmailmode' => $this->config->getSystemValue('mail_sendmailmode', 'smtp'), - ]; + ]); - if ($parameters['mail_smtppassword'] !== '') { - $parameters['mail_smtppassword'] = '********'; - } - - if ($parameters['mail_smtpmode'] === '' || $parameters['mail_smtpmode'] === 'php') { - $parameters['mail_smtpmode'] = 'smtp'; - } - - return new TemplateResponse('settings', 'settings/admin/additional-mail', $parameters, ''); + Util::addScript('settings', 'vue-settings-admin-mail'); + return new TemplateResponse('settings', 'settings/admin/additional-mail', renderAs: ''); } /** diff --git a/apps/settings/src/admin-settings-mail.ts b/apps/settings/src/admin-settings-mail.ts new file mode 100644 index 00000000000..57cb75fd82b --- /dev/null +++ b/apps/settings/src/admin-settings-mail.ts @@ -0,0 +1,10 @@ +/*! + * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import Vue from 'vue' +import AdminSettingsMailServer from './views/AdminSettingsMailServer.vue' + +const app = new Vue(AdminSettingsMailServer) +app.$mount('#vue-admin-settings-mail') diff --git a/apps/settings/src/admin-settings-sharing.ts b/apps/settings/src/admin-settings-sharing.ts index ae73cbd519a..e8bd7d0fa92 100644 --- a/apps/settings/src/admin-settings-sharing.ts +++ b/apps/settings/src/admin-settings-sharing.ts @@ -1,7 +1,8 @@ -/** +/*! * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ + import Vue from 'vue' import AdminSettingsSharing from './views/AdminSettingsSharing.vue' diff --git a/apps/settings/src/admin.js b/apps/settings/src/admin.js deleted file mode 100644 index f272e1173f2..00000000000 --- a/apps/settings/src/admin.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import axios from '@nextcloud/axios' -import { generateUrl } from '@nextcloud/router' -import $ from 'jquery' - -window.addEventListener('DOMContentLoaded', () => { - $('#loglevel').change(function() { - $.post(generateUrl('/settings/admin/log/level'), { level: $(this).val() }, () => { - OC.Log.reload() - }) - }) - - $('#mail_smtpauth').change(function() { - if (!this.checked) { - $('#mail_credentials').addClass('hidden') - } else { - $('#mail_credentials').removeClass('hidden') - } - }) - - $('#mail_smtpmode').change(function() { - if ($(this).val() !== 'smtp') { - $('#setting_smtpauth').addClass('hidden') - $('#setting_smtphost').addClass('hidden') - $('#mail_smtpsecure_label').addClass('hidden') - $('#mail_smtpsecure').addClass('hidden') - $('#mail_credentials').addClass('hidden') - $('#mail_sendmailmode_label, #mail_sendmailmode').removeClass('hidden') - } else { - $('#setting_smtpauth').removeClass('hidden') - $('#setting_smtphost').removeClass('hidden') - $('#mail_smtpsecure_label').removeClass('hidden') - $('#mail_smtpsecure').removeClass('hidden') - if ($('#mail_smtpauth').is(':checked')) { - $('#mail_credentials').removeClass('hidden') - } - $('#mail_sendmailmode_label, #mail_sendmailmode').addClass('hidden') - } - }) - - const changeEmailSettings = function() { - if (OC.PasswordConfirmation.requiresPasswordConfirmation()) { - OC.PasswordConfirmation.requirePasswordConfirmation(changeEmailSettings) - return - } - - OC.msg.startSaving('#mail_settings_msg') - axios.post(generateUrl('/settings/admin/mailsettings'), $('#mail_general_settings_form').serialize()) - .then(() => { - OC.msg.finishedSuccess('#mail_settings_msg', t('settings', 'Saved')) - }).catch((error) => { - OC.msg.finishedError('#mail_settings_msg', error) - }) - } - - const toggleEmailCredentials = function() { - if (OC.PasswordConfirmation.requiresPasswordConfirmation()) { - OC.PasswordConfirmation.requirePasswordConfirmation(toggleEmailCredentials) - return - } - - OC.msg.startSaving('#mail_settings_msg') - axios.post(generateUrl('/settings/admin/mailsettings/credentials'), $('#mail_credentials_settings').serialize()) - .then(() => { - OC.msg.finishedSuccess('#mail_settings_msg', t('settings', 'Saved')) - }).catch((error) => { - OC.msg.finishedError('#mail_settings_msg', error) - }) - } - - $('#mail_general_settings_form').change(changeEmailSettings) - $('#mail_credentials_settings_submit').click(toggleEmailCredentials) - $('#mail_smtppassword').click(() => { - if (this.type === 'text' && this.value === '********') { - this.type = 'password' - this.value = '' - } - }) - - $('#sendtestemail').click((event) => { - event.preventDefault() - OC.msg.startAction('#sendtestmail_msg', t('settings', 'Sending…')) - - axios.post(generateUrl('/settings/admin/mailtest')) - .then(() => { - OC.msg.finishedSuccess('#sendtestmail_msg', t('settings', 'Email sent')) - }).catch((error) => { - OC.msg.finishedError('#sendtestmail_msg', error.response.data) - }) - }) -}) diff --git a/apps/settings/src/views/AdminSettingsMailServer.vue b/apps/settings/src/views/AdminSettingsMailServer.vue new file mode 100644 index 00000000000..713832b88f7 --- /dev/null +++ b/apps/settings/src/views/AdminSettingsMailServer.vue @@ -0,0 +1,259 @@ + + + + + + + diff --git a/apps/settings/templates/settings/admin/additional-mail.php b/apps/settings/templates/settings/admin/additional-mail.php index 6d6c036e813..0f47c10d776 100644 --- a/apps/settings/templates/settings/admin/additional-mail.php +++ b/apps/settings/templates/settings/admin/additional-mail.php @@ -3,152 +3,6 @@ * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ - -/** @var \OCP\IL10N $l */ -/** @var array $_ */ - -$mail_smtpauthtype = [ - 'LOGIN' => $l->t('Login') -]; - -$mail_smtpsecure = [ - '' => $l->t('None/STARTTLS'), - 'ssl' => $l->t('SSL') -]; - -$mail_smtpmode = [ - ['smtp', 'SMTP'], -]; -if ($_['sendmail_is_available']) { - $mail_smtpmode[] = ['sendmail', 'Sendmail']; -} -if ($_['mail_smtpmode'] === 'qmail') { - $mail_smtpmode[] = ['qmail', 'qmail']; -} - -$mail_sendmailmode = [ - 'smtp' => 'smtp (-bs)', - 'pipe' => 'pipe (-t -i)' -]; - ?> -
- -

t('Email server'));?>

- -

- t('Mail delivery is disabled by instance config "%s".', ['mail_smtpmode'])); ?> -

- -
-

t('Email server'));?>

- -

- t('It is important to set up this server to be able to send emails, like for password reset and notifications.')); ?> -

-

- -

- - -

- -

- - -

- -

- - -

- -

- - @ - -

- - - -
-
- -
- -
- t('Test and verify email settings')); ?> - - - -
+
diff --git a/apps/settings/templates/settings/frame.php b/apps/settings/templates/settings/frame.php index 6eafc50a8f4..ec21cad5895 100644 --- a/apps/settings/templates/settings/frame.php +++ b/apps/settings/templates/settings/frame.php @@ -5,7 +5,6 @@ */ style('settings', 'settings'); -\OCP\Util::addScript('settings', 'legacy-admin'); ?>
diff --git a/build/frontend-legacy/webpack.modules.cjs b/build/frontend-legacy/webpack.modules.cjs index b7e557f3dad..2835ec4c1c4 100644 --- a/build/frontend-legacy/webpack.modules.cjs +++ b/build/frontend-legacy/webpack.modules.cjs @@ -52,11 +52,11 @@ module.exports = { 'public-nickname-handler': path.join(__dirname, 'apps/files_sharing/src', 'public-nickname-handler.ts'), }, settings: { - 'legacy-admin': path.join(__dirname, 'apps/settings/src', 'admin.js'), 'vue-settings-admin-overview': path.join(__dirname, 'apps/settings/src', 'main-admin-overview.ts'), 'vue-settings-admin-basic-settings': path.join(__dirname, 'apps/settings/src', 'main-admin-basic-settings.js'), 'vue-settings-admin-ai': path.join(__dirname, 'apps/settings/src', 'main-admin-ai.js'), 'vue-settings-admin-delegation': path.join(__dirname, 'apps/settings/src', 'main-admin-delegation.js'), + 'vue-settings-admin-mail': path.join(__dirname, 'apps/settings/src', 'admin-settings-mail.ts'), 'vue-settings-admin-security': path.join(__dirname, 'apps/settings/src', 'main-admin-security.js'), 'vue-settings-admin-settings-presets': path.join(__dirname, 'apps/settings/src', 'main-admin-settings-presets.js'), 'vue-settings-admin-sharing': path.join(__dirname, 'apps/settings/src', 'admin-settings-sharing.ts'),