From 26dfe10da6c9bb24a9739f7ebbd8b6227a48c09d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 6 Feb 2026 08:26:22 +0000
Subject: [PATCH 1/5] Initial plan
From f852e6e6b3026b7115399eec07c8c3a4ee8e8b56 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 6 Feb 2026 08:29:32 +0000
Subject: [PATCH 2/5] Add backend API for mailbox administration (list, update,
delete)
Co-authored-by: printminion-co <145785698+printminion-co@users.noreply.github.com>
---
appinfo/routes.php | 15 ++
lib/Controller/MailboxAdminController.php | 124 +++++++++++++
lib/Service/MailboxAdminService.php | 201 ++++++++++++++++++++++
3 files changed, 340 insertions(+)
create mode 100644 lib/Controller/MailboxAdminController.php
create mode 100644 lib/Service/MailboxAdminService.php
diff --git a/appinfo/routes.php b/appinfo/routes.php
index addac33608..e89f5c461a 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -530,6 +530,21 @@
'url' => '/api/action-step/{actionId}/steps',
'verb' => 'GET'
],
+ [
+ 'name' => 'mailboxAdmin#listMailboxes',
+ 'url' => '/api/admin/mailboxes',
+ 'verb' => 'GET',
+ ],
+ [
+ 'name' => 'mailboxAdmin#updateMailbox',
+ 'url' => '/api/admin/mailboxes/{userId}',
+ 'verb' => 'PATCH',
+ ],
+ [
+ 'name' => 'mailboxAdmin#deleteMailbox',
+ 'url' => '/api/admin/mailboxes/{userId}',
+ 'verb' => 'DELETE',
+ ],
],
'resources' => [
'accounts' => ['url' => '/api/accounts'],
diff --git a/lib/Controller/MailboxAdminController.php b/lib/Controller/MailboxAdminController.php
new file mode 100644
index 0000000000..80a7c160e5
--- /dev/null
+++ b/lib/Controller/MailboxAdminController.php
@@ -0,0 +1,124 @@
+mailboxAdminService->listAllMailboxes();
+ return new JSONResponse([
+ 'mailboxes' => $mailboxes,
+ ]);
+ } catch (\Exception $e) {
+ $this->logger->error('Failed to list mailboxes', [
+ 'exception' => $e,
+ ]);
+ return new JSONResponse([
+ 'error' => 'Failed to list mailboxes: ' . $e->getMessage(),
+ ], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * Update a mailbox email address (change localpart)
+ *
+ * @param string $userId The Nextcloud user ID
+ * @param string $newLocalpart The new local part of the email (before @)
+ * @return JSONResponse
+ * @NoCSRFRequired
+ * @AuthorizedAdminSetting(settings=OCA\Mail\Settings\AdminSettings)
+ */
+ public function updateMailbox(string $userId, string $newLocalpart): JSONResponse {
+ try {
+ $result = $this->mailboxAdminService->updateMailboxEmail($userId, $newLocalpart);
+
+ if ($result['success']) {
+ return new JSONResponse([
+ 'success' => true,
+ 'email' => $result['email'],
+ 'message' => 'Mailbox updated successfully',
+ ]);
+ } else {
+ return new JSONResponse([
+ 'success' => false,
+ 'error' => $result['error'],
+ ], Http::STATUS_BAD_REQUEST);
+ }
+ } catch (\Exception $e) {
+ $this->logger->error('Failed to update mailbox', [
+ 'userId' => $userId,
+ 'exception' => $e,
+ ]);
+ return new JSONResponse([
+ 'error' => 'Failed to update mailbox: ' . $e->getMessage(),
+ ], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+
+ /**
+ * Delete a mailbox
+ *
+ * @param string $userId The Nextcloud user ID
+ * @return JSONResponse
+ * @NoCSRFRequired
+ * @AuthorizedAdminSetting(settings=OCA\Mail\Settings\AdminSettings)
+ */
+ public function deleteMailbox(string $userId): JSONResponse {
+ try {
+ $success = $this->mailboxAdminService->deleteMailbox($userId);
+
+ if ($success) {
+ return new JSONResponse([
+ 'success' => true,
+ 'message' => 'Mailbox deleted successfully',
+ ]);
+ } else {
+ return new JSONResponse([
+ 'success' => false,
+ 'error' => 'Failed to delete mailbox',
+ ], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ } catch (\Exception $e) {
+ $this->logger->error('Failed to delete mailbox', [
+ 'userId' => $userId,
+ 'exception' => $e,
+ ]);
+ return new JSONResponse([
+ 'error' => 'Failed to delete mailbox: ' . $e->getMessage(),
+ ], Http::STATUS_INTERNAL_SERVER_ERROR);
+ }
+ }
+}
diff --git a/lib/Service/MailboxAdminService.php b/lib/Service/MailboxAdminService.php
new file mode 100644
index 0000000000..75c7eeec3b
--- /dev/null
+++ b/lib/Service/MailboxAdminService.php
@@ -0,0 +1,201 @@
+
+ */
+ public function listAllMailboxes(): array {
+ $mailboxes = [];
+
+ // Check if IONOS integration is enabled
+ if (!$this->ionosFacade->isEnabled()) {
+ $this->logger->debug('IONOS integration is not enabled');
+ return $mailboxes;
+ }
+
+ // Get all users from Nextcloud
+ $this->userManager->callForSeenUsers(function ($user) use (&$mailboxes) {
+ $userId = $user->getUID();
+
+ // Try to get IONOS email for this user
+ $email = $this->ionosFacade->getProvisionedEmail($userId);
+
+ if ($email !== null) {
+ $mailboxes[] = [
+ 'email' => $email,
+ 'userId' => $userId,
+ 'displayName' => $user->getDisplayName(),
+ 'username' => $userId,
+ ];
+ }
+ });
+
+ $this->logger->info('Listed IONOS mailboxes', [
+ 'count' => count($mailboxes),
+ ]);
+
+ return $mailboxes;
+ }
+
+ /**
+ * Update a mailbox email address by changing the localpart
+ *
+ * @param string $userId The Nextcloud user ID
+ * @param string $newLocalpart The new local part (before @)
+ * @return array{success: bool, email?: string, error?: string}
+ */
+ public function updateMailboxEmail(string $userId, string $newLocalpart): array {
+ // Validate localpart
+ if (empty($newLocalpart) || !$this->isValidLocalpart($newLocalpart)) {
+ return [
+ 'success' => false,
+ 'error' => 'Invalid email localpart',
+ ];
+ }
+
+ // Get the domain
+ $domain = $this->configService->getMailDomain();
+ $newEmail = $newLocalpart . '@' . $domain;
+
+ // Check if the new email is already taken
+ if ($this->isEmailTaken($newEmail, $userId)) {
+ return [
+ 'success' => false,
+ 'error' => 'Email is already taken. Please use some other username.',
+ ];
+ }
+
+ try {
+ // Get user display name for account name
+ $user = $this->userManager->get($userId);
+ if ($user === null) {
+ return [
+ 'success' => false,
+ 'error' => 'User not found',
+ ];
+ }
+
+ $accountName = $user->getDisplayName();
+
+ // Update the account via IONOS facade
+ // The createAccount method in the facade handles both create and update
+ $account = $this->ionosFacade->createAccount($userId, $newLocalpart, $accountName);
+
+ $this->logger->info('Successfully updated mailbox', [
+ 'userId' => $userId,
+ 'newEmail' => $newEmail,
+ ]);
+
+ return [
+ 'success' => true,
+ 'email' => $newEmail,
+ ];
+ } catch (\Exception $e) {
+ $this->logger->error('Failed to update mailbox email', [
+ 'userId' => $userId,
+ 'newLocalpart' => $newLocalpart,
+ 'exception' => $e,
+ ]);
+
+ return [
+ 'success' => false,
+ 'error' => $e->getMessage(),
+ ];
+ }
+ }
+
+ /**
+ * Delete a mailbox
+ *
+ * @param string $userId The Nextcloud user ID
+ * @return bool True if successful
+ */
+ public function deleteMailbox(string $userId): bool {
+ try {
+ $success = $this->ionosFacade->deleteAccount($userId);
+
+ $this->logger->info('Mailbox deletion result', [
+ 'userId' => $userId,
+ 'success' => $success,
+ ]);
+
+ return $success;
+ } catch (\Exception $e) {
+ $this->logger->error('Failed to delete mailbox', [
+ 'userId' => $userId,
+ 'exception' => $e,
+ ]);
+ return false;
+ }
+ }
+
+ /**
+ * Check if an email is already taken by another user
+ *
+ * @param string $email The email address to check
+ * @param string $excludeUserId User ID to exclude from the check
+ * @return bool True if email is taken
+ */
+ private function isEmailTaken(string $email, string $excludeUserId): bool {
+ // Check all users for this email
+ $allUsers = $this->userManager->search('');
+
+ foreach ($allUsers as $user) {
+ $userId = $user->getUID();
+
+ // Skip the user we're updating
+ if ($userId === $excludeUserId) {
+ continue;
+ }
+
+ // Check if this user has this email
+ $userEmail = $this->ionosFacade->getProvisionedEmail($userId);
+ if ($userEmail !== null && strcasecmp($userEmail, $email) === 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Validate email localpart
+ *
+ * @param string $localpart The localpart to validate
+ * @return bool True if valid
+ */
+ private function isValidLocalpart(string $localpart): bool {
+ // Basic validation for email localpart
+ // Allow alphanumeric, dot, hyphen, underscore
+ return preg_match('/^[a-zA-Z0-9._-]+$/', $localpart) === 1;
+ }
+}
From f9cbbdf7e0126c4baa1642c6ea834665726e90a7 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 6 Feb 2026 08:30:52 +0000
Subject: [PATCH 3/5] Add frontend Vue components for mailbox management UI
Co-authored-by: printminion-co <145785698+printminion-co@users.noreply.github.com>
---
src/components/settings/AdminSettings.vue | 11 +
src/components/settings/MailboxListItem.vue | 121 ++++++
src/components/settings/MailboxManagement.vue | 383 ++++++++++++++++++
3 files changed, 515 insertions(+)
create mode 100644 src/components/settings/MailboxListItem.vue
create mode 100644 src/components/settings/MailboxManagement.vue
diff --git a/src/components/settings/AdminSettings.vue b/src/components/settings/AdminSettings.vue
index bfd88096fa..460f03041f 100644
--- a/src/components/settings/AdminSettings.vue
+++ b/src/components/settings/AdminSettings.vue
@@ -266,6 +266,15 @@
+
+
{{ t('mail', 'E-Mail Verwaltung') }}
+
+
+ {{ t('mail', 'Manage IONOS mailboxes linked to Nextcloud users. You can edit email addresses and delete mailboxes from this section.') }}
+
+
+
+
@@ -273,6 +282,7 @@
import ButtonVue from '@nextcloud/vue/components/NcButton'
import GmailAdminOauthSettings from './GmailAdminOauthSettings.vue'
import logger from '../../logger.js'
+import MailboxManagement from './MailboxManagement.vue'
import MicrosoftAdminOauthSettings from './MicrosoftAdminOauthSettings.vue'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { loadState } from '@nextcloud/initial-state'
@@ -305,6 +315,7 @@ export default {
components: {
GmailAdminOauthSettings,
AntiSpamSettings,
+ MailboxManagement,
MicrosoftAdminOauthSettings,
ProvisioningSettings,
SettingsSection,
diff --git a/src/components/settings/MailboxListItem.vue b/src/components/settings/MailboxListItem.vue
new file mode 100644
index 0000000000..a206fc17ae
--- /dev/null
+++ b/src/components/settings/MailboxListItem.vue
@@ -0,0 +1,121 @@
+
+
+
+
+
+ {{ mailbox.email }}
+
+
+
+
+
+ {{ mailbox.displayName }}
+ ({{ mailbox.username }})
+
+
+
+
+
+
+
+
+
+ {{ t('mail', 'Edit') }}
+
+
+
+
+
+ {{ t('mail', 'Delete') }}
+
+
+
+
+
+
+
+
+
diff --git a/src/components/settings/MailboxManagement.vue b/src/components/settings/MailboxManagement.vue
new file mode 100644
index 0000000000..95a4810616
--- /dev/null
+++ b/src/components/settings/MailboxManagement.vue
@@ -0,0 +1,383 @@
+
+
+
+
+
{{ t('mail', 'E-Mails verwalten') }}
+
+
+
+
{{ t('mail', 'Loading mailboxes...') }}
+
+
+
+
+
+
{{ t('mail', 'No IONOS mailboxes found.') }}
+
+
+
+
+
+
+
+
+
+
+
+
{{ t('mail', 'Edit Email Address') }}
+
{{ t('mail', 'Change the local part of the email address (before @)') }}
+
+
+
+
+
+ {{ t('mail', 'Cancel') }}
+
+
+
+
+
+ {{ t('mail', 'Save') }}
+
+
+
+
+
+
+
+
+
{{ t('mail', 'Account deletion') }}
+
+ {{ t('mail', 'Fully delete {username}\'s mailbox including all their email data.', { username: deleteMailbox?.displayName || deleteMailbox?.username }) }}
+
+
+ {{ t('mail', 'This action cannot be undone.') }}
+
+
+
+
+ {{ t('mail', 'Cancel') }}
+
+
+
+
+
+ {{ t('mail', 'Delete {username}\'s mailbox', { username: deleteMailbox?.username }) }}
+
+
+
+
+
+
+
+
+
+
From 5408bb18a13cc1baeb37555b61d7ec61389bf5d8 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 6 Feb 2026 08:42:12 +0000
Subject: [PATCH 4/5] Fix linting issues in mailbox management components
Co-authored-by: printminion-co <145785698+printminion-co@users.noreply.github.com>
---
package-lock.json | 161 ++++++------------
src/components/Envelope.vue | 2 +-
src/components/ExternalProviderTab.vue | 3 +
src/components/settings/MailboxManagement.vue | 50 +++---
4 files changed, 80 insertions(+), 136 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index f0487abfe7..a72bd18500 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6,7 +6,7 @@
"packages": {
"": {
"name": "nextcloud-mail",
- "version": "5.5.9",
+ "version": "5.5.11",
"license": "AGPL-3.0-only",
"dependencies": {
"@ckeditor/ckeditor5-alignment": "44.3.0",
@@ -184,6 +184,7 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz",
"integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.27.1",
@@ -215,6 +216,7 @@
"integrity": "sha512-N4ntErOlKvcbTt01rr5wj3y55xnIdx1ymrfIr8C2WnM1Y9glFgWaGDEULJIazOX3XM9NRzhfJ6zZnQ1sBNWU+w==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1",
"eslint-visitor-keys": "^2.1.0",
@@ -3105,6 +3107,7 @@
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz",
"integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -4165,6 +4168,7 @@
}
],
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=18"
},
@@ -4187,6 +4191,7 @@
}
],
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=18"
}
@@ -4252,7 +4257,6 @@
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.41.0.tgz",
"integrity": "sha512-aKUhyn1QI5Ksbqcr3fFJj16p99QdjUxXAEuFst1Z47DRyoiMwivIH9MV/ARcJOCXVjPfjITciej8ZD2O/6qUmw==",
"dev": true,
- "peer": true,
"dependencies": {
"comment-parser": "1.4.1",
"esquery": "^1.5.0",
@@ -4698,7 +4702,6 @@
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
"integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
"dev": true,
- "peer": true,
"engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
@@ -4708,7 +4711,6 @@
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
"integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
"dev": true,
- "peer": true,
"dependencies": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
@@ -4731,8 +4733,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
"version": "1.1.12",
@@ -4740,7 +4741,6 @@
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -4751,7 +4751,6 @@
"resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
"integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
"dev": true,
- "peer": true,
"dependencies": {
"type-fest": "^0.20.2"
},
@@ -4767,7 +4766,6 @@
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
- "peer": true,
"dependencies": {
"argparse": "^2.0.1"
},
@@ -4780,7 +4778,6 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
- "peer": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -4793,7 +4790,6 @@
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -4806,7 +4802,6 @@
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
"integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
"dev": true,
- "peer": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
@@ -4857,7 +4852,6 @@
"integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
"deprecated": "Use @eslint/config-array instead",
"dev": true,
- "peer": true,
"dependencies": {
"@humanwhocodes/object-schema": "^2.0.3",
"debug": "^4.3.1",
@@ -4873,7 +4867,6 @@
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -4884,7 +4877,6 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
- "peer": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -4897,7 +4889,6 @@
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=12.22"
},
@@ -4911,8 +4902,7 @@
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
"integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
"deprecated": "Use @eslint/object-schema instead",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/@iframe-resizer/child": {
"version": "5.5.5",
@@ -5844,6 +5834,7 @@
"integrity": "sha512-RX+0FxpL1h2EzjNLeW0VSGTkbyWIq7WgV7QAjtyUmDbSGwf1ds9Zy5OcRkgXRHRIu/W0gB0DhS2iz9qXHphCzA==",
"dev": true,
"license": "ISC",
+ "peer": true,
"dependencies": {
"fast-xml-parser": "^4.2.5",
"requireindex": "^1.2.0",
@@ -6112,6 +6103,7 @@
"resolved": "https://registry.npmjs.org/@nextcloud/timezones/-/timezones-0.2.0.tgz",
"integrity": "sha512-1mwQ+asTFOgv9rxPoAMEbDF8JfnenIa2EGNS+8MATCyi6WXxYh0Lhkaq1d3l2+xNbUPHgMnk4cRYsvIo319lkA==",
"license": "AGPL-3.0-or-later",
+ "peer": true,
"dependencies": {
"ical.js": "^2.1.0"
},
@@ -6136,6 +6128,7 @@
"resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-8.31.0.tgz",
"integrity": "sha512-P5m3Odfw4m0siu7qs88WJutu2C8mEknqMS1ijlqYtQvc8qZwmpQshgCV5GhyyBTTK9Baicthm+ULglIf/Eq/sg==",
"license": "AGPL-3.0-or-later",
+ "peer": true,
"dependencies": {
"@floating-ui/dom": "^1.7.4",
"@linusborg/vue-simple-portal": "^0.1.5",
@@ -6282,7 +6275,6 @@
"resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz",
"integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=12.4.0"
}
@@ -7098,7 +7090,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz",
"integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==",
"dev": true,
- "peer": true,
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "7.18.0",
@@ -7197,7 +7188,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz",
"integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==",
"dev": true,
- "peer": true,
"dependencies": {
"@typescript-eslint/types": "7.18.0",
"@typescript-eslint/visitor-keys": "7.18.0"
@@ -7232,7 +7222,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz",
"integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==",
"dev": true,
- "peer": true,
"dependencies": {
"@typescript-eslint/typescript-estree": "7.18.0",
"@typescript-eslint/utils": "7.18.0",
@@ -7260,7 +7249,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz",
"integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==",
"dev": true,
- "peer": true,
"engines": {
"node": "^18.18.0 || >=20.0.0"
},
@@ -7274,7 +7262,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz",
"integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==",
"dev": true,
- "peer": true,
"dependencies": {
"@typescript-eslint/types": "7.18.0",
"@typescript-eslint/visitor-keys": "7.18.0",
@@ -7303,7 +7290,6 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"dev": true,
- "peer": true,
"bin": {
"semver": "bin/semver.js"
},
@@ -7316,7 +7302,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz",
"integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==",
"dev": true,
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "7.18.0",
@@ -7339,7 +7324,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz",
"integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==",
"dev": true,
- "peer": true,
"dependencies": {
"@typescript-eslint/types": "7.18.0",
"eslint-visitor-keys": "^3.4.3"
@@ -7357,7 +7341,6 @@
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
"dev": true,
- "peer": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
@@ -8204,6 +8187,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
+ "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -8291,6 +8275,7 @@
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -8409,7 +8394,6 @@
"resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz",
"integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=14"
}
@@ -8696,6 +8680,7 @@
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
"integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
"dev": true,
+ "peer": true,
"dependencies": {
"@jest/transform": "^29.7.0",
"@types/babel__core": "^7.1.14",
@@ -9207,6 +9192,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"caniuse-lite": "^1.0.30001726",
"electron-to-chromium": "^1.5.173",
@@ -9282,7 +9268,6 @@
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
"integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=6"
},
@@ -9301,7 +9286,6 @@
"resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz",
"integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==",
"dev": true,
- "peer": true,
"dependencies": {
"semver": "^7.0.0"
}
@@ -9311,7 +9295,6 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"dev": true,
- "peer": true,
"bin": {
"semver": "bin/semver.js"
},
@@ -9854,7 +9837,6 @@
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
"integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==",
"dev": true,
- "peer": true,
"engines": {
"node": ">= 12.0.0"
}
@@ -10766,7 +10748,6 @@
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
"dev": true,
- "peer": true,
"dependencies": {
"esutils": "^2.0.2"
},
@@ -11409,7 +11390,6 @@
"resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz",
"integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==",
"dev": true,
- "peer": true,
"dependencies": {
"semver": "^7.5.4"
},
@@ -11425,7 +11405,6 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"dev": true,
- "peer": true,
"bin": {
"semver": "bin/semver.js"
},
@@ -11452,6 +11431,7 @@
"url": "https://feross.org/support"
}
],
+ "peer": true,
"engines": {
"node": ">=12.0.0"
},
@@ -11568,7 +11548,6 @@
"https://github.com/sponsors/ota-meshi",
"https://opencollective.com/eslint"
],
- "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.1.2",
"@eslint-community/regexpp": "^4.11.0",
@@ -11587,6 +11566,7 @@
"integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@rtsao/scc": "^1.1.0",
"array-includes": "^3.1.9",
@@ -11667,7 +11647,6 @@
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.10.1.tgz",
"integrity": "sha512-x8wxIpv00Y50NyweDUpa+58ffgSAI5sqe+zcZh33xphD0AVh+1kqr1ombaTRb7Fhpove1zfUuujlX9DWWBP5ag==",
"dev": true,
- "peer": true,
"dependencies": {
"@es-joy/jsdoccomment": "~0.41.0",
"are-docs-informative": "^0.0.2",
@@ -11691,7 +11670,6 @@
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -11704,7 +11682,6 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"dev": true,
- "peer": true,
"bin": {
"semver": "bin/semver.js"
},
@@ -11747,7 +11724,6 @@
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -11758,7 +11734,6 @@
"resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
"integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
"dev": true,
- "peer": true,
"dependencies": {
"type-fest": "^0.20.2"
},
@@ -11774,7 +11749,6 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
- "peer": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -11787,7 +11761,6 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"dev": true,
- "peer": true,
"bin": {
"semver": "bin/semver.js"
},
@@ -11800,7 +11773,6 @@
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -11990,6 +11962,7 @@
"integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"globals": "^13.24.0",
@@ -12074,8 +12047,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/eslint/node_modules/brace-expansion": {
"version": "1.1.12",
@@ -12083,7 +12055,6 @@
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -12094,7 +12065,6 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
- "peer": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -12111,7 +12081,6 @@
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -12124,7 +12093,6 @@
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
"integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
"dev": true,
- "peer": true,
"dependencies": {
"esrecurse": "^4.3.0",
"estraverse": "^5.2.0"
@@ -12141,7 +12109,6 @@
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
"dev": true,
- "peer": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
@@ -12154,7 +12121,6 @@
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=4.0"
}
@@ -12164,7 +12130,6 @@
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
- "peer": true,
"dependencies": {
"locate-path": "^6.0.0",
"path-exists": "^4.0.0"
@@ -12181,7 +12146,6 @@
"resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
"integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
"dev": true,
- "peer": true,
"dependencies": {
"type-fest": "^0.20.2"
},
@@ -12197,7 +12161,6 @@
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
- "peer": true,
"dependencies": {
"argparse": "^2.0.1"
},
@@ -12210,7 +12173,6 @@
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
- "peer": true,
"dependencies": {
"p-locate": "^5.0.0"
},
@@ -12226,7 +12188,6 @@
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
- "peer": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -12239,7 +12200,6 @@
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
- "peer": true,
"dependencies": {
"yocto-queue": "^0.1.0"
},
@@ -12255,7 +12215,6 @@
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
- "peer": true,
"dependencies": {
"p-limit": "^3.0.2"
},
@@ -12271,7 +12230,6 @@
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -12284,7 +12242,6 @@
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=10"
},
@@ -12609,7 +12566,6 @@
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
"integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
"dev": true,
- "peer": true,
"dependencies": {
"flat-cache": "^3.0.4"
},
@@ -12691,7 +12647,6 @@
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
"integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
"dev": true,
- "peer": true,
"dependencies": {
"flatted": "^3.2.9",
"keyv": "^4.5.3",
@@ -13061,7 +13016,6 @@
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"dev": true,
- "peer": true,
"dependencies": {
"is-glob": "^4.0.3"
},
@@ -13198,8 +13152,7 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/handlebars": {
"version": "4.7.8",
@@ -13546,7 +13499,8 @@
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ical.js/-/ical.js-2.2.1.tgz",
"integrity": "sha512-yK/UlPbEs316igb/tjRgbFA8ZV75rCsBJp/hWOatpyaPNlgw0dGDmU+FoicOcwX4xXkeXOkYiOmCqNPFpNPkQg==",
- "license": "MPL-2.0"
+ "license": "MPL-2.0",
+ "peer": true
},
"node_modules/iconv-lite": {
"version": "0.6.3",
@@ -13853,7 +13807,6 @@
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
"integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
"dev": true,
- "peer": true,
"dependencies": {
"builtin-modules": "^3.3.0"
},
@@ -13869,7 +13822,6 @@
"resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz",
"integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==",
"dev": true,
- "peer": true,
"dependencies": {
"semver": "^7.6.3"
}
@@ -13879,7 +13831,6 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
"integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"dev": true,
- "peer": true,
"bin": {
"semver": "bin/semver.js"
},
@@ -14457,6 +14408,7 @@
"resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
"integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
"dev": true,
+ "peer": true,
"dependencies": {
"@jest/core": "^29.7.0",
"@jest/types": "^29.6.3",
@@ -15567,7 +15519,6 @@
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz",
"integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=12.0.0"
}
@@ -15632,8 +15583,7 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
@@ -15649,8 +15599,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/json5": {
"version": "2.2.3",
@@ -15684,7 +15633,6 @@
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"dev": true,
- "peer": true,
"dependencies": {
"json-buffer": "3.0.1"
}
@@ -15723,8 +15671,7 @@
"resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.36.0.tgz",
"integrity": "sha512-A+9jP+IUmuQsNdsLdcg6Yt7voiMF/D4K83ew0OpJtpu+l34ef7LaohWV0Rc6KNvzw6ZDizkqfyB5JznZnzuKQA==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/layerr": {
"version": "0.1.2",
@@ -15753,7 +15700,6 @@
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
"dev": true,
- "peer": true,
"dependencies": {
"prelude-ls": "^1.2.1",
"type-check": "~0.4.0"
@@ -15853,8 +15799,7 @@
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/lodash.throttle": {
"version": "4.1.1",
@@ -17509,7 +17454,6 @@
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
"dev": true,
- "peer": true,
"dependencies": {
"deep-is": "^0.1.3",
"fast-levenshtein": "^2.0.6",
@@ -17877,6 +17821,7 @@
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.3.1.tgz",
"integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@vue/devtools-api": "^6.6.3",
"vue-demi": "^0.14.10"
@@ -18019,6 +17964,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -18122,7 +18068,6 @@
"integrity": "sha512-5mMeb1TgLWoRKxZ0Xh9RZDfwUUIqRrcxO2uXO+Ezl1N5lqpCiSU5Gk6+1kZediBfBHFtPCdopr2UZ2SgUsKcgQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"htmlparser2": "^8.0.0",
"js-tokens": "^9.0.0",
@@ -18138,8 +18083,7 @@
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
"integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/postcss-html/node_modules/postcss-safe-parser": {
"version": "6.0.0",
@@ -18147,7 +18091,6 @@
"integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12.0"
},
@@ -18249,8 +18192,7 @@
"resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz",
"integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==",
"dev": true,
- "license": "MIT",
- "peer": true
+ "license": "MIT"
},
"node_modules/postcss-merge-longhand": {
"version": "5.1.7",
@@ -18682,7 +18624,6 @@
}
],
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=12.0"
},
@@ -18694,6 +18635,7 @@
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+ "peer": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -18756,7 +18698,6 @@
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true,
- "peer": true,
"engines": {
"node": ">= 0.8.0"
}
@@ -19652,6 +19593,7 @@
"integrity": "sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"chokidar": "^4.0.0",
"immutable": "^5.0.2",
@@ -19749,6 +19691,7 @@
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+ "peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
@@ -20100,15 +20043,13 @@
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
"integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/spdx-expression-parse": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz",
"integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==",
"dev": true,
- "peer": true,
"dependencies": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
@@ -20118,8 +20059,7 @@
"version": "3.0.20",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz",
"integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/splitpanes": {
"version": "2.4.1",
@@ -20153,8 +20093,7 @@
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz",
"integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/stack-utils": {
"version": "2.0.6",
@@ -20502,6 +20441,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"@csstools/css-parser-algorithms": "^3.0.5",
"@csstools/css-tokenizer": "^3.0.4",
@@ -20555,7 +20495,6 @@
"integrity": "sha512-IZv4IVESjKLumUGi+HWeb7skgO6/g4VMuAYrJdlqQFndgbj6WJAXPhaysvBiXefX79upBdQVumgYcdd17gCpjQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"engines": {
"node": "^12 || >=14"
},
@@ -20583,7 +20522,6 @@
}
],
"license": "MIT",
- "peer": true,
"engines": {
"node": ">=18.12.0"
},
@@ -20622,7 +20560,6 @@
"integrity": "sha512-lLW7hTIMBiTfjenGuDq2kyHA6fBWd/+Df7MO4/AWOxiFeXP9clbpKgg27kHfwA3H7UNMGC7aeP3mNlZB5LMmEQ==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"semver": "^7.3.5",
"stylelint-config-html": ">=1.0.0",
@@ -20645,7 +20582,6 @@
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"dev": true,
"license": "ISC",
- "peer": true,
"bin": {
"semver": "bin/semver.js"
},
@@ -20659,7 +20595,6 @@
"integrity": "sha512-UJUfBFIvXfly8WKIgmqfmkGKPilKB4L5j38JfsDd+OCg2GBdU0vGUV08Uw82tsRZzd4TbsUURVVNGeOhJVF7pA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"css-tree": "^3.0.1",
"is-plain-object": "^5.0.0",
@@ -20683,7 +20618,6 @@
"integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"mdn-data": "2.12.2",
"source-map-js": "^1.0.1"
@@ -20697,16 +20631,14 @@
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz",
"integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==",
"dev": true,
- "license": "CC0-1.0",
- "peer": true
+ "license": "CC0-1.0"
},
"node_modules/stylelint-scss/node_modules/mdn-data": {
"version": "2.22.1",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.22.1.tgz",
"integrity": "sha512-u9Xnc9zLuF/CL2IHPow7HcXPpb8okQyzYpwL5wFsY//JRedSWYglYRg3PYWoQCu1zO+tBTmWOJN/iM0mPC5CRQ==",
"dev": true,
- "license": "CC0-1.0",
- "peer": true
+ "license": "CC0-1.0"
},
"node_modules/stylelint-scss/node_modules/postcss-selector-parser": {
"version": "7.1.0",
@@ -20714,7 +20646,6 @@
"integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -20867,6 +20798,7 @@
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz",
"integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -21350,8 +21282,7 @@
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
- "dev": true,
- "peer": true
+ "dev": true
},
"node_modules/through2": {
"version": "3.0.2",
@@ -21427,6 +21358,7 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"license": "MIT",
+ "peer": true,
"engines": {
"node": ">=12"
},
@@ -21535,7 +21467,6 @@
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
"integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
"dev": true,
- "peer": true,
"engines": {
"node": ">=16"
},
@@ -21765,7 +21696,6 @@
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
"dev": true,
- "peer": true,
"dependencies": {
"prelude-ls": "^1.2.1"
},
@@ -21876,6 +21806,7 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"license": "Apache-2.0",
+ "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -22308,6 +22239,7 @@
"resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz",
"integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==",
"deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.",
+ "peer": true,
"dependencies": {
"@vue/compiler-sfc": "2.7.16",
"csstype": "^3.1.0"
@@ -22580,6 +22512,7 @@
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz",
"integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==",
"dev": true,
+ "peer": true,
"dependencies": {
"de-indent": "^1.0.2",
"he": "^1.2.0"
@@ -22739,6 +22672,7 @@
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.0.tgz",
"integrity": "sha512-B4t+nJqytPeuZlHuIKTbalhljIFXeNRqrUGAQgTGlfOl2lXXKXw+yZu6bicycP+PUlM44CxBjCFD6aciKFT3LQ==",
"license": "MIT",
+ "peer": true,
"dependencies": {
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.8",
@@ -22787,6 +22721,7 @@
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz",
"integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==",
"dev": true,
+ "peer": true,
"dependencies": {
"@discoveryjs/json-ext": "^0.5.0",
"@webpack-cli/configtest": "^2.1.1",
diff --git a/src/components/Envelope.vue b/src/components/Envelope.vue
index 7c0454aee6..3e66498239 100644
--- a/src/components/Envelope.vue
+++ b/src/components/Envelope.vue
@@ -971,7 +971,7 @@ export default {
*
* In Mailbox.onDelete, fetchNextEnvelopes requires the current envelope to find the next envelope.
* Therefore, it must run before removing the envelope.
- */
+ */
if (removeEnvelope) {
this.$emit('delete', envelope)
diff --git a/src/components/ExternalProviderTab.vue b/src/components/ExternalProviderTab.vue
index edc7cb8e3a..2c7edb47c7 100644
--- a/src/components/ExternalProviderTab.vue
+++ b/src/components/ExternalProviderTab.vue
@@ -305,6 +305,8 @@ export default {
/**
* Try to fetch mailboxes with exponential backoff retry logic
* Returns true if successful, false if all retries failed
+ * @param account
+ * @param maxAttempts
*/
async tryFetchMailboxesWithRetry(account, maxAttempts = 3) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
@@ -359,6 +361,7 @@ export default {
/**
* Helper to delay execution
+ * @param ms
*/
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
diff --git a/src/components/settings/MailboxManagement.vue b/src/components/settings/MailboxManagement.vue
index 95a4810616..cc7527ee25 100644
--- a/src/components/settings/MailboxManagement.vue
+++ b/src/components/settings/MailboxManagement.vue
@@ -6,7 +6,7 @@
{{ t('mail', 'E-Mails verwalten') }}
-
+
{{ t('mail', 'Loading mailboxes...') }}
@@ -22,13 +22,18 @@
-
+ :name="t('mail', 'Edit Mailbox')"
+ @close="closeEditModal">
{{ t('mail', 'Edit Email Address') }}
{{ t('mail', 'Change the local part of the email address (before @)') }}
-
+
@@ -75,8 +81,8 @@
+ :name="t('mail', 'Account deletion')"
+ @close="closeDeleteModal">
{{ t('mail', 'Account deletion') }}
@@ -128,14 +134,14 @@ export default {
error: null,
mailboxes: [],
emailDomain: '',
-
+
// Edit state
showEditModal: false,
editMailbox: null,
editLocalpart: '',
editError: null,
editSaving: false,
-
+
// Delete state
showDeleteModal: false,
deleteMailbox: null,
@@ -153,9 +159,9 @@ export default {
try {
const url = generateUrl('/apps/mail/api/admin/mailboxes')
const response = await axios.get(url)
-
+
this.mailboxes = response.data.mailboxes || []
-
+
// Extract domain from first mailbox if available
if (this.mailboxes.length > 0) {
const firstEmail = this.mailboxes[0].email
@@ -164,7 +170,7 @@ export default {
this.emailDomain = firstEmail.substring(atIndex + 1)
}
}
-
+
logger.info('Loaded mailboxes', { count: this.mailboxes.length })
} catch (error) {
logger.error('Failed to load mailboxes', { error })
@@ -204,7 +210,7 @@ export default {
const url = generateUrl('/apps/mail/api/admin/mailboxes/{userId}', {
userId: this.editMailbox.userId,
})
-
+
const response = await axios.patch(url, {
newLocalpart: this.editLocalpart,
})
@@ -219,7 +225,7 @@ export default {
}
} catch (error) {
logger.error('Failed to update mailbox', { error })
-
+
if (error.response?.data?.error) {
this.editError = error.response.data.error
} else {
@@ -253,7 +259,7 @@ export default {
const url = generateUrl('/apps/mail/api/admin/mailboxes/{userId}', {
userId: this.deleteMailbox.userId,
})
-
+
await axios.delete(url)
showSuccess(this.t('mail', 'Mailbox deleted successfully'))
From 46d33a68934fc06150a08995d6964b250bc074ee Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 6 Feb 2026 08:43:36 +0000
Subject: [PATCH 5/5] Add documentation for IONOS mailbox management feature
Co-authored-by: printminion-co <145785698+printminion-co@users.noreply.github.com>
---
doc/admin.md | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/doc/admin.md b/doc/admin.md
index f8d1c9ea82..e45eef1f51 100644
--- a/doc/admin.md
+++ b/doc/admin.md
@@ -286,3 +286,41 @@ If you can not access your Outlook.com account try to enable the 'Two-Factor Ver
If autoconfiguration for your domain fails, you can create an autoconfig file and place it as https://autoconfig.yourdomain.tld/mail/config-v1.1.xml
For more information please refer to Mozilla's documentation:
https://developer.mozilla.org/en-US/docs/Mozilla/Thunderbird/Autoconfiguration/FileFormat/HowTo
+
+## IONOS Mailbox Management
+
+If you have IONOS mail integration enabled, administrators can manage IONOS mailboxes from the admin settings page.
+
+### Features
+
+- **View all mailboxes**: Lists all IONOS mailboxes linked to Nextcloud users
+- **Edit email addresses**: Change the local part (before @) of a user's email address
+- **Delete mailboxes**: Remove IONOS mailboxes with confirmation
+
+### Access
+
+1. Navigate to Administration Settings > Mail
+2. Scroll down to the "E-Mail Verwaltung" (Email Administration) section
+
+### Edit a Mailbox
+
+To change a user's email address:
+
+1. Click the three-dot menu next to the mailbox
+2. Select "Edit"
+3. Enter the new local part (username before @)
+4. Click "Save"
+
+The system will validate that:
+- The new email address is not already in use
+- The local part is valid (alphanumeric, dots, hyphens, underscores)
+
+### Delete a Mailbox
+
+To delete a user's IONOS mailbox:
+
+1. Click the three-dot menu next to the mailbox
+2. Select "Delete"
+3. Confirm the deletion in the dialog
+
+**Warning**: This action cannot be undone and will remove all email data for that user.