@rapidmx/web-client 0.21.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -14
- package/apps/admin/_layout.tsx +2 -2
- package/apps/admin/audit-log/index.tsx +4 -4
- package/apps/admin/branding/index.tsx +3 -3
- package/apps/admin/data-requests/index.tsx +8 -8
- package/apps/admin/distribution-lists/[uid].tsx +3 -3
- package/apps/admin/distribution-lists/index.tsx +4 -4
- package/apps/admin/distribution-lists/new/index.tsx +5 -5
- package/apps/admin/domains/[uid].tsx +6 -6
- package/apps/admin/domains/index.tsx +4 -4
- package/apps/admin/domains/new/index.tsx +5 -5
- package/apps/admin/encryption-policy/index.tsx +1 -1
- package/apps/admin/escrow-scopes/[uid].tsx +7 -7
- package/apps/admin/escrow-scopes/index.tsx +4 -4
- package/apps/admin/escrow-scopes/new/index.tsx +5 -5
- package/apps/admin/index.tsx +6 -6
- package/apps/admin/ingest-queue/index.tsx +4 -4
- package/apps/admin/mailbox-policy/index.tsx +1 -1
- package/apps/admin/mailboxes/[uid].tsx +5 -5
- package/apps/admin/quarantine/index.tsx +5 -5
- package/apps/admin/retention-policy/index.tsx +3 -3
- package/apps/admin/signing-certificates/index.tsx +5 -5
- package/apps/admin/transport-rules/[uid].tsx +5 -5
- package/apps/admin/transport-rules/_transportRuleConfig.tsx +3 -3
- package/apps/admin/transport-rules/index.tsx +4 -4
- package/apps/admin/transport-rules/new/index.tsx +5 -5
- package/apps/escrow/_layout.tsx +1 -1
- package/apps/escrow/audit-log/index.tsx +4 -4
- package/apps/escrow/index.tsx +4 -4
- package/apps/escrow/matters/[uid].tsx +10 -10
- package/apps/escrow/matters/new/index.tsx +6 -6
- package/apps/shared/appearance/AppearanceForm.tsx +3 -3
- package/apps/shared/appearance/AppearanceHead.tsx +1 -1
- package/apps/shared/appearance/AppearanceProvider.tsx +3 -3
- package/apps/shared/appearance/appearanceCache.ts +1 -1
- package/apps/shared/appearance/appearanceContext.ts +1 -1
- package/apps/shared/appearance/theme.ts +1 -1
- package/apps/shared/auth/adminAccess.ts +1 -1
- package/apps/shared/calendar/bookingPlugin.ts +1 -1
- package/apps/shared/calendar/calendarLiveUpdates.ts +1 -1
- package/apps/shared/calendar/calendarReminders.ts +1 -1
- package/apps/shared/calendar/useCalendarReminders.ts +1 -1
- package/apps/shared/components/admin/diagnostics/DiagnosticsManager.tsx +1 -1
- package/apps/shared/components/admin/diagnostics/InstalledPlugins.tsx +2 -2
- package/apps/shared/components/admin/diagnostics/LogsPanel.tsx +2 -2
- package/apps/shared/components/admin/diagnostics/PackagesTable.tsx +1 -1
- package/apps/shared/components/admin/diagnostics/RuntimePanel.tsx +1 -1
- package/apps/shared/components/admin/diagnostics/SystemPanel.tsx +2 -2
- package/apps/shared/components/admin/diagnostics/VersionsPanel.tsx +1 -1
- package/apps/shared/components/admin/diagnostics/diagnosticsApi.ts +1 -1
- package/apps/shared/components/admin/diagnostics/format.ts +1 -1
- package/apps/shared/components/admin/diagnostics/logClient.ts +1 -1
- package/apps/shared/components/admin/distributionLists/MemberListCard.tsx +4 -4
- package/apps/shared/components/admin/elevation.ts +1 -1
- package/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.tsx +3 -3
- package/apps/shared/components/admin/layout/AdminShell.tsx +8 -8
- package/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.tsx +6 -6
- package/apps/shared/components/admin/mailboxes/EscrowScopeCard.tsx +10 -8
- package/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.tsx +4 -4
- package/apps/shared/components/admin/mailboxes/MailboxTable.tsx +1 -1
- package/apps/shared/components/admin/mailboxes/ResourceSettingsCard.tsx +19 -14
- package/apps/shared/components/admin/mailboxes/ShareAccessCard.tsx +5 -5
- package/apps/shared/components/admin/settings/BrandingForm.tsx +5 -5
- package/apps/shared/components/admin/settings/DomainDnsSetup.tsx +5 -5
- package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +4 -4
- package/apps/shared/components/admin/settings/LoadedSettingsForm.tsx +2 -2
- package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +32 -27
- package/apps/shared/components/admin/settings/MailboxPolicyForm.tsx +4 -4
- package/apps/shared/components/admin/settings/PluginsManager.tsx +5 -5
- package/apps/shared/components/admin/settings/RetentionPolicyForm.tsx +5 -5
- package/apps/shared/components/admin/setup/EscrowSetupStep.tsx +7 -7
- package/apps/shared/components/admin/setup/SetupWizard.tsx +28 -24
- package/apps/shared/components/admin/signOut.ts +1 -1
- package/apps/shared/components/admin/usePagedList.tsx +2 -2
- package/apps/shared/components/calendar/AppointmentQuickForm.tsx +3 -3
- package/apps/shared/components/calendar/CalendarListSidebar.tsx +3 -3
- package/apps/shared/components/calendar/DescriptionEditor.tsx +1 -1
- package/apps/shared/components/calendar/EventDescriptionView.tsx +1 -1
- package/apps/shared/components/calendar/EventDetails.tsx +16 -14
- package/apps/shared/components/calendar/EventEditor.tsx +54 -39
- package/apps/shared/components/calendar/EventExpandedForm.tsx +3 -3
- package/apps/shared/components/calendar/EventFormParts.tsx +2 -2
- package/apps/shared/components/calendar/EventModal.tsx +5 -5
- package/apps/shared/components/calendar/EventQuickForm.tsx +3 -3
- package/apps/shared/components/calendar/EventShell.tsx +1 -1
- package/apps/shared/components/calendar/FindATime.tsx +6 -4
- package/apps/shared/components/calendar/GuestInput.tsx +2 -2
- package/apps/shared/components/calendar/MonthView.tsx +2 -2
- package/apps/shared/components/calendar/QuickCreateFaces.tsx +1 -1
- package/apps/shared/components/calendar/QuickFaceFrame.tsx +1 -1
- package/apps/shared/components/calendar/RecurrenceEditor.tsx +2 -2
- package/apps/shared/components/calendar/RequestChangeForm.tsx +8 -6
- package/apps/shared/components/calendar/ResourcePicker.tsx +7 -5
- package/apps/shared/components/calendar/SplitDayView.tsx +1 -1
- package/apps/shared/components/calendar/TaskQuickForm.tsx +23 -18
- package/apps/shared/components/calendar/TimeGridView.tsx +5 -3
- package/apps/shared/components/calendar/allDay.ts +2 -2
- package/apps/shared/components/calendar/eventDialogFields.ts +3 -3
- package/apps/shared/components/calendar/eventForm.ts +3 -3
- package/apps/shared/components/calendar/eventFormat.ts +3 -3
- package/apps/shared/components/calendar/findTimeGrid.ts +2 -2
- package/apps/shared/components/calendar/layout/CalendarShell.tsx +11 -9
- package/apps/shared/components/contacts/ContactDetailPane.tsx +4 -4
- package/apps/shared/components/contacts/ContactForm.tsx +27 -17
- package/apps/shared/components/contacts/ContactsSidebar.tsx +7 -5
- package/apps/shared/components/contacts/KeyChangeReview.tsx +5 -5
- package/apps/shared/components/contacts/contactKeys.ts +3 -3
- package/apps/shared/components/contacts/layout/ContactsShell.tsx +9 -7
- package/apps/shared/components/escrow/layout/EscrowShell.tsx +6 -6
- package/apps/shared/components/forms/StringListField.tsx +1 -1
- package/apps/shared/components/layout/AppShell.tsx +12 -10
- package/apps/shared/components/layout/BrandingChrome.tsx +1 -1
- package/apps/shared/components/layout/KeyEnrollmentGate.tsx +9 -9
- package/apps/shared/components/layout/MailboxProvisioning.tsx +8 -6
- package/apps/shared/components/layout/RecoveryCodeUnlock.tsx +9 -9
- package/apps/shared/components/layout/ThemeSwitch.tsx +1 -1
- package/apps/shared/components/layout/UnlockPromptProvider.tsx +6 -6
- package/apps/shared/components/layout/UserMenu.tsx +6 -4
- package/apps/shared/components/mail/ConversationList.tsx +25 -10
- package/apps/shared/components/mail/ConversationThreadPane.tsx +33 -17
- package/apps/shared/components/mail/InviteCard.tsx +11 -9
- package/apps/shared/components/mail/LazyReadingPane.tsx +2 -2
- package/apps/shared/components/mail/MailAddress.tsx +1 -1
- package/apps/shared/components/mail/MailListToolbar.tsx +2 -2
- package/apps/shared/components/mail/MailSelectionBar.tsx +2 -2
- package/apps/shared/components/mail/MenuButton.tsx +1 -1
- package/apps/shared/components/mail/MessageDetailPane.tsx +69 -48
- package/apps/shared/components/mail/MoveToFolderDialog.tsx +8 -6
- package/apps/shared/components/mail/OutboxRowStatus.tsx +1 -1
- package/apps/shared/components/mail/PermanentDeleteDialog.tsx +2 -2
- package/apps/shared/components/mail/compose/ComposeContext.tsx +14 -3
- package/apps/shared/components/mail/compose/ComposeWindow.tsx +34 -30
- package/apps/shared/components/mail/compose/ComposeWindowPlaceholder.tsx +4 -4
- package/apps/shared/components/mail/compose/EmojiPicker.tsx +2 -2
- package/apps/shared/components/mail/compose/GifPicker.tsx +3 -3
- package/apps/shared/components/mail/compose/RecipientInput.tsx +1 -1
- package/apps/shared/components/mail/compose/ScheduleSendPicker.tsx +1 -1
- package/apps/shared/components/mail/compose/encryptionRequirement.ts +2 -2
- package/apps/shared/components/mail/compose/quotedBody.ts +5 -5
- package/apps/shared/components/mail/compose/recipients.ts +1 -1
- package/apps/shared/components/mail/invite/InviteRowChip.tsx +10 -14
- package/apps/shared/components/mail/invite/InviteRsvpPopover.tsx +11 -9
- package/apps/shared/components/mail/invite/InviteTimeline.tsx +1 -1
- package/apps/shared/components/mail/invite/ProposeTimeForm.tsx +2 -2
- package/apps/shared/components/mail/invite/inviteFormat.ts +2 -2
- package/apps/shared/components/mail/invite/inviteStore.ts +14 -6
- package/apps/shared/components/mail/labelMenu.tsx +9 -7
- package/apps/shared/components/mail/layout/MailShell.tsx +4 -4
- package/apps/shared/components/mail/listPreferences.ts +2 -2
- package/apps/shared/components/mail/pinnedSigners.ts +45 -19
- package/apps/shared/components/mail/reading/EncryptedBody.tsx +2 -2
- package/apps/shared/components/mail/reading/MessageBody.tsx +6 -6
- package/apps/shared/components/mail/reading/MessageCard.tsx +3 -3
- package/apps/shared/components/mail/reading/MessageSourceDialog.tsx +3 -3
- package/apps/shared/components/mail/reading/PendingMessageCard.tsx +1 -1
- package/apps/shared/components/mail/reading/bodyContent.ts +3 -3
- package/apps/shared/components/mail/reading/bodyHtml.ts +1 -1
- package/apps/shared/components/mail/reading/conversationPrint.ts +76 -0
- package/apps/shared/components/mail/reading/messageExport.ts +1 -1
- package/apps/shared/components/mail/reading/printMessage.ts +46 -9
- package/apps/shared/components/mail/reading/useMessageActions.ts +28 -21
- package/apps/shared/components/mail/unreadStyle.tsx +1 -1
- package/apps/shared/components/mail/verificationSeals.ts +16 -12
- package/apps/shared/components/mail/writableMailboxes.ts +14 -7
- package/apps/shared/components/rules/RuleBuilder.tsx +1 -1
- package/apps/shared/components/settings/SigningCertificateCard.tsx +4 -4
- package/apps/shared/components/settings/layout/SettingsShell.tsx +8 -6
- package/apps/shared/components/sharing/PrincipalListField.tsx +1 -1
- package/apps/shared/components/sharing/PrincipalPicker.tsx +1 -1
- package/apps/shared/components/sharing/PrincipalResolver.tsx +4 -4
- package/apps/shared/components/tasks/TasksSidebar.tsx +7 -5
- package/apps/shared/components/tasks/layout/TasksShell.tsx +9 -7
- package/apps/shared/keyboard/ShortcutsDialog.tsx +1 -1
- package/apps/shared/keyboard/keymap.ts +1 -0
- package/apps/shared/mail/decryptedMessages.ts +116 -0
- package/apps/shared/mail/findWellKnownFolderUid.ts +6 -4
- package/apps/shared/mail/folderCounts.ts +8 -4
- package/apps/shared/mail/folderOfType.ts +5 -3
- package/apps/shared/mail/folderTree.ts +1 -1
- package/apps/shared/mail/listSnapshots.ts +2 -2
- package/apps/shared/mail/messageReadState.ts +6 -5
- package/apps/shared/mail/newMailNotifications.ts +2 -2
- package/apps/shared/mail/outbox/composeBridge.ts +2 -2
- package/apps/shared/mail/outbox/outboxState.ts +1 -1
- package/apps/shared/mail/outbox/outgoingReplies.ts +2 -2
- package/apps/shared/mail/outbox/sendDecision.ts +2 -2
- package/apps/shared/mail/outbox/sendJob.ts +40 -35
- package/apps/shared/mail/outbox/sendOutcomes.ts +20 -15
- package/apps/shared/mail/outbox/useOutboxStatus.ts +5 -3
- package/apps/shared/mail/permanentDelete.ts +8 -7
- package/apps/shared/mail/primaryMailbox.ts +1 -1
- package/apps/shared/mail/reportNotices.ts +1 -1
- package/apps/shared/mail/senderBlocking.ts +36 -20
- package/apps/shared/mail/useMailConnection.ts +12 -10
- package/apps/shared/mail/useMailLiveUpdates.ts +3 -3
- package/apps/shared/mail/useMailboxUpdateAccess.ts +35 -11
- package/apps/shared/mail/useMarkMessageRead.ts +14 -7
- package/apps/shared/mail/useNewMailNotifications.ts +1 -1
- package/apps/shared/mail/usePermanentDelete.tsx +5 -3
- package/apps/shared/navigation/pageTitle.ts +1 -1
- package/apps/shared/notifications/NotificationCenter.tsx +1 -1
- package/apps/shared/notifications/NotificationHistoryDialog.tsx +2 -2
- package/apps/shared/notifications/apiErrors.ts +2 -2
- package/apps/shared/notifications/pushStatus.ts +1 -1
- package/apps/shared/notifications/systemErrors.ts +1 -1
- package/apps/shared/search/LocalIndexLifecycle.tsx +18 -12
- package/apps/shared/search/crossMailboxSearch.ts +3 -3
- package/apps/shared/search/localIndexBuilder.ts +24 -12
- package/apps/shared/search/localIndexKey.ts +1 -1
- package/apps/shared/search/localIndexRpcClient.ts +150 -30
- package/apps/shared/search/localIndexTransport.ts +84 -0
- package/apps/shared/search/localIndexWorker.ts +1 -1
- package/apps/shared/search/searchTier2.ts +3 -3
- package/apps/shared/signing/enrollmentTracker.ts +3 -3
- package/apps/shared/signing/enrollmentView.ts +1 -1
- package/apps/shared/signing/signingInfo.ts +1 -1
- package/apps/shared/signing/useSigningEnrollmentWatcher.ts +6 -4
- package/apps/shared/styles/app.css +14 -23
- package/apps/www/_layout.tsx +2 -2
- package/apps/www/calendar/index.tsx +20 -18
- package/apps/www/contacts/[uid].tsx +8 -6
- package/apps/www/contacts/index.tsx +19 -17
- package/apps/www/index.tsx +68 -48
- package/apps/www/messages/[uid].tsx +11 -9
- package/apps/www/settings/auto-reply/index.tsx +6 -4
- package/apps/www/settings/blocked-senders/index.tsx +9 -7
- package/apps/www/settings/encryption/index.tsx +38 -32
- package/apps/www/settings/filters/[uid].tsx +19 -14
- package/apps/www/settings/filters/_mailFilterRuleConfig.tsx +2 -2
- package/apps/www/settings/filters/index.tsx +4 -4
- package/apps/www/settings/filters/new/index.tsx +10 -8
- package/apps/www/settings/labels/index.tsx +12 -10
- package/apps/www/settings/privacy/index.tsx +18 -14
- package/apps/www/settings/profile/index.tsx +16 -11
- package/apps/www/settings/read-receipts/index.tsx +17 -12
- package/apps/www/settings/sharing/index.tsx +6 -6
- package/apps/www/settings/signatures/[uid].tsx +5 -5
- package/apps/www/settings/signatures/index.tsx +4 -4
- package/apps/www/settings/signatures/new/index.tsx +4 -4
- package/apps/www/settings/signatures/signatureDefaults.ts +1 -1
- package/apps/www/tasks/index.tsx +28 -23
- package/dist/apps/admin/_layout.d.ts +1 -1
- package/dist/apps/admin/_layout.js +1 -1
- package/dist/apps/admin/audit-log/index.d.ts +1 -1
- package/dist/apps/admin/audit-log/index.js +4 -4
- package/dist/apps/admin/branding/index.js +3 -3
- package/dist/apps/admin/data-requests/index.js +8 -8
- package/dist/apps/admin/distribution-lists/[uid].js +3 -3
- package/dist/apps/admin/distribution-lists/index.js +4 -4
- package/dist/apps/admin/distribution-lists/new/index.js +5 -5
- package/dist/apps/admin/domains/[uid].js +6 -6
- package/dist/apps/admin/domains/index.js +4 -4
- package/dist/apps/admin/domains/new/index.js +5 -5
- package/dist/apps/admin/encryption-policy/index.js +1 -1
- package/dist/apps/admin/escrow-scopes/[uid].d.ts +1 -1
- package/dist/apps/admin/escrow-scopes/[uid].js +7 -7
- package/dist/apps/admin/escrow-scopes/index.js +4 -4
- package/dist/apps/admin/escrow-scopes/new/index.js +5 -5
- package/dist/apps/admin/index.js +6 -6
- package/dist/apps/admin/ingest-queue/index.js +4 -4
- package/dist/apps/admin/mailbox-policy/index.js +1 -1
- package/dist/apps/admin/mailboxes/[uid].js +5 -5
- package/dist/apps/admin/quarantine/index.js +5 -5
- package/dist/apps/admin/retention-policy/index.js +3 -3
- package/dist/apps/admin/signing-certificates/index.js +5 -5
- package/dist/apps/admin/transport-rules/[uid].js +5 -5
- package/dist/apps/admin/transport-rules/_transportRuleConfig.d.ts +1 -1
- package/dist/apps/admin/transport-rules/_transportRuleConfig.js +2 -2
- package/dist/apps/admin/transport-rules/index.js +4 -4
- package/dist/apps/admin/transport-rules/new/index.js +5 -5
- package/dist/apps/escrow/_layout.d.ts +1 -1
- package/dist/apps/escrow/audit-log/index.d.ts +1 -1
- package/dist/apps/escrow/audit-log/index.js +4 -4
- package/dist/apps/escrow/index.js +4 -4
- package/dist/apps/escrow/matters/[uid].js +10 -10
- package/dist/apps/escrow/matters/new/index.js +6 -6
- package/dist/apps/shared/appearance/AppearanceForm.js +3 -3
- package/dist/apps/shared/appearance/AppearanceHead.js +1 -1
- package/dist/apps/shared/appearance/AppearanceProvider.d.ts +1 -1
- package/dist/apps/shared/appearance/AppearanceProvider.js +3 -3
- package/dist/apps/shared/appearance/appearanceCache.d.ts +1 -1
- package/dist/apps/shared/appearance/appearanceCache.js +1 -1
- package/dist/apps/shared/appearance/appearanceContext.d.ts +1 -1
- package/dist/apps/shared/appearance/theme.d.ts +1 -1
- package/dist/apps/shared/auth/adminAccess.js +1 -1
- package/dist/apps/shared/calendar/bookingPlugin.js +1 -1
- package/dist/apps/shared/calendar/calendarLiveUpdates.d.ts +1 -1
- package/dist/apps/shared/calendar/calendarReminders.d.ts +1 -1
- package/dist/apps/shared/calendar/useCalendarReminders.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/DiagnosticsManager.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/InstalledPlugins.d.ts +1 -1
- package/dist/apps/shared/components/admin/diagnostics/InstalledPlugins.js +2 -2
- package/dist/apps/shared/components/admin/diagnostics/LogsPanel.js +2 -2
- package/dist/apps/shared/components/admin/diagnostics/PackagesTable.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/RuntimePanel.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/SystemPanel.js +2 -2
- package/dist/apps/shared/components/admin/diagnostics/VersionsPanel.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/diagnosticsApi.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/format.js +1 -1
- package/dist/apps/shared/components/admin/diagnostics/logClient.js +1 -1
- package/dist/apps/shared/components/admin/distributionLists/MemberListCard.d.ts +1 -1
- package/dist/apps/shared/components/admin/distributionLists/MemberListCard.js +4 -4
- package/dist/apps/shared/components/admin/elevation.js +1 -1
- package/dist/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.js +3 -3
- package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +1 -1
- package/dist/apps/shared/components/admin/layout/AdminShell.js +7 -7
- package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.d.ts +1 -1
- package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.js +6 -6
- package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.d.ts +1 -1
- package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.js +10 -8
- package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.js +4 -4
- package/dist/apps/shared/components/admin/mailboxes/MailboxTable.d.ts +1 -1
- package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.d.ts +1 -1
- package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.js +7 -5
- package/dist/apps/shared/components/admin/mailboxes/ShareAccessCard.js +5 -5
- package/dist/apps/shared/components/admin/settings/BrandingForm.d.ts +1 -1
- package/dist/apps/shared/components/admin/settings/BrandingForm.js +5 -5
- package/dist/apps/shared/components/admin/settings/DomainDnsSetup.d.ts +1 -1
- package/dist/apps/shared/components/admin/settings/DomainDnsSetup.js +5 -5
- package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.d.ts +1 -1
- package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.js +4 -4
- package/dist/apps/shared/components/admin/settings/LoadedSettingsForm.js +2 -2
- package/dist/apps/shared/components/admin/settings/MailboxCreateForm.d.ts +1 -1
- package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +14 -12
- package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.d.ts +1 -1
- package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.js +4 -4
- package/dist/apps/shared/components/admin/settings/PluginsManager.js +5 -5
- package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.d.ts +1 -1
- package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.js +5 -5
- package/dist/apps/shared/components/admin/setup/EscrowSetupStep.js +7 -7
- package/dist/apps/shared/components/admin/setup/SetupWizard.d.ts +4 -4
- package/dist/apps/shared/components/admin/setup/SetupWizard.js +27 -23
- package/dist/apps/shared/components/admin/signOut.js +1 -1
- package/dist/apps/shared/components/admin/usePagedList.js +2 -2
- package/dist/apps/shared/components/calendar/AppointmentQuickForm.js +3 -3
- package/dist/apps/shared/components/calendar/CalendarListSidebar.d.ts +1 -1
- package/dist/apps/shared/components/calendar/CalendarListSidebar.js +2 -2
- package/dist/apps/shared/components/calendar/DescriptionEditor.js +1 -1
- package/dist/apps/shared/components/calendar/EventDescriptionView.js +1 -1
- package/dist/apps/shared/components/calendar/EventDetails.d.ts +2 -2
- package/dist/apps/shared/components/calendar/EventDetails.js +16 -14
- package/dist/apps/shared/components/calendar/EventEditor.d.ts +2 -2
- package/dist/apps/shared/components/calendar/EventEditor.js +22 -20
- package/dist/apps/shared/components/calendar/EventExpandedForm.js +2 -2
- package/dist/apps/shared/components/calendar/EventFormParts.d.ts +1 -1
- package/dist/apps/shared/components/calendar/EventFormParts.js +1 -1
- package/dist/apps/shared/components/calendar/EventModal.d.ts +2 -2
- package/dist/apps/shared/components/calendar/EventModal.js +3 -3
- package/dist/apps/shared/components/calendar/EventQuickForm.js +3 -3
- package/dist/apps/shared/components/calendar/EventShell.js +1 -1
- package/dist/apps/shared/components/calendar/FindATime.js +6 -4
- package/dist/apps/shared/components/calendar/GuestInput.d.ts +2 -2
- package/dist/apps/shared/components/calendar/MonthView.d.ts +1 -1
- package/dist/apps/shared/components/calendar/MonthView.js +1 -1
- package/dist/apps/shared/components/calendar/QuickCreateFaces.js +1 -1
- package/dist/apps/shared/components/calendar/QuickFaceFrame.js +1 -1
- package/dist/apps/shared/components/calendar/RecurrenceEditor.d.ts +1 -1
- package/dist/apps/shared/components/calendar/RecurrenceEditor.js +1 -1
- package/dist/apps/shared/components/calendar/RequestChangeForm.js +8 -6
- package/dist/apps/shared/components/calendar/ResourcePicker.d.ts +1 -1
- package/dist/apps/shared/components/calendar/ResourcePicker.js +7 -5
- package/dist/apps/shared/components/calendar/SplitDayView.d.ts +1 -1
- package/dist/apps/shared/components/calendar/TaskQuickForm.d.ts +1 -1
- package/dist/apps/shared/components/calendar/TaskQuickForm.js +9 -7
- package/dist/apps/shared/components/calendar/TimeGridView.d.ts +1 -1
- package/dist/apps/shared/components/calendar/TimeGridView.js +2 -2
- package/dist/apps/shared/components/calendar/allDay.d.ts +2 -2
- package/dist/apps/shared/components/calendar/allDay.js +1 -1
- package/dist/apps/shared/components/calendar/eventDialogFields.d.ts +2 -2
- package/dist/apps/shared/components/calendar/eventDialogFields.js +2 -2
- package/dist/apps/shared/components/calendar/eventForm.d.ts +3 -3
- package/dist/apps/shared/components/calendar/eventFormat.d.ts +1 -1
- package/dist/apps/shared/components/calendar/eventFormat.js +2 -2
- package/dist/apps/shared/components/calendar/findTimeGrid.d.ts +1 -1
- package/dist/apps/shared/components/calendar/findTimeGrid.js +1 -1
- package/dist/apps/shared/components/calendar/layout/CalendarShell.d.ts +1 -1
- package/dist/apps/shared/components/calendar/layout/CalendarShell.js +11 -9
- package/dist/apps/shared/components/contacts/ContactDetailPane.d.ts +1 -1
- package/dist/apps/shared/components/contacts/ContactDetailPane.js +2 -2
- package/dist/apps/shared/components/contacts/ContactForm.d.ts +2 -2
- package/dist/apps/shared/components/contacts/ContactForm.js +12 -8
- package/dist/apps/shared/components/contacts/ContactsSidebar.d.ts +1 -1
- package/dist/apps/shared/components/contacts/ContactsSidebar.js +7 -5
- package/dist/apps/shared/components/contacts/KeyChangeReview.d.ts +1 -1
- package/dist/apps/shared/components/contacts/KeyChangeReview.js +5 -5
- package/dist/apps/shared/components/contacts/contactKeys.d.ts +2 -2
- package/dist/apps/shared/components/contacts/contactKeys.js +2 -2
- package/dist/apps/shared/components/contacts/layout/ContactsShell.d.ts +1 -1
- package/dist/apps/shared/components/contacts/layout/ContactsShell.js +9 -7
- package/dist/apps/shared/components/escrow/layout/EscrowShell.js +6 -6
- package/dist/apps/shared/components/forms/StringListField.js +1 -1
- package/dist/apps/shared/components/layout/AppShell.d.ts +2 -2
- package/dist/apps/shared/components/layout/AppShell.js +11 -9
- package/dist/apps/shared/components/layout/BrandingChrome.d.ts +1 -1
- package/dist/apps/shared/components/layout/KeyEnrollmentGate.d.ts +1 -1
- package/dist/apps/shared/components/layout/KeyEnrollmentGate.js +9 -9
- package/dist/apps/shared/components/layout/MailboxProvisioning.js +8 -6
- package/dist/apps/shared/components/layout/RecoveryCodeUnlock.d.ts +1 -1
- package/dist/apps/shared/components/layout/RecoveryCodeUnlock.js +9 -9
- package/dist/apps/shared/components/layout/UnlockPromptProvider.d.ts +2 -2
- package/dist/apps/shared/components/layout/UnlockPromptProvider.js +5 -5
- package/dist/apps/shared/components/layout/UserMenu.js +6 -4
- package/dist/apps/shared/components/mail/ConversationList.d.ts +2 -2
- package/dist/apps/shared/components/mail/ConversationList.js +23 -8
- package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +3 -3
- package/dist/apps/shared/components/mail/ConversationThreadPane.js +19 -13
- package/dist/apps/shared/components/mail/InviteCard.js +10 -8
- package/dist/apps/shared/components/mail/LazyReadingPane.js +2 -2
- package/dist/apps/shared/components/mail/MailAddress.d.ts +1 -1
- package/dist/apps/shared/components/mail/MailAddress.js +1 -1
- package/dist/apps/shared/components/mail/MailListToolbar.d.ts +2 -2
- package/dist/apps/shared/components/mail/MailSelectionBar.d.ts +2 -2
- package/dist/apps/shared/components/mail/MenuButton.js +1 -1
- package/dist/apps/shared/components/mail/MessageDetailPane.d.ts +3 -3
- package/dist/apps/shared/components/mail/MessageDetailPane.js +61 -46
- package/dist/apps/shared/components/mail/MoveToFolderDialog.d.ts +1 -1
- package/dist/apps/shared/components/mail/MoveToFolderDialog.js +8 -6
- package/dist/apps/shared/components/mail/OutboxRowStatus.d.ts +1 -1
- package/dist/apps/shared/components/mail/PermanentDeleteDialog.js +2 -2
- package/dist/apps/shared/components/mail/compose/ComposeContext.d.ts +10 -1
- package/dist/apps/shared/components/mail/compose/ComposeContext.js +4 -2
- package/dist/apps/shared/components/mail/compose/ComposeWindow.js +34 -30
- package/dist/apps/shared/components/mail/compose/ComposeWindowPlaceholder.js +4 -4
- package/dist/apps/shared/components/mail/compose/EmojiPicker.js +2 -2
- package/dist/apps/shared/components/mail/compose/GifPicker.js +3 -3
- package/dist/apps/shared/components/mail/compose/RecipientInput.d.ts +1 -1
- package/dist/apps/shared/components/mail/compose/RecipientInput.js +1 -1
- package/dist/apps/shared/components/mail/compose/ScheduleSendPicker.js +1 -1
- package/dist/apps/shared/components/mail/compose/encryptionRequirement.d.ts +2 -2
- package/dist/apps/shared/components/mail/compose/encryptionRequirement.js +1 -1
- package/dist/apps/shared/components/mail/compose/quotedBody.d.ts +3 -3
- package/dist/apps/shared/components/mail/compose/quotedBody.js +3 -3
- package/dist/apps/shared/components/mail/compose/recipients.d.ts +1 -1
- package/dist/apps/shared/components/mail/invite/InviteRowChip.d.ts +3 -3
- package/dist/apps/shared/components/mail/invite/InviteRowChip.js +7 -9
- package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.d.ts +2 -2
- package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.js +11 -9
- package/dist/apps/shared/components/mail/invite/InviteTimeline.d.ts +1 -1
- package/dist/apps/shared/components/mail/invite/ProposeTimeForm.d.ts +1 -1
- package/dist/apps/shared/components/mail/invite/ProposeTimeForm.js +1 -1
- package/dist/apps/shared/components/mail/invite/inviteFormat.d.ts +2 -2
- package/dist/apps/shared/components/mail/invite/inviteStore.d.ts +9 -3
- package/dist/apps/shared/components/mail/invite/inviteStore.js +13 -6
- package/dist/apps/shared/components/mail/labelMenu.d.ts +1 -1
- package/dist/apps/shared/components/mail/labelMenu.js +9 -7
- package/dist/apps/shared/components/mail/layout/MailShell.d.ts +1 -1
- package/dist/apps/shared/components/mail/layout/MailShell.js +3 -3
- package/dist/apps/shared/components/mail/listPreferences.d.ts +2 -2
- package/dist/apps/shared/components/mail/listPreferences.js +1 -1
- package/dist/apps/shared/components/mail/pinnedSigners.d.ts +12 -5
- package/dist/apps/shared/components/mail/pinnedSigners.js +37 -18
- package/dist/apps/shared/components/mail/reading/EncryptedBody.js +2 -2
- package/dist/apps/shared/components/mail/reading/MessageBody.d.ts +2 -2
- package/dist/apps/shared/components/mail/reading/MessageBody.js +4 -4
- package/dist/apps/shared/components/mail/reading/MessageCard.d.ts +1 -1
- package/dist/apps/shared/components/mail/reading/MessageCard.js +2 -2
- package/dist/apps/shared/components/mail/reading/MessageSourceDialog.js +3 -3
- package/dist/apps/shared/components/mail/reading/PendingMessageCard.js +1 -1
- package/dist/apps/shared/components/mail/reading/bodyContent.d.ts +2 -2
- package/dist/apps/shared/components/mail/reading/bodyContent.js +2 -2
- package/dist/apps/shared/components/mail/reading/bodyHtml.js +1 -1
- package/dist/apps/shared/components/mail/reading/conversationPrint.d.ts +15 -0
- package/dist/apps/shared/components/mail/reading/conversationPrint.js +69 -0
- package/dist/apps/shared/components/mail/reading/messageExport.js +1 -1
- package/dist/apps/shared/components/mail/reading/printMessage.d.ts +9 -3
- package/dist/apps/shared/components/mail/reading/printMessage.js +33 -6
- package/dist/apps/shared/components/mail/reading/useMessageActions.d.ts +1 -1
- package/dist/apps/shared/components/mail/reading/useMessageActions.js +18 -16
- package/dist/apps/shared/components/mail/unreadStyle.d.ts +1 -1
- package/dist/apps/shared/components/mail/verificationSeals.d.ts +27 -6
- package/dist/apps/shared/components/mail/verificationSeals.js +15 -11
- package/dist/apps/shared/components/mail/writableMailboxes.d.ts +8 -3
- package/dist/apps/shared/components/mail/writableMailboxes.js +12 -6
- package/dist/apps/shared/components/rules/RuleBuilder.js +1 -1
- package/dist/apps/shared/components/settings/SigningCertificateCard.d.ts +1 -1
- package/dist/apps/shared/components/settings/SigningCertificateCard.js +3 -3
- package/dist/apps/shared/components/settings/layout/SettingsShell.d.ts +1 -1
- package/dist/apps/shared/components/settings/layout/SettingsShell.js +8 -6
- package/dist/apps/shared/components/sharing/PrincipalListField.d.ts +1 -1
- package/dist/apps/shared/components/sharing/PrincipalPicker.d.ts +1 -1
- package/dist/apps/shared/components/sharing/PrincipalPicker.js +1 -1
- package/dist/apps/shared/components/sharing/PrincipalResolver.d.ts +1 -1
- package/dist/apps/shared/components/sharing/PrincipalResolver.js +3 -3
- package/dist/apps/shared/components/tasks/TasksSidebar.d.ts +1 -1
- package/dist/apps/shared/components/tasks/TasksSidebar.js +7 -5
- package/dist/apps/shared/components/tasks/layout/TasksShell.d.ts +1 -1
- package/dist/apps/shared/components/tasks/layout/TasksShell.js +9 -7
- package/dist/apps/shared/keyboard/ShortcutsDialog.js +1 -1
- package/dist/apps/shared/keyboard/keymap.d.ts +6 -0
- package/dist/apps/shared/keyboard/keymap.js +1 -0
- package/dist/apps/shared/mail/decryptedMessages.d.ts +27 -0
- package/dist/apps/shared/mail/decryptedMessages.js +97 -0
- package/dist/apps/shared/mail/findWellKnownFolderUid.d.ts +5 -3
- package/dist/apps/shared/mail/findWellKnownFolderUid.js +5 -4
- package/dist/apps/shared/mail/folderCounts.d.ts +1 -1
- package/dist/apps/shared/mail/folderCounts.js +6 -4
- package/dist/apps/shared/mail/folderOfType.d.ts +3 -2
- package/dist/apps/shared/mail/folderOfType.js +4 -4
- package/dist/apps/shared/mail/folderTree.d.ts +1 -1
- package/dist/apps/shared/mail/listSnapshots.d.ts +2 -2
- package/dist/apps/shared/mail/messageReadState.d.ts +4 -3
- package/dist/apps/shared/mail/messageReadState.js +5 -5
- package/dist/apps/shared/mail/newMailNotifications.d.ts +1 -1
- package/dist/apps/shared/mail/newMailNotifications.js +1 -1
- package/dist/apps/shared/mail/outbox/composeBridge.d.ts +2 -2
- package/dist/apps/shared/mail/outbox/outboxState.d.ts +1 -1
- package/dist/apps/shared/mail/outbox/outgoingReplies.d.ts +2 -2
- package/dist/apps/shared/mail/outbox/sendDecision.d.ts +2 -2
- package/dist/apps/shared/mail/outbox/sendDecision.js +1 -1
- package/dist/apps/shared/mail/outbox/sendJob.d.ts +10 -6
- package/dist/apps/shared/mail/outbox/sendJob.js +39 -35
- package/dist/apps/shared/mail/outbox/sendOutcomes.d.ts +6 -3
- package/dist/apps/shared/mail/outbox/sendOutcomes.js +19 -15
- package/dist/apps/shared/mail/outbox/useOutboxStatus.js +5 -3
- package/dist/apps/shared/mail/permanentDelete.d.ts +4 -3
- package/dist/apps/shared/mail/permanentDelete.js +8 -8
- package/dist/apps/shared/mail/primaryMailbox.d.ts +1 -1
- package/dist/apps/shared/mail/primaryMailbox.js +1 -1
- package/dist/apps/shared/mail/reportNotices.d.ts +1 -1
- package/dist/apps/shared/mail/senderBlocking.d.ts +5 -4
- package/dist/apps/shared/mail/senderBlocking.js +19 -16
- package/dist/apps/shared/mail/useMailConnection.d.ts +1 -1
- package/dist/apps/shared/mail/useMailConnection.js +12 -10
- package/dist/apps/shared/mail/useMailLiveUpdates.d.ts +2 -2
- package/dist/apps/shared/mail/useMailLiveUpdates.js +2 -2
- package/dist/apps/shared/mail/useMailboxUpdateAccess.d.ts +3 -2
- package/dist/apps/shared/mail/useMailboxUpdateAccess.js +31 -10
- package/dist/apps/shared/mail/useMarkMessageRead.d.ts +1 -1
- package/dist/apps/shared/mail/useMarkMessageRead.js +5 -3
- package/dist/apps/shared/mail/useNewMailNotifications.d.ts +1 -1
- package/dist/apps/shared/mail/usePermanentDelete.d.ts +1 -1
- package/dist/apps/shared/mail/usePermanentDelete.js +4 -2
- package/dist/apps/shared/navigation/pageTitle.d.ts +1 -1
- package/dist/apps/shared/notifications/NotificationCenter.js +1 -1
- package/dist/apps/shared/notifications/NotificationHistoryDialog.js +2 -2
- package/dist/apps/shared/notifications/apiErrors.js +2 -2
- package/dist/apps/shared/notifications/pushStatus.js +1 -1
- package/dist/apps/shared/notifications/systemErrors.js +1 -1
- package/dist/apps/shared/search/LocalIndexLifecycle.d.ts +2 -2
- package/dist/apps/shared/search/LocalIndexLifecycle.js +15 -10
- package/dist/apps/shared/search/crossMailboxSearch.d.ts +1 -1
- package/dist/apps/shared/search/crossMailboxSearch.js +2 -2
- package/dist/apps/shared/search/localIndexBuilder.d.ts +4 -3
- package/dist/apps/shared/search/localIndexBuilder.js +15 -12
- package/dist/apps/shared/search/localIndexKey.js +1 -1
- package/dist/apps/shared/search/localIndexRpcClient.d.ts +43 -31
- package/dist/apps/shared/search/localIndexRpcClient.js +113 -20
- package/dist/apps/shared/search/localIndexTransport.d.ts +77 -0
- package/dist/apps/shared/search/localIndexTransport.js +1 -0
- package/dist/apps/shared/search/localIndexWorker.d.ts +1 -1
- package/dist/apps/shared/search/searchTier2.d.ts +3 -3
- package/dist/apps/shared/signing/enrollmentTracker.d.ts +1 -1
- package/dist/apps/shared/signing/enrollmentTracker.js +3 -3
- package/dist/apps/shared/signing/enrollmentView.d.ts +1 -1
- package/dist/apps/shared/signing/signingInfo.d.ts +1 -1
- package/dist/apps/shared/signing/signingInfo.js +1 -1
- package/dist/apps/shared/signing/useSigningEnrollmentWatcher.d.ts +1 -1
- package/dist/apps/shared/signing/useSigningEnrollmentWatcher.js +5 -3
- package/dist/apps/shared/styles/app.css +14 -23
- package/dist/apps/www/_layout.d.ts +1 -1
- package/dist/apps/www/_layout.js +1 -1
- package/dist/apps/www/calendar/index.d.ts +1 -1
- package/dist/apps/www/calendar/index.js +20 -18
- package/dist/apps/www/contacts/[uid].d.ts +1 -1
- package/dist/apps/www/contacts/[uid].js +8 -6
- package/dist/apps/www/contacts/index.d.ts +1 -1
- package/dist/apps/www/contacts/index.js +19 -17
- package/dist/apps/www/index.d.ts +1 -1
- package/dist/apps/www/index.js +64 -50
- package/dist/apps/www/messages/[uid].d.ts +1 -1
- package/dist/apps/www/messages/[uid].js +11 -9
- package/dist/apps/www/settings/appearance/index.d.ts +1 -1
- package/dist/apps/www/settings/auto-reply/index.d.ts +1 -1
- package/dist/apps/www/settings/auto-reply/index.js +6 -4
- package/dist/apps/www/settings/blocked-senders/index.d.ts +1 -1
- package/dist/apps/www/settings/blocked-senders/index.js +6 -4
- package/dist/apps/www/settings/encryption/index.d.ts +1 -1
- package/dist/apps/www/settings/encryption/index.js +31 -29
- package/dist/apps/www/settings/filters/[uid].d.ts +1 -1
- package/dist/apps/www/settings/filters/[uid].js +11 -9
- package/dist/apps/www/settings/filters/_mailFilterRuleConfig.d.ts +2 -2
- package/dist/apps/www/settings/filters/index.d.ts +1 -1
- package/dist/apps/www/settings/filters/index.js +4 -4
- package/dist/apps/www/settings/filters/new/index.d.ts +1 -1
- package/dist/apps/www/settings/filters/new/index.js +10 -8
- package/dist/apps/www/settings/labels/index.d.ts +1 -1
- package/dist/apps/www/settings/labels/index.js +12 -10
- package/dist/apps/www/settings/privacy/index.d.ts +1 -1
- package/dist/apps/www/settings/privacy/index.js +18 -14
- package/dist/apps/www/settings/profile/index.d.ts +1 -1
- package/dist/apps/www/settings/profile/index.js +7 -5
- package/dist/apps/www/settings/read-receipts/index.d.ts +1 -1
- package/dist/apps/www/settings/read-receipts/index.js +5 -3
- package/dist/apps/www/settings/sharing/index.d.ts +1 -1
- package/dist/apps/www/settings/sharing/index.js +6 -6
- package/dist/apps/www/settings/signatures/[uid].d.ts +1 -1
- package/dist/apps/www/settings/signatures/[uid].js +5 -5
- package/dist/apps/www/settings/signatures/index.d.ts +1 -1
- package/dist/apps/www/settings/signatures/index.js +4 -4
- package/dist/apps/www/settings/signatures/new/index.d.ts +1 -1
- package/dist/apps/www/settings/signatures/new/index.js +4 -4
- package/dist/apps/www/settings/signatures/signatureDefaults.d.ts +1 -1
- package/dist/apps/www/settings/signatures/signatureDefaults.js +1 -1
- package/dist/apps/www/tasks/index.d.ts +1 -1
- package/dist/apps/www/tasks/index.js +17 -15
- package/dist/lib/admin/auditLogApi.d.ts +32 -0
- package/dist/lib/admin/auditLogApi.js +27 -0
- package/dist/lib/admin/distributionListsApi.d.ts +47 -0
- package/dist/lib/admin/distributionListsApi.js +34 -0
- package/dist/lib/admin/domainsApi.d.ts +75 -0
- package/dist/lib/admin/domainsApi.js +44 -0
- package/dist/lib/admin/escrowAccessRequestsApi.d.ts +79 -0
- package/dist/lib/admin/escrowAccessRequestsApi.js +46 -0
- package/dist/lib/admin/escrowAuditLogApi.d.ts +66 -0
- package/dist/lib/admin/escrowAuditLogApi.js +31 -0
- package/dist/lib/admin/escrowScopesApi.d.ts +78 -0
- package/dist/lib/admin/escrowScopesApi.js +50 -0
- package/dist/lib/admin/leftoverMailboxApi.d.ts +73 -0
- package/dist/lib/admin/leftoverMailboxApi.js +67 -0
- package/dist/lib/admin/mailboxPolicyApi.d.ts +27 -0
- package/dist/lib/admin/mailboxPolicyApi.js +21 -0
- package/dist/lib/admin/matterExportApi.d.ts +40 -0
- package/dist/lib/admin/matterExportApi.js +39 -0
- package/dist/lib/admin/matterSearchApi.d.ts +20 -0
- package/dist/lib/admin/matterSearchApi.js +27 -0
- package/dist/lib/admin/mattersApi.d.ts +56 -0
- package/dist/lib/admin/mattersApi.js +40 -0
- package/dist/lib/admin/pluginsApi.d.ts +265 -0
- package/dist/lib/admin/pluginsApi.js +102 -0
- package/dist/lib/admin/retentionPolicyApi.d.ts +32 -0
- package/dist/lib/admin/retentionPolicyApi.js +29 -0
- package/dist/lib/admin/setupApi.d.ts +23 -0
- package/dist/lib/admin/setupApi.js +26 -0
- package/dist/lib/admin/transportRulesApi.d.ts +66 -0
- package/dist/lib/admin/transportRulesApi.js +43 -0
- package/dist/lib/appearance/preferencesApi.d.ts +128 -0
- package/dist/lib/appearance/preferencesApi.js +257 -0
- package/dist/lib/auth/profileApi.d.ts +33 -0
- package/dist/lib/auth/profileApi.js +52 -0
- package/dist/lib/auth/session.d.ts +70 -0
- package/dist/lib/auth/session.js +210 -0
- package/dist/lib/branding/brandingApi.d.ts +47 -0
- package/dist/lib/branding/brandingApi.js +61 -0
- package/dist/lib/branding/useBranding.d.ts +23 -0
- package/dist/lib/branding/useBranding.js +65 -0
- package/dist/lib/calendar/calendarApi.d.ts +230 -0
- package/dist/lib/calendar/calendarApi.js +106 -0
- package/dist/lib/calendar/calendarColors.d.ts +18 -0
- package/dist/lib/calendar/calendarColors.js +39 -0
- package/dist/lib/calendar/calendarDragIds.d.ts +42 -0
- package/dist/lib/calendar/calendarDragIds.js +92 -0
- package/dist/lib/calendar/calendarMutations.d.ts +68 -0
- package/dist/lib/calendar/calendarMutations.js +190 -0
- package/dist/lib/calendar/eventDescription.d.ts +43 -0
- package/dist/lib/calendar/eventDescription.js +195 -0
- package/dist/lib/calendar/freeBusyApi.d.ts +100 -0
- package/dist/lib/calendar/freeBusyApi.js +119 -0
- package/dist/lib/calendar/inviteApi.d.ts +121 -0
- package/dist/lib/calendar/inviteApi.js +54 -0
- package/dist/lib/calendar/recurrence.d.ts +60 -0
- package/dist/lib/calendar/recurrence.js +225 -0
- package/dist/lib/components/avatar/ContactAvatar.d.ts +8 -0
- package/dist/lib/components/avatar/ContactAvatar.js +26 -0
- package/dist/lib/components/buttons/Button.d.ts +9 -0
- package/dist/lib/components/buttons/Button.js +14 -0
- package/dist/lib/components/buttons/CopyButton.d.ts +18 -0
- package/dist/lib/components/buttons/CopyButton.js +14 -0
- package/dist/lib/components/feedback/Alert.d.ts +4 -0
- package/dist/lib/components/feedback/Alert.js +4 -0
- package/dist/lib/components/feedback/Skeleton.d.ts +21 -0
- package/dist/lib/components/feedback/Skeleton.js +14 -0
- package/dist/lib/components/forms/FormField.d.ts +8 -0
- package/dist/lib/components/forms/FormField.js +5 -0
- package/dist/lib/components/navigation/BottomTabBar.d.ts +27 -0
- package/dist/lib/components/navigation/BottomTabBar.js +32 -0
- package/dist/lib/components/overlays/Drawer.d.ts +20 -0
- package/dist/lib/components/overlays/Drawer.js +27 -0
- package/dist/lib/components/overlays/Modal.d.ts +17 -0
- package/dist/lib/components/overlays/Modal.js +25 -0
- package/dist/lib/components/overlays/PopoverPortal.d.ts +23 -0
- package/dist/lib/components/overlays/PopoverPortal.js +53 -0
- package/dist/lib/components/overlays/overlayStack.d.ts +31 -0
- package/dist/lib/components/overlays/overlayStack.js +143 -0
- package/dist/lib/components/pickers/MiniDatePicker.d.ts +13 -0
- package/dist/lib/components/pickers/MiniDatePicker.js +42 -0
- package/dist/lib/contacts/contactsApi.d.ts +174 -0
- package/dist/lib/contacts/contactsApi.js +139 -0
- package/dist/lib/contacts/vcard.d.ts +23 -0
- package/dist/lib/contacts/vcard.js +179 -0
- package/dist/lib/crypto/composeSecurity.d.ts +67 -0
- package/dist/lib/crypto/composeSecurity.js +93 -0
- package/dist/lib/crypto/encoding.d.ts +9 -0
- package/dist/lib/crypto/encoding.js +32 -0
- package/dist/lib/crypto/escrowKeys.d.ts +25 -0
- package/dist/lib/crypto/escrowKeys.js +59 -0
- package/dist/lib/crypto/idleTimeout.d.ts +16 -0
- package/dist/lib/crypto/idleTimeout.js +47 -0
- package/dist/lib/crypto/keySession.d.ts +159 -0
- package/dist/lib/crypto/keySession.js +367 -0
- package/dist/lib/crypto/keys.d.ts +50 -0
- package/dist/lib/crypto/keys.js +89 -0
- package/dist/lib/crypto/keyvaultApi.d.ts +394 -0
- package/dist/lib/crypto/keyvaultApi.js +350 -0
- package/dist/lib/crypto/masterKey.d.ts +59 -0
- package/dist/lib/crypto/masterKey.js +104 -0
- package/dist/lib/crypto/masterKeyWraps.d.ts +108 -0
- package/dist/lib/crypto/masterKeyWraps.js +228 -0
- package/dist/lib/crypto/messageSecurity.d.ts +248 -0
- package/dist/lib/crypto/messageSecurity.js +367 -0
- package/dist/lib/crypto/mime.d.ts +143 -0
- package/dist/lib/crypto/mime.js +504 -0
- package/dist/lib/crypto/passkeyUnlock.d.ts +20 -0
- package/dist/lib/crypto/passkeyUnlock.js +79 -0
- package/dist/lib/crypto/passwordUnlock.d.ts +39 -0
- package/dist/lib/crypto/passwordUnlock.js +73 -0
- package/dist/lib/crypto/recoveryCode.d.ts +28 -0
- package/dist/lib/crypto/recoveryCode.js +86 -0
- package/dist/lib/crypto/signingProviderApi.d.ts +95 -0
- package/dist/lib/crypto/signingProviderApi.js +60 -0
- package/dist/lib/crypto/smime.d.ts +128 -0
- package/dist/lib/crypto/smime.js +402 -0
- package/dist/lib/crypto/smimeMessage.d.ts +132 -0
- package/dist/lib/crypto/smimeMessage.js +341 -0
- package/dist/lib/crypto/useIdleKeyTimeout.d.ts +10 -0
- package/dist/lib/crypto/useIdleKeyTimeout.js +163 -0
- package/dist/lib/crypto/verificationSeal.d.ts +56 -0
- package/dist/lib/crypto/verificationSeal.js +220 -0
- package/dist/lib/mail/compose/composeQuoting.d.ts +88 -0
- package/dist/lib/mail/compose/composeQuoting.js +204 -0
- package/dist/lib/mail/compose/emojiData.d.ts +9 -0
- package/dist/lib/mail/compose/emojiData.js +18 -0
- package/dist/lib/mail/compose/giphyApi.d.ts +17 -0
- package/dist/lib/mail/compose/giphyApi.js +20 -0
- package/dist/lib/mail/conversationsApi.d.ts +80 -0
- package/dist/lib/mail/conversationsApi.js +44 -0
- package/dist/lib/mail/dataExportApi.d.ts +50 -0
- package/dist/lib/mail/dataExportApi.js +40 -0
- package/dist/lib/mail/directoryApi.d.ts +49 -0
- package/dist/lib/mail/directoryApi.js +101 -0
- package/dist/lib/mail/erasureRequestApi.d.ts +45 -0
- package/dist/lib/mail/erasureRequestApi.js +43 -0
- package/dist/lib/mail/flaggedMessages.d.ts +22 -0
- package/dist/lib/mail/flaggedMessages.js +73 -0
- package/dist/lib/mail/focusedInboxOverridesApi.d.ts +37 -0
- package/dist/lib/mail/focusedInboxOverridesApi.js +34 -0
- package/dist/lib/mail/labelsApi.d.ts +47 -0
- package/dist/lib/mail/labelsApi.js +38 -0
- package/dist/lib/mail/mailAddress.d.ts +27 -0
- package/dist/lib/mail/mailAddress.js +54 -0
- package/dist/lib/mail/mailApi.d.ts +850 -0
- package/dist/lib/mail/mailApi.js +602 -0
- package/dist/lib/mail/mailDetailHooks.d.ts +10 -0
- package/dist/lib/mail/mailDetailHooks.js +53 -0
- package/dist/lib/mail/mailFilterRulesApi.d.ts +76 -0
- package/dist/lib/mail/mailFilterRulesApi.js +45 -0
- package/dist/lib/mail/mailSignaturesApi.d.ts +49 -0
- package/dist/lib/mail/mailSignaturesApi.js +42 -0
- package/dist/lib/mail/mailboxAccessApi.d.ts +74 -0
- package/dist/lib/mail/mailboxAccessApi.js +56 -0
- package/dist/lib/mail/mailboxImportApi.d.ts +53 -0
- package/dist/lib/mail/mailboxImportApi.js +51 -0
- package/dist/lib/mail/messageBodySanitizer.d.ts +16 -0
- package/dist/lib/mail/messageBodySanitizer.js +118 -0
- package/dist/lib/mail/pushClient.d.ts +106 -0
- package/dist/lib/mail/pushClient.js +317 -0
- package/dist/lib/mail/sendEvents.d.ts +33 -0
- package/dist/lib/mail/sendEvents.js +44 -0
- package/dist/lib/mail/sendFailure.d.ts +16 -0
- package/dist/lib/mail/sendFailure.js +86 -0
- package/dist/lib/mail/senderListsApi.d.ts +69 -0
- package/dist/lib/mail/senderListsApi.js +126 -0
- package/dist/lib/search/queryGrammar.d.ts +51 -0
- package/dist/lib/search/queryGrammar.js +111 -0
- package/dist/lib/search/searchApi.d.ts +100 -0
- package/dist/lib/search/searchApi.js +107 -0
- package/dist/lib/search/searchScoring.d.ts +34 -0
- package/dist/lib/search/searchScoring.js +44 -0
- package/dist/lib/search/searchTier3.d.ts +64 -0
- package/dist/lib/search/searchTier3.js +335 -0
- package/dist/lib/tasks/tasksApi.d.ts +85 -0
- package/dist/lib/tasks/tasksApi.js +55 -0
- package/dist/lib/util/api.d.ts +160 -0
- package/dist/lib/util/api.js +251 -0
- package/dist/lib/util/apiClientContext.d.ts +7 -0
- package/dist/lib/util/apiClientContext.js +32 -0
- package/dist/lib/util/apiQuery.d.ts +32 -0
- package/dist/lib/util/apiQuery.js +42 -0
- package/dist/lib/util/clipboard.d.ts +7 -0
- package/dist/lib/util/clipboard.js +56 -0
- package/dist/lib/util/dateInput.d.ts +6 -0
- package/dist/lib/util/dateInput.js +14 -0
- package/dist/lib/util/timeZone.d.ts +12 -0
- package/dist/lib/util/timeZone.js +32 -0
- package/dist/lib/util/useCopyToClipboard.d.ts +12 -0
- package/dist/lib/util/useCopyToClipboard.js +34 -0
- package/dist/lib/util/useIsMobile.d.ts +10 -0
- package/dist/lib/util/useIsMobile.js +29 -0
- package/dist/lib/videoconf/videoMeetingsApi.d.ts +116 -0
- package/dist/lib/videoconf/videoMeetingsApi.js +49 -0
- package/lib/admin/auditLogApi.ts +48 -0
- package/lib/admin/distributionListsApi.ts +77 -0
- package/lib/admin/domainsApi.ts +113 -0
- package/lib/admin/escrowAccessRequestsApi.ts +110 -0
- package/lib/admin/escrowAuditLogApi.ts +101 -0
- package/lib/admin/escrowScopesApi.ts +112 -0
- package/lib/admin/leftoverMailboxApi.ts +120 -0
- package/lib/admin/mailboxPolicyApi.ts +38 -0
- package/lib/admin/matterExportApi.ts +62 -0
- package/lib/admin/matterSearchApi.ts +35 -0
- package/lib/admin/mattersApi.ts +86 -0
- package/lib/admin/pluginsApi.ts +339 -0
- package/lib/admin/retentionPolicyApi.ts +46 -0
- package/lib/admin/setupApi.ts +40 -0
- package/lib/admin/transportRulesApi.ts +106 -0
- package/lib/appearance/preferencesApi.ts +335 -0
- package/lib/auth/profileApi.ts +77 -0
- package/lib/auth/session.ts +238 -0
- package/lib/branding/brandingApi.ts +97 -0
- package/lib/branding/useBranding.ts +81 -0
- package/lib/calendar/calendarApi.ts +309 -0
- package/lib/calendar/calendarColors.ts +45 -0
- package/lib/calendar/calendarDragIds.ts +112 -0
- package/lib/calendar/calendarMutations.ts +236 -0
- package/lib/calendar/eventDescription.ts +211 -0
- package/lib/calendar/freeBusyApi.ts +197 -0
- package/lib/calendar/inviteApi.ts +154 -0
- package/lib/calendar/recurrence.ts +285 -0
- package/lib/components/avatar/ContactAvatar.tsx +47 -0
- package/lib/components/buttons/Button.tsx +40 -0
- package/lib/components/buttons/CopyButton.tsx +45 -0
- package/lib/components/feedback/Alert.tsx +13 -0
- package/lib/components/feedback/Skeleton.tsx +38 -0
- package/lib/components/forms/FormField.tsx +23 -0
- package/lib/components/navigation/BottomTabBar.tsx +66 -0
- package/lib/components/overlays/Drawer.tsx +72 -0
- package/lib/components/overlays/Modal.tsx +64 -0
- package/lib/components/overlays/PopoverPortal.tsx +74 -0
- package/lib/components/overlays/overlayStack.ts +165 -0
- package/lib/components/pickers/MiniDatePicker.tsx +90 -0
- package/lib/contacts/contactsApi.ts +289 -0
- package/lib/contacts/vcard.ts +197 -0
- package/lib/crypto/composeSecurity.ts +140 -0
- package/lib/crypto/encoding.ts +36 -0
- package/lib/crypto/escrowKeys.ts +74 -0
- package/lib/crypto/idleTimeout.ts +49 -0
- package/lib/crypto/keySession.ts +483 -0
- package/lib/crypto/keys.ts +105 -0
- package/lib/crypto/keyvaultApi.ts +674 -0
- package/lib/crypto/masterKey.ts +134 -0
- package/lib/crypto/masterKeyWraps.ts +269 -0
- package/lib/crypto/messageSecurity.ts +600 -0
- package/lib/crypto/mime.ts +568 -0
- package/lib/crypto/passkeyUnlock.ts +103 -0
- package/lib/crypto/passwordUnlock.ts +98 -0
- package/lib/crypto/recoveryCode.ts +93 -0
- package/lib/crypto/signingProviderApi.ts +135 -0
- package/lib/crypto/smime.ts +459 -0
- package/lib/crypto/smimeMessage.ts +491 -0
- package/lib/crypto/useIdleKeyTimeout.ts +176 -0
- package/lib/crypto/verificationSeal.ts +288 -0
- package/lib/mail/compose/composeQuoting.ts +243 -0
- package/lib/mail/compose/emojiData.ts +34 -0
- package/lib/mail/compose/giphyApi.ts +31 -0
- package/lib/mail/conversationsApi.ts +123 -0
- package/lib/mail/dataExportApi.ts +73 -0
- package/lib/mail/directoryApi.ts +161 -0
- package/lib/mail/erasureRequestApi.ts +71 -0
- package/lib/mail/flaggedMessages.ts +80 -0
- package/lib/mail/focusedInboxOverridesApi.ts +64 -0
- package/lib/mail/labelsApi.ts +71 -0
- package/lib/mail/mailAddress.ts +76 -0
- package/lib/mail/mailApi.ts +1286 -0
- package/lib/mail/mailDetailHooks.ts +57 -0
- package/lib/mail/mailFilterRulesApi.ts +116 -0
- package/lib/mail/mailSignaturesApi.ts +84 -0
- package/lib/mail/mailboxAccessApi.ts +106 -0
- package/lib/mail/mailboxImportApi.ts +87 -0
- package/lib/mail/messageBodySanitizer.ts +129 -0
- package/lib/mail/pushClient.ts +375 -0
- package/lib/mail/sendEvents.ts +72 -0
- package/lib/mail/sendFailure.ts +98 -0
- package/lib/mail/senderListsApi.ts +161 -0
- package/lib/search/queryGrammar.ts +179 -0
- package/lib/search/searchApi.ts +199 -0
- package/lib/search/searchScoring.ts +46 -0
- package/lib/search/searchTier3.ts +406 -0
- package/lib/tasks/tasksApi.ts +128 -0
- package/lib/util/api.ts +318 -0
- package/lib/util/apiClientContext.ts +35 -0
- package/lib/util/apiQuery.ts +61 -0
- package/lib/util/clipboard.ts +55 -0
- package/lib/util/dateInput.ts +15 -0
- package/lib/util/timeZone.ts +33 -0
- package/lib/util/useCopyToClipboard.ts +48 -0
- package/lib/util/useIsMobile.ts +34 -0
- package/lib/videoconf/videoMeetingsApi.ts +144 -0
- package/package.json +10 -4
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
/**
|
|
6
|
+
* Typed wrappers over `@rapidmx/restapi`'s REST surface. Shared by `apps/admin` and (from Phase 3 on)
|
|
7
|
+
* `apps/www` — there is no separate admin-only endpoint set to isolate: every route here is gated entirely
|
|
8
|
+
* by the ACL system, so the exact same call returns the caller's own data and what is shared with them - an
|
|
9
|
+
* administrator's included: no role reads another user's mail. The one exception is the administration scope
|
|
10
|
+
* (`scope: "admin"` -> `?scope=admin`), which ONLY the admin console passes: mailboxes then come back as
|
|
11
|
+
* administrative metadata (no keys, settings or content) and every call is audited; an administrator who needs
|
|
12
|
+
* to see somebody's mail impersonates them (`impersonateUser()`). See `BaseMailboxRoute`'s doc comment in
|
|
13
|
+
* `@rapidmx/restapi` and this repo's `.claude/NOTES.md`.
|
|
14
|
+
*/
|
|
15
|
+
import { ApiRequestError, apiFetch, apiUrl, authApiFetch, withClient, withCsrfHeader } from "../util/api.js";
|
|
16
|
+
import { buildQuery } from "../util/apiQuery.js";
|
|
17
|
+
import { deviceTimeZone } from "../util/timeZone.js";
|
|
18
|
+
import { bytesToBinaryString } from "../crypto/mime.js";
|
|
19
|
+
/** Whether `mailbox` is one shared with the caller rather than their own: a delegate grant on somebody's mailbox, or a mailbox with no
|
|
20
|
+
* owner at all (a shared/org mailbox they were granted). */
|
|
21
|
+
export function isSharedWithMe(mailbox) {
|
|
22
|
+
return mailbox.accessRole ? mailbox.accessRole === "delegate" : !mailbox.ownerUserUid;
|
|
23
|
+
}
|
|
24
|
+
/** The `scope` query parameter of `params`, when set. */
|
|
25
|
+
function scopeQuery(params) {
|
|
26
|
+
return params.scope ? { scope: params.scope } : {};
|
|
27
|
+
}
|
|
28
|
+
/** The free/busy visibility `mailbox` has: `"domain"` when it says none (a mailbox stored before the setting existed). */
|
|
29
|
+
export function freeBusyVisibilityOf(mailbox) {
|
|
30
|
+
return mailbox.freeBusyVisibility ?? "domain";
|
|
31
|
+
}
|
|
32
|
+
/** The blocked senders `mailbox` has: none when it says none (a mailbox stored before the list existed, or `null` from an SQL row). */
|
|
33
|
+
export function blockedSendersOf(mailbox) {
|
|
34
|
+
return mailbox.blockedSenders ?? [];
|
|
35
|
+
}
|
|
36
|
+
/** The safe senders `mailbox` has: none when it says none. */
|
|
37
|
+
export function safeSendersOf(mailbox) {
|
|
38
|
+
return mailbox.safeSenders ?? [];
|
|
39
|
+
}
|
|
40
|
+
/** Lists the mailboxes the caller owns or has been granted - the same for everyone, an administrator included. With
|
|
41
|
+
* `scope: "admin"` (admin console only) it lists every mailbox as administrative metadata instead. */
|
|
42
|
+
export function listMailboxes(params = {}, client) {
|
|
43
|
+
return withClient(client, `/mail/mailboxes?${buildQuery(params, scopeQuery(params))}`);
|
|
44
|
+
}
|
|
45
|
+
/** One mailbox the caller owns or has been granted; with `scope: "admin"` (admin console only), its administrative metadata. */
|
|
46
|
+
export function getMailbox(uid, options = {}, client) {
|
|
47
|
+
return withClient(client, `/mail/mailboxes/${encodeURIComponent(uid)}${options.scope ? `?scope=${options.scope}` : ""}`);
|
|
48
|
+
}
|
|
49
|
+
/** Lists bookable resource mailboxes (rooms/equipment) visible to the caller — same ACL scoping as
|
|
50
|
+
* `listMailboxes()`, just pre-filtered server-side to `isResource: true` so `ResourcePicker` doesn't
|
|
51
|
+
* need to fetch and filter the caller's entire mailbox list client-side. */
|
|
52
|
+
export function listResourceMailboxes(params = {}, client) {
|
|
53
|
+
return withClient(client, `/mail/mailboxes?${buildQuery(params, { isResource: "true" })}`);
|
|
54
|
+
}
|
|
55
|
+
export function createMailbox(input, client) {
|
|
56
|
+
return withClient(client, "/mail/mailboxes", {
|
|
57
|
+
method: "POST",
|
|
58
|
+
body: JSON.stringify({ aliasAddresses: [], usedBytes: 0, ...input }),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Who a typed principal - a mailbox address, an auth-server username or e-mail alias, or a user uid - is, for an
|
|
63
|
+
* administrator naming a mailbox's owner (a new mailbox here, or a future reassignment) to confirm before saving.
|
|
64
|
+
* Rejects with a 404 `ApiRequestError` ("No user found for ...") for nobody. Trusted-role-only
|
|
65
|
+
* (`BaseMailboxRoute.resolveOwner()` in `@rapidmx/restapi`) - the same exact-match resolution
|
|
66
|
+
* `resolveMailboxPrincipal()` (`mailboxAccessApi.ts`) uses for sharing.
|
|
67
|
+
*/
|
|
68
|
+
export function resolveMailboxOwner(principal, client) {
|
|
69
|
+
return withClient(client, `/mail/mailboxes/resolve-owner?principal=${encodeURIComponent(principal)}`);
|
|
70
|
+
}
|
|
71
|
+
/** This server's configured domain list (`mail:domains`) — empty when unconfigured, meaning no
|
|
72
|
+
* restriction applies and a `primarySmtpAddress` may be on any domain. */
|
|
73
|
+
export function listMailboxDomains(client) {
|
|
74
|
+
return withClient(client, "/mail/mailboxes/domains");
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Self-service mailbox creation for a user with none yet — see `BaseMailboxRoute.autoProvision()`'s own
|
|
78
|
+
* doc comment in `@rapidmx/restapi` for the full contract. Call with no `selection` first; if the
|
|
79
|
+
* result is `needs_selection`, call again with the option the user picked from that list.
|
|
80
|
+
*/
|
|
81
|
+
export function autoProvisionMailbox(selection, client) {
|
|
82
|
+
return withClient(client, "/mail/mailboxes/auto-provision", {
|
|
83
|
+
method: "POST",
|
|
84
|
+
// The device's time zone goes with every call, for the mailbox this may create.
|
|
85
|
+
body: JSON.stringify({ ...selection, timezone: deviceTimeZone() }),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
export function updateMailbox(input, client) {
|
|
89
|
+
return withClient(client, `/mail/mailboxes/${encodeURIComponent(input.uid)}`, {
|
|
90
|
+
method: "PUT",
|
|
91
|
+
body: JSON.stringify(input),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Deletes a mailbox. Only the mailbox itself goes: its folders and everything in them stay - and the address can't be used for a
|
|
96
|
+
* new mailbox - until that data is erased. `erase: true` (administrators only; anybody else is refused 403 before anything is
|
|
97
|
+
* deleted) also files that erasure in the same step, which the server then runs in the background; without it the data is left for
|
|
98
|
+
* `admin/leftoverMailboxApi.ts` to list and erase later.
|
|
99
|
+
*/
|
|
100
|
+
export function deleteMailbox(uid, version, options = {}, client) {
|
|
101
|
+
return withClient(client, `/mail/mailboxes/${encodeURIComponent(uid)}?version=${version}${options.erase ? "&erase=true" : ""}`, { method: "DELETE" });
|
|
102
|
+
}
|
|
103
|
+
/** Lists quarantined mail for a mailbox the caller owns or has been granted; with `scope: "admin"` (admin console only), for any mailbox. */
|
|
104
|
+
export function listQuarantine(mailboxUid, params = {}, client) {
|
|
105
|
+
return withClient(client, `/mail/quarantine?${buildQuery(params, { mailboxUid, ...scopeQuery(params) })}`);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Marks a quarantined entry released. This only updates the record's metadata — it does not re-inject the
|
|
109
|
+
* message into normal delivery (see `@rapidmx/restapi`'s NOTES.md for why that's an explicit non-goal here).
|
|
110
|
+
*/
|
|
111
|
+
export function releaseQuarantineEntry(uid, version, releasedByUserUid, client) {
|
|
112
|
+
return withClient(client, `/mail/quarantine/${encodeURIComponent(uid)}`, {
|
|
113
|
+
method: "PUT",
|
|
114
|
+
body: JSON.stringify({ uid, version, releasedAt: new Date().toISOString(), releasedByUserUid }),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
/** Lists ingest-queue entries for a mailbox the caller owns or has been granted - useful for diagnosing stuck delivery; with
|
|
118
|
+
* `scope: "admin"` (admin console only), for any mailbox. */
|
|
119
|
+
export function listIngestQueue(mailboxUid, params = {}, client) {
|
|
120
|
+
return withClient(client, `/mail/ingest-queue?${buildQuery(params, { mailboxUid, ...scopeQuery(params) })}`);
|
|
121
|
+
}
|
|
122
|
+
/** Fetches a mailbox's own ACL — its `records` are its owner's/delegates' grants (see BaseACLRoute). The server only answers a
|
|
123
|
+
* caller who holds full access to that mailbox as themselves (never through a trusted role): to list, grant or revoke a mailbox's
|
|
124
|
+
* members use `listMailboxAccess()`/`setMailboxAccess()`/`removeMailboxAccess()` (`mailboxAccessApi.ts`), which is also the
|
|
125
|
+
* audited way an administrator shares an ownerless mailbox. */
|
|
126
|
+
export function getMailboxAcl(mailboxUid, client) {
|
|
127
|
+
return withClient(client, `/acls/${encodeURIComponent(mailboxUid)}`);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Grants (or replaces, if `userOrRoleId` already has a record) a delegate's access to a mailbox — the
|
|
131
|
+
* mechanism behind Exchange-style shared mailboxes. Read-modify-write against the ACL's own optimistic
|
|
132
|
+
* `version`, so concurrent grants can conflict; the caller should retry on a 409/version-mismatch.
|
|
133
|
+
*/
|
|
134
|
+
export async function grantMailboxAccess(mailboxUid, userOrRoleId, actions, client) {
|
|
135
|
+
const acl = await getMailboxAcl(mailboxUid, client);
|
|
136
|
+
const records = acl.records.filter((r) => r.userOrRoleId !== userOrRoleId);
|
|
137
|
+
records.push({ userOrRoleId, actions });
|
|
138
|
+
return withClient(client, `/acls/${encodeURIComponent(mailboxUid)}`, {
|
|
139
|
+
method: "PUT",
|
|
140
|
+
body: JSON.stringify({ uid: mailboxUid, version: acl.version, records }),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
/** Revokes a delegate's access to a mailbox previously granted via `grantMailboxAccess`. */
|
|
144
|
+
export async function revokeMailboxAccess(mailboxUid, userOrRoleId, client) {
|
|
145
|
+
const acl = await getMailboxAcl(mailboxUid, client);
|
|
146
|
+
const records = acl.records.filter((r) => r.userOrRoleId !== userOrRoleId);
|
|
147
|
+
return withClient(client, `/acls/${encodeURIComponent(mailboxUid)}`, {
|
|
148
|
+
method: "PUT",
|
|
149
|
+
body: JSON.stringify({ uid: mailboxUid, version: acl.version, records }),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/** Lists a mailbox's folders — visible to its owner, any delegate the mailbox is shared with, or (trusted) anyone. */
|
|
153
|
+
export function listFolders(mailboxUid, client) {
|
|
154
|
+
return withClient(client, `/mail/folders?${buildQuery({ limit: 200 }, { mailboxUid })}`);
|
|
155
|
+
}
|
|
156
|
+
/** Creates a new folder — e.g. an additional `calendar`-type folder for multi-calendar support. Nothing
|
|
157
|
+
* about folder creation is type-restricted server-side (see the Phase 4 plan's own note on
|
|
158
|
+
* `BaseFolderRoute.create()`), so this is just a thin wrapper, not a new backend capability. */
|
|
159
|
+
export function createFolder(input, client) {
|
|
160
|
+
return withClient(client, "/mail/folders", {
|
|
161
|
+
method: "POST",
|
|
162
|
+
body: JSON.stringify({ unreadCount: 0, totalCount: 0, ...input }),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
export function updateFolder(input, client) {
|
|
166
|
+
return withClient(client, `/mail/folders/${encodeURIComponent(input.uid)}`, {
|
|
167
|
+
method: "PUT",
|
|
168
|
+
body: JSON.stringify(input),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* The most labels one list request may filter by, matching `@rapidmx/restapi`'s own
|
|
173
|
+
* `MAX_MESSAGE_LABEL_FILTER_UIDS` — a longer set is refused with a 400, so a label menu offering multiple
|
|
174
|
+
* selection should stop the user here rather than send it.
|
|
175
|
+
*/
|
|
176
|
+
export const MAX_MESSAGE_LABEL_FILTER = 20;
|
|
177
|
+
/** Only the sort/filter params actually set, so a default list sends the same URL it always did. */
|
|
178
|
+
export function messageListQuery(params) {
|
|
179
|
+
const query = {};
|
|
180
|
+
if (params.sortBy) {
|
|
181
|
+
query.sortBy = params.sortBy;
|
|
182
|
+
}
|
|
183
|
+
if (params.sortOrder) {
|
|
184
|
+
query.sortOrder = params.sortOrder;
|
|
185
|
+
}
|
|
186
|
+
if (params.filter) {
|
|
187
|
+
query.filter = params.filter;
|
|
188
|
+
}
|
|
189
|
+
// One comma-separated value, the only form the server parses. An empty selection sends no parameter at all
|
|
190
|
+
// rather than an empty one, so a filter menu with nothing ticked makes the request it always made.
|
|
191
|
+
if (params.labelUids?.length) {
|
|
192
|
+
query.labelUids = params.labelUids.join(",");
|
|
193
|
+
}
|
|
194
|
+
return query;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Lists messages in a folder — newest received first unless `sortBy`/`sortOrder` say otherwise, and unfiltered
|
|
198
|
+
* unless `filter`/`labelUids` say otherwise. All of them are applied by the *database*, over the whole folder
|
|
199
|
+
* rather than over the page this call happens to return, so `page`/`limit` stay correct under a filter and a
|
|
200
|
+
* sort. Ties are broken by `uid`, so a message never appears on two pages or on neither.
|
|
201
|
+
*/
|
|
202
|
+
export function listMessages(folderUid, params = {}, client) {
|
|
203
|
+
return withClient(client, `/mail/messages?${buildQuery(params, { folderUid, ...messageListQuery(params) })}`);
|
|
204
|
+
}
|
|
205
|
+
export function getMessage(uid, client) {
|
|
206
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(uid)}`);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Attempts to recall a message this mailbox previously sent — only valid for a message currently in
|
|
210
|
+
* Sent Items (enforced server-side). Asynchronous and best-effort: this composes and relays a control
|
|
211
|
+
* message to every original recipient, but the actual delete-if-still-unread mutation happens later on
|
|
212
|
+
* each recipient's own mail system — there is no synchronous "recalled" outcome to report back, and the
|
|
213
|
+
* only visible effect here is `recallRequestedAt` getting set on the response.
|
|
214
|
+
*/
|
|
215
|
+
export function recallMessage(uid, client) {
|
|
216
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(uid)}/recall`, { method: "POST" });
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Moves a message into the mailbox's Archive folder (`FolderType.ARCHIVE`), lazily created on first use
|
|
220
|
+
* server-side — same pattern as Sent Items/Outbox, no client-side folder-creation step needed. Rejects
|
|
221
|
+
* (400, surfaced as an `ApiRequestError`) for a message currently in Drafts or Outbox. Idempotent —
|
|
222
|
+
* archiving an already-archived message is a no-op that still returns the message.
|
|
223
|
+
*/
|
|
224
|
+
export function archiveMessage(uid, client) {
|
|
225
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(uid)}/archive`, { method: "POST" });
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Moves a message between the Focused and Other halves of the Inbox — Outlook's "Move to Other" gesture.
|
|
229
|
+
* With `applyToSender: true` ("Always move to Other"), also upserts a standing `FocusedInboxOverride` for
|
|
230
|
+
* every future message from the same sender (see `focusedInboxOverridesApi.ts`) in the same round trip.
|
|
231
|
+
*/
|
|
232
|
+
export function classifyMessage(uid, classifyAs, applyToSender = false, client) {
|
|
233
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(uid)}/classify`, {
|
|
234
|
+
method: "POST",
|
|
235
|
+
body: JSON.stringify({ classifyAs, applyToSender }),
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Marks a message read/unread in place. `folderUid` must be included even though it isn't changing — every
|
|
240
|
+
* `Message` update is scoped by its owning folder (see `BaseScopedChildRoute`), and this framework's `PUT`
|
|
241
|
+
* routes replace the whole record rather than patch individual fields.
|
|
242
|
+
*/
|
|
243
|
+
export function setMessageRead(message, read, client) {
|
|
244
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(message.uid)}`, {
|
|
245
|
+
method: "PUT",
|
|
246
|
+
body: JSON.stringify({ uid: message.uid, version: message.version, flags: { ...message.flags, read } }),
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
/** Flags/unflags a message in place — Outlook's flag-status toggle, and what `listMessages({ filter:
|
|
250
|
+
* "flagged" })` and `listFlaggedMessages()` select on. */
|
|
251
|
+
export function setMessageFlagged(message, flagged, client) {
|
|
252
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(message.uid)}`, {
|
|
253
|
+
method: "PUT",
|
|
254
|
+
body: JSON.stringify({ uid: message.uid, version: message.version, flags: { ...message.flags, flagged } }),
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
/** Moves a message into another folder of the same mailbox — how "Move to", "Archive" (to the Archive folder),
|
|
258
|
+
* "Report junk" (to Junk) and "Delete" (to Deleted Items) are all expressed. */
|
|
259
|
+
export function moveMessage(message, folderUid, client) {
|
|
260
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(message.uid)}`, {
|
|
261
|
+
method: "PUT",
|
|
262
|
+
body: JSON.stringify({ uid: message.uid, version: message.version, folderUid }),
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Reports a message as junk, phishing or not junk - `POST /mail/messages/:uid/report`. The SERVER moves it (`junk` and `phishing` to the mailbox's Junk Email,
|
|
267
|
+
* `not_junk` to its Inbox; a message already there is not moved), records what was reported, teaches its spam filter (never for an encrypted message) and
|
|
268
|
+
* writes an audit entry; a caller needs no folder uid and no `version`. Rejects with a 400 for a message in Drafts or Outbox, a 403 without the right to change
|
|
269
|
+
* the message (or, for `alwaysTrustSender`, without full access to the mailbox), a 404 for an unknown message - and also for a server that predates the route,
|
|
270
|
+
* where a caller falls back to `moveMessage()`.
|
|
271
|
+
*/
|
|
272
|
+
export function reportMessage(uid, kind, options = {}, client) {
|
|
273
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(uid)}/report`, {
|
|
274
|
+
method: "POST",
|
|
275
|
+
body: JSON.stringify({ kind, ...(options.alwaysTrustSender ? { alwaysTrustSender: true } : {}) }),
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* The most updates `bulkUpdateMessages()` puts in one request, matching `@rapidmx/restapi`'s own
|
|
280
|
+
* `MAX_BULK_UPDATE` — a longer list is refused with a 400, so the helper below chunks rather than sending it.
|
|
281
|
+
*/
|
|
282
|
+
export const MAX_BULK_MESSAGE_UPDATE = 100;
|
|
283
|
+
/**
|
|
284
|
+
* Applies `updates` through `PUT /mail/messages`, the bulk form of the single-message update — one request per
|
|
285
|
+
* `MAX_BULK_MESSAGE_UPDATE` updates instead of one per message, with every permission, folder and legal-hold
|
|
286
|
+
* check the single-message path makes.
|
|
287
|
+
*
|
|
288
|
+
* Deliberately NOT atomic, on either side of the wire: the server applies each element in order and the first
|
|
289
|
+
* failure (a stale `version`, a refused move) aborts the rest of *that* request, leaving the elements before it
|
|
290
|
+
* applied; this helper then stops and rejects rather than sending the remaining chunks. So a caller should
|
|
291
|
+
* refetch the list after a rejection instead of assuming nothing happened, and should send fresh `version`s -
|
|
292
|
+
* a bulk action over a stale selection is the common way to hit a 409. For a per-element outcome, call the
|
|
293
|
+
* single-message functions instead.
|
|
294
|
+
*
|
|
295
|
+
* Resolves with every message actually updated, in request order.
|
|
296
|
+
*/
|
|
297
|
+
export async function bulkUpdateMessages(updates, client) {
|
|
298
|
+
const updated = [];
|
|
299
|
+
for (let i = 0; i < updates.length; i += MAX_BULK_MESSAGE_UPDATE) {
|
|
300
|
+
const chunk = updates.slice(i, i + MAX_BULK_MESSAGE_UPDATE);
|
|
301
|
+
updated.push(...(await withClient(client, "/mail/messages", { method: "PUT", body: JSON.stringify(chunk) })));
|
|
302
|
+
}
|
|
303
|
+
return updated;
|
|
304
|
+
}
|
|
305
|
+
/** Marks a whole selection read/unread in one pass — see `bulkUpdateMessages()` for the failure semantics. */
|
|
306
|
+
export function setMessagesRead(messages, read, client) {
|
|
307
|
+
return bulkUpdateMessages(messages.map((message) => ({ uid: message.uid, version: message.version, flags: { ...message.flags, read } })), client);
|
|
308
|
+
}
|
|
309
|
+
/** Flags/unflags a whole selection in one pass — see `bulkUpdateMessages()`. */
|
|
310
|
+
export function setMessagesFlagged(messages, flagged, client) {
|
|
311
|
+
return bulkUpdateMessages(messages.map((message) => ({ uid: message.uid, version: message.version, flags: { ...message.flags, flagged } })), client);
|
|
312
|
+
}
|
|
313
|
+
/** Moves a whole selection into `folderUid` — bulk Move, Archive, Report junk and Delete (to Deleted Items)
|
|
314
|
+
* are all this call with a different target folder. See `bulkUpdateMessages()`. */
|
|
315
|
+
export function moveMessages(messages, folderUid, client) {
|
|
316
|
+
return bulkUpdateMessages(messages.map((message) => ({ uid: message.uid, version: message.version, folderUid })), client);
|
|
317
|
+
}
|
|
318
|
+
/** Sets the full `labelUids` list on a whole selection — see `setMessageLabels()` and `bulkUpdateMessages()`. */
|
|
319
|
+
export function setMessagesLabels(messages, labelUids, client) {
|
|
320
|
+
return bulkUpdateMessages(messages.map((message) => ({ uid: message.uid, version: message.version, labelUids })), client);
|
|
321
|
+
}
|
|
322
|
+
/** Sets a message's full `labelUids` list (not an add/remove delta - the caller computes the complete
|
|
323
|
+
* new set, same convention as `Note`/`Task` label-like fields elsewhere in restapi). Deleting a label
|
|
324
|
+
* elsewhere already strips it server-side from every message (`labelsApi.ts#deleteLabel()`'s own doc
|
|
325
|
+
* comment) - this is only for a user explicitly applying/removing labels on one message. */
|
|
326
|
+
export function setMessageLabels(message, labelUids, client) {
|
|
327
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(message.uid)}`, {
|
|
328
|
+
method: "PUT",
|
|
329
|
+
body: JSON.stringify({ uid: message.uid, version: message.version, labelUids }),
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Cancels a scheduled send by moving the message out of Outbox into `draftsFolderUid` (the mailbox's Drafts
|
|
334
|
+
* folder, which the caller resolves). The server clears `scheduledSendTime` itself on any move out of Outbox;
|
|
335
|
+
* the `null` sent here is accepted and ignored.
|
|
336
|
+
*/
|
|
337
|
+
export function cancelScheduledSend(message, draftsFolderUid, client) {
|
|
338
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(message.uid)}`, {
|
|
339
|
+
method: "PUT",
|
|
340
|
+
body: JSON.stringify({ uid: message.uid, version: message.version, scheduledSendTime: null, folderUid: draftsFolderUid }),
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Sets a draft's `requestReceipt` ahead of calling `sendMessage()`, overriding the mailbox's own
|
|
345
|
+
* `alwaysRequestReceiptInternal`/`External` defaults for this one message — same ordinary-`PUT`-before-
|
|
346
|
+
* `send()` convention.
|
|
347
|
+
*/
|
|
348
|
+
export function setMessageRequestReceipt(message, requestReceipt, client) {
|
|
349
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(message.uid)}`, {
|
|
350
|
+
method: "PUT",
|
|
351
|
+
body: JSON.stringify({ uid: message.uid, version: message.version, requestReceipt }),
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Thrown by `setMessageVerificationSeal()` when restapi answers `409`: the message already carries a different seal the
|
|
356
|
+
* server won't replace (it replaces one only when the stored seal's generation is older than the vault's current
|
|
357
|
+
* `masterKeyGeneration` and the request's generation equals the current one). Still an `ApiRequestError` (`status` 409).
|
|
358
|
+
* A caller writing seals best effort should ignore it.
|
|
359
|
+
*/
|
|
360
|
+
export class VerificationSealConflictError extends ApiRequestError {
|
|
361
|
+
constructor(message, code) {
|
|
362
|
+
super(message, 409, code);
|
|
363
|
+
this.name = "VerificationSealConflictError";
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Stores a verification seal on a message (`PUT /mail/messages/:id/verification-seal` with
|
|
368
|
+
* `{ seal, masterKeyGeneration }`), normally `MessageSecurityResult.sealToWrite`'s two fields from
|
|
369
|
+
* `crypto/messageSecurity.ts`'s `evaluateMessageSecurityWithSeal()`. Resolves with the updated message; storing the
|
|
370
|
+
* identical seal again succeeds. Rejects with `VerificationSealConflictError` on `409` (a different seal is stored and
|
|
371
|
+
* isn't replaceable - see that class), and a plain `ApiRequestError` for `400` (an invalid seal or generation) and
|
|
372
|
+
* `403`/`404`.
|
|
373
|
+
*/
|
|
374
|
+
export async function setMessageVerificationSeal(messageUid, seal, masterKeyGeneration, client) {
|
|
375
|
+
try {
|
|
376
|
+
return await withClient(client, `/mail/messages/${encodeURIComponent(messageUid)}/verification-seal`, {
|
|
377
|
+
method: "PUT",
|
|
378
|
+
body: JSON.stringify({ seal, masterKeyGeneration }),
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
catch (err) {
|
|
382
|
+
if (err instanceof ApiRequestError && err.status === 409) {
|
|
383
|
+
throw new VerificationSealConflictError(err.message, err.code);
|
|
384
|
+
}
|
|
385
|
+
throw err;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
/** Sends a delivery/read receipt this mailbox held pending the owner's explicit approval (see
|
|
389
|
+
* `Message.deliveryReceiptPending`/`readReceiptPending`). */
|
|
390
|
+
export function approveReceipt(uid, type, client) {
|
|
391
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(uid)}/receipt/approve`, {
|
|
392
|
+
method: "POST",
|
|
393
|
+
body: JSON.stringify({ type }),
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
/** Permanently declines a pending receipt — no later re-prompt for that same event. */
|
|
397
|
+
export function declineReceipt(uid, type, client) {
|
|
398
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(uid)}/receipt/decline`, {
|
|
399
|
+
method: "POST",
|
|
400
|
+
body: JSON.stringify({ type }),
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
/** Lists the attachments belonging to a single message. */
|
|
404
|
+
export function listAttachments(folderUid, messageUid, client) {
|
|
405
|
+
return withClient(client, `/mail/attachments?${buildQuery({ limit: 200 }, { folderUid, messageUid })}`);
|
|
406
|
+
}
|
|
407
|
+
/** The URL to download/display an attachment's binary content — not fetched via `apiFetch`, used directly as
|
|
408
|
+
* a link/image `href`/`src`. Honors `configureApiBaseUrl()` (see `apiUrl()`). */
|
|
409
|
+
export function attachmentContentUrl(uid) {
|
|
410
|
+
return apiUrl(`/mail/attachments/${encodeURIComponent(uid)}/content`);
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Uploads a file's raw bytes as a new attachment on a not-yet-sent draft. Bypasses `apiFetch` — that helper
|
|
414
|
+
* always forces `Content-Type: application/json`, which would corrupt binary content; this sends the file's
|
|
415
|
+
* own bytes/type directly instead, matching `BaseAttachmentRoute.upload`'s expectation of a raw request body.
|
|
416
|
+
*/
|
|
417
|
+
export async function uploadAttachment(messageUid, file) {
|
|
418
|
+
const params = new URLSearchParams({ messageUid, filename: file.name, mimeType: file.type || "application/octet-stream" });
|
|
419
|
+
const res = await fetch(apiUrl(`/mail/attachments/upload?${params.toString()}`), {
|
|
420
|
+
method: "POST",
|
|
421
|
+
credentials: "include",
|
|
422
|
+
headers: withCsrfHeader({ "Content-Type": file.type || "application/octet-stream" }),
|
|
423
|
+
body: file,
|
|
424
|
+
});
|
|
425
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
426
|
+
const responseBody = contentType.includes("application/json") ? await res.json().catch(() => undefined) : undefined;
|
|
427
|
+
if (!res.ok) {
|
|
428
|
+
const message = (responseBody && (responseBody.message || responseBody.error)) || res.statusText || "Upload failed.";
|
|
429
|
+
throw new ApiRequestError(message, res.status, responseBody?.code);
|
|
430
|
+
}
|
|
431
|
+
return responseBody;
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Creates a blank draft `Message` in the given folder (normally the mailbox's Drafts folder) to compose into.
|
|
435
|
+
*
|
|
436
|
+
* A reply MUST pass `threading` (build it with `buildReplyThreading()` from the message being replied to).
|
|
437
|
+
* `@rapidmx/restapi` writes those values into the `In-Reply-To`/`References` headers of the MIME it relays and
|
|
438
|
+
* groups the message into the replied-to message's conversation; a reply created without them is relayed with no
|
|
439
|
+
* threading headers at all, and every recipient - and the sender's own Sent Items copy - files it as a brand-new
|
|
440
|
+
* conversation. Nothing else recovers them: this server composes the MIME from the recipients, subject and HTML
|
|
441
|
+
* passed to `assembleDraft()`, which say nothing about what is being replied to.
|
|
442
|
+
*/
|
|
443
|
+
export function createDraft(mailboxUid, folderUid, threading, client) {
|
|
444
|
+
return withClient(client, "/mail/messages", {
|
|
445
|
+
method: "POST",
|
|
446
|
+
body: JSON.stringify({
|
|
447
|
+
mailboxUid,
|
|
448
|
+
folderUid,
|
|
449
|
+
messageId: `${crypto.randomUUID()}@webmail`,
|
|
450
|
+
...(threading?.inReplyTo ? { inReplyTo: threading.inReplyTo } : {}),
|
|
451
|
+
...(threading?.references?.length ? { references: threading.references } : {}),
|
|
452
|
+
}),
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
/** Deletes a message - e.g. an unsent draft that's no longer needed because compose switched to a different
|
|
456
|
+
* sending mailbox. */
|
|
457
|
+
export function deleteMessage(uid, version, client) {
|
|
458
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(uid)}?version=${version}`, { method: "DELETE" });
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Permanently deletes one message - `DELETE /mail/messages/:uid?purge=true`, the hard delete: the row and its search
|
|
462
|
+
* document are gone and it cannot be restored, unlike `deleteMessage()` (a soft delete the server can bring back) or a
|
|
463
|
+
* move into Deleted Items. Whoever may delete in the message's folder may do this - the mailbox's owner, or a delegate
|
|
464
|
+
* granted `delete` - there is nothing administrative about it.
|
|
465
|
+
*
|
|
466
|
+
* Takes no `version`: one that no longer matches (another device flipped a flag since the list was fetched) would make
|
|
467
|
+
* the server answer "not found", which is no reason to keep a message the reader has asked to erase. Refused with a
|
|
468
|
+
* `409` for a message under an active legal hold (the response's message says so) or with a send in flight, and with a
|
|
469
|
+
* `403` without the `delete` grant. Nothing about the message changes when it is refused, so a caller deleting several
|
|
470
|
+
* reports each refusal and carries on with the rest.
|
|
471
|
+
*/
|
|
472
|
+
export function purgeMessage(uid, client) {
|
|
473
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(uid)}?purge=true`, { method: "DELETE" });
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Permanently deletes every message in a folder in one request - `DELETE /mail/messages?folderUid=` (the collection
|
|
477
|
+
* `truncate`, always a hard delete). All or nothing: the server checks every message for a legal hold first and refuses
|
|
478
|
+
* the whole request with a `409` if any is held, and with a `403` unless the caller holds the `truncate` grant on the
|
|
479
|
+
* mailbox (its owner or a manager - not a delegate who may merely delete). Resolves without saying how many messages
|
|
480
|
+
* went, so a caller that needs to says so from what it knew. Messages already soft-deleted are not part of it.
|
|
481
|
+
*
|
|
482
|
+
* After a refusal, fall back to `purgeMessage()` per message: that removes what may be removed and says which may not.
|
|
483
|
+
*/
|
|
484
|
+
export function emptyFolder(folderUid, client) {
|
|
485
|
+
return withClient(client, `/mail/messages?${new URLSearchParams({ folderUid }).toString()}`, { method: "DELETE" });
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Assembles a draft's structured compose input (recipients/subject/HTML body, plus whatever attachments have
|
|
489
|
+
* already been `uploadAttachment()`-ed onto it) into RFC 5322 MIME and stores it as the draft's `bodyBlobKey`
|
|
490
|
+
* — see `BaseMailComposeRoute` (this app's own compose-assembly glue, since `@rapidmx/restapi`'s `send()`
|
|
491
|
+
* itself does no MIME composition). Does not send the message.
|
|
492
|
+
*/
|
|
493
|
+
export function assembleDraft(messageUid, input, client) {
|
|
494
|
+
return withClient(client, `/mail/compose/${encodeURIComponent(messageUid)}/assemble`, {
|
|
495
|
+
method: "POST",
|
|
496
|
+
body: JSON.stringify(input),
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Stores an already-signed/encrypted draft's raw MIME source as its `bodyBlobKey`, completely
|
|
501
|
+
* unmodified — the E2E counterpart to `assembleDraft()`, for when the message body was built
|
|
502
|
+
* client-side via `crypto/smimeMessage.ts` rather than from plain HTML. Does not send the message. A
|
|
503
|
+
* draft assembled this way cannot carry file attachments yet — see `BaseMailComposeRoute.assembleRaw()`'s
|
|
504
|
+
* own doc comment in `server`.
|
|
505
|
+
*/
|
|
506
|
+
export function assembleDraftRaw(messageUid, input, client) {
|
|
507
|
+
return withClient(client, `/mail/compose/${encodeURIComponent(messageUid)}/assemble-raw`, {
|
|
508
|
+
method: "POST",
|
|
509
|
+
body: JSON.stringify(input),
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Scans, relays, and moves an already-assembled draft into Sent Items - or, with a future
|
|
514
|
+
* `scheduledSendTime`, queues it in Outbox for `@rapidmx/restapi`'s `ScheduledSendJob`. A message already in
|
|
515
|
+
* Outbox or Sent Items is refused (409); move it back to Drafts first.
|
|
516
|
+
*/
|
|
517
|
+
export function sendMessage(messageUid, options, client) {
|
|
518
|
+
return withClient(client, `/mail/messages/${encodeURIComponent(messageUid)}/send`, {
|
|
519
|
+
method: "POST",
|
|
520
|
+
...(options?.scheduledSendTime ? { body: JSON.stringify({ scheduledSendTime: options.scheduledSendTime }) } : {}),
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Sends an already-assembled draft *in the background*: `POST /mail/messages/:id/send` with `{ background: true }`. The server
|
|
525
|
+
* checks the message, moves it into Outbox with a lease and answers `202 { status: "queued", message }` at once - relaying happens
|
|
526
|
+
* afterwards, and its outcome is published as push events on the mailbox's, Outbox's and Sent Items' channels rather than answered
|
|
527
|
+
* here. Rejects with the server's own error (validation, permissions: the message was not queued). A server that has no queue
|
|
528
|
+
* relays first and answers with the message, which resolves as `{ queued: false }` - as does a message class with no send job, which
|
|
529
|
+
* answers a background send `501`: it is then sent the ordinary, synchronous way.
|
|
530
|
+
*/
|
|
531
|
+
export async function queueMessageSend(messageUid, client) {
|
|
532
|
+
let result;
|
|
533
|
+
try {
|
|
534
|
+
result = await withClient(client, `/mail/messages/${encodeURIComponent(messageUid)}/send`, { method: "POST", body: JSON.stringify({ background: true }) });
|
|
535
|
+
}
|
|
536
|
+
catch (err) {
|
|
537
|
+
if (err instanceof ApiRequestError && err.status === 501) {
|
|
538
|
+
return { queued: false, message: await sendMessage(messageUid, undefined, client) };
|
|
539
|
+
}
|
|
540
|
+
throw err;
|
|
541
|
+
}
|
|
542
|
+
const queued = result;
|
|
543
|
+
if (queued.status === "queued" && queued.message) {
|
|
544
|
+
return { queued: true, message: queued.message };
|
|
545
|
+
}
|
|
546
|
+
return { queued: false, message: result };
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Fetches a message's raw RFC 5322 MIME source — for client-side E2E decrypt/signature-verification
|
|
550
|
+
* only (`crypto/smimeMessage.ts`), never for display. Bypasses `apiFetch()` (which only ever decodes a
|
|
551
|
+
* JSON response body): this server-local route (`BaseMessageRawContentRoute.ts` in `server`, mounted
|
|
552
|
+
* alongside `@rapidmx/restapi`'s own `MessageRoute`) returns `message/rfc822`, not JSON — the one thing
|
|
553
|
+
* that library's own `GET /:id/content` deliberately never serves (see that route's own doc comment).
|
|
554
|
+
*
|
|
555
|
+
* Returns a *binary string* - the response bytes decoded as Latin-1, exactly one character per byte -
|
|
556
|
+
* rather than `res.text()`'s UTF-8 decoding, which would replace every invalid byte of a non-UTF-8 8bit
|
|
557
|
+
* part with U+FFFD before its own `charset` is known and break any signature over those bytes. Pass it
|
|
558
|
+
* straight to `evaluateMessageSecurity()` (see `crypto/mime.ts`'s doc comment on binary strings); it is
|
|
559
|
+
* not display text.
|
|
560
|
+
*/
|
|
561
|
+
export async function getMessageRawContent(messageUid) {
|
|
562
|
+
const res = await fetch(apiUrl(`/mail/messages/${encodeURIComponent(messageUid)}/raw`), { credentials: "include" });
|
|
563
|
+
if (!res.ok) {
|
|
564
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
565
|
+
const body = contentType.includes("application/json") ? await res.json().catch(() => undefined) : undefined;
|
|
566
|
+
const message = (body && (body.message || body.error)) || res.statusText || "Could not load this message's raw content.";
|
|
567
|
+
throw new ApiRequestError(message, res.status, body?.code);
|
|
568
|
+
}
|
|
569
|
+
// Not `new TextDecoder("latin1")`: WHATWG maps that label to windows-1252, which remaps 0x80-0x9F and so
|
|
570
|
+
// isn't byte-preserving. `bytesToBinaryString()` is an exact byte -> code unit conversion.
|
|
571
|
+
return bytesToBinaryString(new Uint8Array(await res.arrayBuffer()));
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Trusted-role-only: starts an admin "log in as user" session. In production this calls auth-server
|
|
575
|
+
* directly (not this app's own API) since only auth-server can mint a token carrying `userUid`'s real
|
|
576
|
+
* roles/scopes the way its own sign-in flow would — see `@rapidrest/auth`'s `BaseImpersonationRoute` and
|
|
577
|
+
* this repo's `.claude/NOTES.md`. The browser's `jwt` cookie is swapped for the freshly-minted token, and
|
|
578
|
+
* the caller's own session is stashed (`jwt_impersonator`) so `stopImpersonating()` can restore it later.
|
|
579
|
+
* The caller is responsible for navigating to `/` afterward — this call only swaps the cookie, it doesn't
|
|
580
|
+
* redirect.
|
|
581
|
+
*
|
|
582
|
+
* @param impersonationBaseUrl The origin to call — the real auth-server in production, or `""` under
|
|
583
|
+
* `yarn dev` (see `AdminConsoleRoute`/`wwwRoute`'s `fetchProps`) to instead call this app's own local
|
|
584
|
+
* dev-only endpoint (`DevImpersonationRoute`), since a real auth-server isn't running locally.
|
|
585
|
+
*/
|
|
586
|
+
export function impersonateUser(impersonationBaseUrl, userUid) {
|
|
587
|
+
const init = { method: "POST", body: JSON.stringify({ userUid }) };
|
|
588
|
+
return impersonationBaseUrl
|
|
589
|
+
? authApiFetch(impersonationBaseUrl, "/admin/impersonate", init)
|
|
590
|
+
: apiFetch("/admin/impersonate", init);
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Ends an active impersonation session, restoring the admin's own — a no-op (`restored: false`) if none is
|
|
594
|
+
* active. POST, not GET: this mutates state (swaps the active `jwt` cookie back), and a state-changing GET
|
|
595
|
+
* is exploitable via a bare navigation — no form or script required at all — bypassing CSRF defenses
|
|
596
|
+
* entirely, since they only ever apply to non-safe methods. See `@rapidrest/auth`'s `BaseImpersonationRoute`.
|
|
597
|
+
*/
|
|
598
|
+
export function stopImpersonating(impersonationBaseUrl) {
|
|
599
|
+
return impersonationBaseUrl
|
|
600
|
+
? authApiFetch(impersonationBaseUrl, "/admin/impersonate/stop", { method: "POST" })
|
|
601
|
+
: apiFetch("/admin/impersonate/stop", { method: "POST" });
|
|
602
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Attachment, Message } from "./mailApi.js";
|
|
2
|
+
/** Loads a message's attachments (only when it actually has any) — shared by every place a message is read. */
|
|
3
|
+
export declare function useMessageAttachments(message: Message | null): Attachment[];
|
|
4
|
+
/**
|
|
5
|
+
* Marks a message read the first time it's viewed. `onUpdated` receives the server's updated copy — the
|
|
6
|
+
* desktop reading pane patches its in-memory message list with it; the mobile detail route (which has no
|
|
7
|
+
* list to patch) just replaces its own local `message` state. Best-effort: a failed update shouldn't block
|
|
8
|
+
* reading the message, matching this app's existing `handleSelect` behavior.
|
|
9
|
+
*/
|
|
10
|
+
export declare function useMarkMessageRead(message: Message | null, onUpdated: (updated: Message) => void): void;
|