@cosmicdrift/kumiko-bundled-features 0.393.0 → 0.394.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/dist/account-security/feature.d.ts +2 -0
- package/dist/account-security/feature.js +3 -1
- package/dist/audit/event-classification.js +1 -0
- package/dist/auth-email-password/handlers/change-password.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/confirm-account-unlock.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/invite-accept-with-login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/invite-accept.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/invite-create.write.d.ts +2 -2
- package/dist/auth-email-password/handlers/invite-signup-complete.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/login.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/logout.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-account-unlock.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-email-verification.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/request-password-reset.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/reset-password.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/signup-confirm.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/signup-request.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/switch-tenant-mfa-gate.write.d.ts +1 -1
- package/dist/auth-email-password/handlers/token-request-handler.d.ts +1 -1
- package/dist/auth-email-password/handlers/verify-email.write.d.ts +1 -1
- package/dist/auth-email-password/web/auth-client.d.ts +3 -7
- package/dist/auth-email-password/web/auth-client.js +3 -24
- package/dist/auth-email-password/web/auth-gate.d.ts +2 -4
- package/dist/auth-email-password/web/auth-redirect.d.ts +2 -2
- package/dist/auth-email-password/web/auth-redirect.js +3 -12
- package/dist/auth-email-password/web/index.d.ts +2 -1
- package/dist/auth-email-password/web/index.js +1 -0
- package/dist/auth-email-password/web/login-failure.d.ts +9 -0
- package/dist/auth-email-password/web/login-failure.js +32 -0
- package/dist/auth-email-password/web/login-url.d.ts +5 -0
- package/dist/auth-email-password/web/login-url.js +13 -0
- package/dist/auth-email-password/web/static-login.d.ts +42 -0
- package/dist/auth-email-password/web/static-login.js +122 -0
- package/dist/auth-mfa/handlers/disable.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-confirm-preauth.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-confirm.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-start-preauth.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/enable-start.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/regenerate-recovery.write.d.ts +1 -1
- package/dist/auth-mfa/handlers/verify.write.d.ts +1 -1
- package/dist/auth-mfa/web/mfa-client.js +4 -43
- package/dist/billing-foundation/checkout-core.d.ts +2 -1
- package/dist/billing-foundation/checkout-core.js +2 -11
- package/dist/billing-foundation/events.d.ts +1 -0
- package/dist/billing-foundation/events.js +2 -0
- package/dist/billing-foundation/feature.js +1 -1
- package/dist/billing-foundation/handlers/create-checkout-session.write.js +9 -2
- package/dist/billing-foundation/handlers/process-payment-event.write.d.ts +1 -0
- package/dist/billing-foundation/handlers/process-payment-event.write.js +2 -0
- package/dist/billing-foundation/index.d.ts +1 -1
- package/dist/billing-foundation/one-off-checkout-gate.d.ts +9 -0
- package/dist/billing-foundation/one-off-checkout-gate.js +30 -0
- package/dist/billing-foundation/one-off-customer.d.ts +6 -0
- package/dist/billing-foundation/one-off-customer.js +12 -0
- package/dist/billing-foundation/plan-catalog.js +1 -0
- package/dist/billing-foundation/types.d.ts +25 -0
- package/dist/billing-foundation/web/billing-plans-panel.js +1 -0
- package/dist/billing-foundation/web/plan-switch-confirm-dialog.js +7 -3
- package/dist/billing-foundation/web/plan-switch-recurring.d.ts +16 -0
- package/dist/billing-foundation/web/plan-switch-recurring.js +10 -0
- package/dist/billing-foundation/webhook-handler.js +1 -0
- package/dist/cap-overview/handlers/caps-usage.query.js +3 -3
- package/dist/cap-overview/types.d.ts +2 -0
- package/dist/channel-in-app/handlers/mark-all-read.write.d.ts +1 -1
- package/dist/channel-in-app/handlers/mark-read.write.d.ts +1 -1
- package/dist/compliance-profiles/handlers/set-profile.write.d.ts +1 -1
- package/dist/compliance-profiles/web/compliance-profile-catalog.js +8 -1
- package/dist/config/handlers/reset.write.d.ts +1 -1
- package/dist/config/handlers/set.write.d.ts +1 -1
- package/dist/crypto-shredding/handlers/forget-subject.write.d.ts +1 -1
- package/dist/delivery/handlers/resubscribe-address.write.d.ts +1 -1
- package/dist/delivery/handlers/resubscribe-user.write.d.ts +1 -1
- package/dist/delivery/handlers/set-preference.write.d.ts +1 -1
- package/dist/delivery/handlers/unsubscribe-address.write.d.ts +1 -1
- package/dist/delivery/handlers/unsubscribe-user.write.d.ts +1 -1
- package/dist/feature-toggles/handlers/set.write.d.ts +1 -1
- package/dist/file-foundation/read-file-ref-content.d.ts +2 -0
- package/dist/file-foundation/read-file-ref-content.js +9 -3
- package/dist/form-draft/handlers/discard.write.d.ts +1 -1
- package/dist/form-draft/handlers/save.write.d.ts +1 -1
- package/dist/inbound-mail-foundation/account-health.d.ts +17 -0
- package/dist/inbound-mail-foundation/account-health.js +101 -0
- package/dist/inbound-mail-foundation/account-poll-schedule.d.ts +19 -0
- package/dist/inbound-mail-foundation/account-poll-schedule.js +44 -0
- package/dist/inbound-mail-foundation/account-poll.d.ts +24 -0
- package/dist/inbound-mail-foundation/account-poll.js +157 -0
- package/dist/inbound-mail-foundation/account-record.d.ts +1 -0
- package/dist/inbound-mail-foundation/account-record.js +1 -0
- package/dist/inbound-mail-foundation/account-wake.d.ts +3 -0
- package/dist/inbound-mail-foundation/account-wake.js +17 -0
- package/dist/inbound-mail-foundation/connect-callback-verify.d.ts +10 -0
- package/dist/inbound-mail-foundation/connect-callback-verify.js +31 -0
- package/dist/inbound-mail-foundation/connect-route-responses.d.ts +13 -0
- package/dist/inbound-mail-foundation/connect-route-responses.js +16 -0
- package/dist/inbound-mail-foundation/connect-routes.js +52 -33
- package/dist/inbound-mail-foundation/constants.d.ts +50 -2
- package/dist/inbound-mail-foundation/constants.js +53 -3
- package/dist/inbound-mail-foundation/content-refetch.d.ts +14 -0
- package/dist/inbound-mail-foundation/content-refetch.js +93 -0
- package/dist/inbound-mail-foundation/describe-error.d.ts +1 -0
- package/dist/inbound-mail-foundation/describe-error.js +5 -0
- package/dist/inbound-mail-foundation/entities.d.ts +26 -0
- package/dist/inbound-mail-foundation/entities.js +43 -3
- package/dist/inbound-mail-foundation/events.d.ts +97 -0
- package/dist/inbound-mail-foundation/events.js +57 -2
- package/dist/inbound-mail-foundation/feature.d.ts +5 -2
- package/dist/inbound-mail-foundation/feature.js +122 -106
- package/dist/inbound-mail-foundation/file-storage-failure.d.ts +8 -0
- package/dist/inbound-mail-foundation/file-storage-failure.js +19 -0
- package/dist/inbound-mail-foundation/handlers/account-address.d.ts +16 -0
- package/dist/inbound-mail-foundation/handlers/account-address.js +51 -0
- package/dist/inbound-mail-foundation/handlers/acknowledge-quarantine.write.d.ts +8 -0
- package/dist/inbound-mail-foundation/handlers/acknowledge-quarantine.write.js +39 -0
- package/dist/inbound-mail-foundation/handlers/attach-message-content.write.d.ts +60 -0
- package/dist/inbound-mail-foundation/handlers/attach-message-content.write.js +128 -0
- package/dist/inbound-mail-foundation/handlers/connect-account.write.d.ts +3 -2
- package/dist/inbound-mail-foundation/handlers/connect-account.write.js +96 -55
- package/dist/inbound-mail-foundation/handlers/disconnect-account.write.d.ts +2 -1
- package/dist/inbound-mail-foundation/handlers/disconnect-account.write.js +55 -42
- package/dist/inbound-mail-foundation/handlers/ingest-message-prepare.d.ts +26 -0
- package/dist/inbound-mail-foundation/handlers/ingest-message-prepare.js +131 -0
- package/dist/inbound-mail-foundation/handlers/ingest-message-schema.d.ts +64 -0
- package/dist/inbound-mail-foundation/handlers/ingest-message-schema.js +39 -0
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.d.ts +74 -21
- package/dist/inbound-mail-foundation/handlers/ingest-message.write.js +57 -134
- package/dist/inbound-mail-foundation/handlers/list-accounts.query.d.ts +2 -1
- package/dist/inbound-mail-foundation/handlers/list-accounts.query.js +60 -26
- package/dist/inbound-mail-foundation/handlers/list-messages.query.d.ts +2 -1
- package/dist/inbound-mail-foundation/handlers/list-messages.query.js +43 -29
- package/dist/inbound-mail-foundation/handlers/list-quarantine.query.d.ts +3 -0
- package/dist/inbound-mail-foundation/handlers/list-quarantine.query.js +75 -0
- package/dist/inbound-mail-foundation/handlers/mark-credential-stored.write.d.ts +7 -0
- package/dist/inbound-mail-foundation/handlers/mark-credential-stored.write.js +38 -0
- package/dist/inbound-mail-foundation/handlers/message-content.d.ts +70 -0
- package/dist/inbound-mail-foundation/handlers/message-content.js +137 -0
- package/dist/inbound-mail-foundation/handlers/message-content.query.d.ts +19 -0
- package/dist/inbound-mail-foundation/handlers/message-content.query.js +59 -0
- package/dist/inbound-mail-foundation/handlers/message-detail.query.d.ts +3 -0
- package/dist/inbound-mail-foundation/handlers/message-detail.query.js +23 -0
- package/dist/inbound-mail-foundation/handlers/reactivate-account.write.d.ts +8 -0
- package/dist/inbound-mail-foundation/handlers/reactivate-account.write.js +84 -0
- package/dist/inbound-mail-foundation/handlers/retry-quarantined-message.write.d.ts +8 -0
- package/dist/inbound-mail-foundation/handlers/retry-quarantined-message.write.js +34 -0
- package/dist/inbound-mail-foundation/handlers/scope-visibility.d.ts +10 -2
- package/dist/inbound-mail-foundation/handlers/scope-visibility.js +27 -8
- package/dist/inbound-mail-foundation/handlers/set-trusted-authserv-id.write.d.ts +13 -0
- package/dist/inbound-mail-foundation/handlers/set-trusted-authserv-id.write.js +54 -0
- package/dist/inbound-mail-foundation/handlers/thread-rollup.d.ts +24 -0
- package/dist/inbound-mail-foundation/handlers/thread-rollup.js +98 -0
- package/dist/inbound-mail-foundation/handlers/trusted-authserv-id.d.ts +3 -0
- package/dist/inbound-mail-foundation/handlers/trusted-authserv-id.js +3 -0
- package/dist/inbound-mail-foundation/handlers/update-account.write.d.ts +13 -3
- package/dist/inbound-mail-foundation/handlers/update-account.write.js +61 -45
- package/dist/inbound-mail-foundation/i18n.js +72 -3
- package/dist/inbound-mail-foundation/inbound-oauth-flow.d.ts +43 -0
- package/dist/inbound-mail-foundation/inbound-oauth-flow.js +1 -0
- package/dist/inbound-mail-foundation/index.d.ts +19 -6
- package/dist/inbound-mail-foundation/index.js +17 -6
- package/dist/inbound-mail-foundation/ingest-failures.d.ts +77 -0
- package/dist/inbound-mail-foundation/ingest-failures.js +79 -0
- package/dist/inbound-mail-foundation/ingest-payload.d.ts +7 -0
- package/dist/inbound-mail-foundation/ingest-payload.js +34 -0
- package/dist/inbound-mail-foundation/mail-roles.d.ts +21 -0
- package/dist/inbound-mail-foundation/mail-roles.js +83 -0
- package/dist/inbound-mail-foundation/normalize-inbound-message.d.ts +17 -0
- package/dist/inbound-mail-foundation/normalize-inbound-message.js +90 -0
- package/dist/inbound-mail-foundation/oauth-access-token.d.ts +3 -1
- package/dist/inbound-mail-foundation/oauth-access-token.js +13 -2
- package/dist/inbound-mail-foundation/outbound-attachment-access.d.ts +5 -0
- package/dist/inbound-mail-foundation/outbound-attachment-access.js +16 -0
- package/dist/inbound-mail-foundation/outbound-attachments.d.ts +18 -0
- package/dist/inbound-mail-foundation/outbound-attachments.js +77 -0
- package/dist/inbound-mail-foundation/outbound-mail.d.ts +15 -1
- package/dist/inbound-mail-foundation/outbound-mail.js +4 -0
- package/dist/inbound-mail-foundation/probe.js +1 -1
- package/dist/inbound-mail-foundation/projection.d.ts +28 -0
- package/dist/inbound-mail-foundation/projection.js +25 -3
- package/dist/inbound-mail-foundation/provider-errors.d.ts +28 -0
- package/dist/inbound-mail-foundation/provider-errors.js +66 -0
- package/dist/inbound-mail-foundation/quarantine-entities.d.ts +61 -0
- package/dist/inbound-mail-foundation/quarantine-entities.js +47 -0
- package/dist/inbound-mail-foundation/quarantine-header-import.d.ts +9 -0
- package/dist/inbound-mail-foundation/quarantine-header-import.js +53 -0
- package/dist/inbound-mail-foundation/quarantine-retry.d.ts +13 -0
- package/dist/inbound-mail-foundation/quarantine-retry.js +97 -0
- package/dist/inbound-mail-foundation/quarantine-screens.d.ts +4 -0
- package/dist/inbound-mail-foundation/quarantine-screens.js +57 -0
- package/dist/inbound-mail-foundation/quarantine.d.ts +13 -0
- package/dist/inbound-mail-foundation/quarantine.js +46 -0
- package/dist/inbound-mail-foundation/retention-job.d.ts +2 -0
- package/dist/inbound-mail-foundation/retention-job.js +62 -0
- package/dist/inbound-mail-foundation/retention-sweep.d.ts +4 -0
- package/dist/inbound-mail-foundation/retention-sweep.js +35 -8
- package/dist/inbound-mail-foundation/screens.d.ts +13 -2
- package/dist/inbound-mail-foundation/screens.js +216 -89
- package/dist/inbound-mail-foundation/send-from-account.d.ts +11 -1
- package/dist/inbound-mail-foundation/send-from-account.js +19 -2
- package/dist/inbound-mail-foundation/sender-auth.d.ts +63 -0
- package/dist/inbound-mail-foundation/sender-auth.js +198 -0
- package/dist/inbound-mail-foundation/supervisor-ingest.d.ts +43 -0
- package/dist/inbound-mail-foundation/supervisor-ingest.js +195 -0
- package/dist/inbound-mail-foundation/sync-account-now.d.ts +22 -0
- package/dist/inbound-mail-foundation/sync-account-now.js +29 -0
- package/dist/inbound-mail-foundation/sync-cursor-store.d.ts +9 -0
- package/dist/inbound-mail-foundation/sync-cursor-store.js +54 -0
- package/dist/inbound-mail-foundation/syncable-accounts.d.ts +16 -0
- package/dist/inbound-mail-foundation/syncable-accounts.js +79 -0
- package/dist/inbound-mail-foundation/tenant-destroy-hook.js +5 -1
- package/dist/inbound-mail-foundation/types.d.ts +61 -62
- package/dist/inbound-mail-foundation/types.js +0 -54
- package/dist/inbound-mail-foundation/wake-consumer.d.ts +2 -0
- package/dist/inbound-mail-foundation/wake-consumer.js +30 -0
- package/dist/inbound-mail-foundation/watch-catch-up.d.ts +19 -0
- package/dist/inbound-mail-foundation/watch-catch-up.js +33 -0
- package/dist/inbound-mail-foundation/watch-lease.d.ts +15 -0
- package/dist/inbound-mail-foundation/watch-lease.js +81 -0
- package/dist/inbound-mail-foundation/watch-supervisor-types.d.ts +83 -0
- package/dist/inbound-mail-foundation/watch-supervisor-types.js +1 -0
- package/dist/inbound-mail-foundation/watch-supervisor.d.ts +1 -53
- package/dist/inbound-mail-foundation/watch-supervisor.js +123 -290
- package/dist/inbound-mail-foundation/web/client-plugin.d.ts +14 -0
- package/dist/inbound-mail-foundation/web/client-plugin.js +40 -0
- package/dist/inbound-mail-foundation/web/constants.d.ts +5 -0
- package/dist/inbound-mail-foundation/web/constants.js +6 -0
- package/dist/inbound-mail-foundation/web/index.d.ts +1 -0
- package/dist/inbound-mail-foundation/web/index.js +1 -0
- package/dist/inbound-provider-imap/connect-mailbox.d.ts +21 -3
- package/dist/inbound-provider-imap/connect-mailbox.js +69 -20
- package/dist/inbound-provider-imap/connect-my-mailbox.d.ts +13 -0
- package/dist/inbound-provider-imap/connect-my-mailbox.js +25 -0
- package/dist/inbound-provider-imap/constants.d.ts +2 -1
- package/dist/inbound-provider-imap/constants.js +2 -1
- package/dist/inbound-provider-imap/credential-document.js +2 -2
- package/dist/inbound-provider-imap/download-batch.d.ts +6 -0
- package/dist/inbound-provider-imap/download-batch.js +24 -0
- package/dist/inbound-provider-imap/feature.d.ts +2 -2
- package/dist/inbound-provider-imap/feature.js +49 -37
- package/dist/inbound-provider-imap/fetch-content.d.ts +4 -0
- package/dist/inbound-provider-imap/fetch-content.js +68 -0
- package/dist/inbound-provider-imap/i18n.js +8 -1
- package/dist/inbound-provider-imap/imap-client.d.ts +27 -23
- package/dist/inbound-provider-imap/imap-client.js +30 -68
- package/dist/inbound-provider-imap/index.d.ts +2 -1
- package/dist/inbound-provider-imap/index.js +2 -1
- package/dist/inbound-provider-imap/mime-content.d.ts +11 -0
- package/dist/inbound-provider-imap/mime-content.js +66 -0
- package/dist/inbound-provider-imap/parse-message.d.ts +35 -0
- package/dist/inbound-provider-imap/parse-message.js +113 -0
- package/dist/inbound-provider-imap/reconnect-account.d.ts +2 -0
- package/dist/inbound-provider-imap/reconnect-account.js +4 -6
- package/dist/inbound-provider-imap/reconnect-mailbox.d.ts +4 -2
- package/dist/inbound-provider-imap/reconnect-mailbox.js +35 -12
- package/dist/inbound-provider-imap/reconnect-prefill.query.d.ts +2 -1
- package/dist/inbound-provider-imap/reconnect-prefill.query.js +11 -8
- package/dist/inbound-provider-imap/screens.d.ts +6 -2
- package/dist/inbound-provider-imap/screens.js +171 -109
- package/dist/inbound-provider-imap/send-mail.d.ts +2 -2
- package/dist/inbound-provider-imap/send-mail.js +8 -1
- package/dist/inbound-provider-imap/sender-auth-headers.d.ts +3 -0
- package/dist/inbound-provider-imap/sender-auth-headers.js +18 -0
- package/dist/inbound-provider-inmemory/feature.d.ts +15 -0
- package/dist/inbound-provider-inmemory/feature.js +57 -2
- package/dist/inbound-provider-inmemory/index.d.ts +1 -1
- package/dist/inbound-provider-inmemory/index.js +1 -1
- package/dist/jobs/handlers/consumer.write.d.ts +4 -4
- package/dist/jobs/handlers/retry.write.d.ts +1 -1
- package/dist/jobs/handlers/trigger.write.d.ts +1 -1
- package/dist/managed-pages/handlers/set.write.d.ts +1 -1
- package/dist/managed-pages/web/i18n.js +1 -0
- package/dist/personal-access-tokens/handlers/create.write.d.ts +1 -1
- package/dist/personal-access-tokens/handlers/revoke.write.d.ts +1 -1
- package/dist/readiness/handlers/run-probes.write.d.ts +1 -1
- package/dist/secrets/handlers/delete.write.d.ts +1 -1
- package/dist/secrets/handlers/set.write.d.ts +1 -1
- package/dist/sessions/handlers/revoke-all-for-user.write.d.ts +1 -1
- package/dist/sessions/handlers/revoke-all-others.write.d.ts +1 -1
- package/dist/sessions/handlers/revoke.write.d.ts +1 -1
- package/dist/subscription-paddle/checkout-config.query.d.ts +3 -0
- package/dist/subscription-paddle/checkout-config.query.js +14 -0
- package/dist/subscription-paddle/checkout-methods.d.ts +6 -0
- package/dist/subscription-paddle/checkout-methods.js +85 -0
- package/dist/subscription-paddle/checkout-page.d.ts +19 -0
- package/dist/subscription-paddle/checkout-page.js +126 -0
- package/dist/subscription-paddle/client.d.ts +24 -0
- package/dist/subscription-paddle/client.js +60 -0
- package/dist/subscription-paddle/constants.d.ts +16 -0
- package/dist/subscription-paddle/constants.js +25 -0
- package/dist/subscription-paddle/feature.d.ts +49 -0
- package/dist/subscription-paddle/feature.js +192 -0
- package/dist/subscription-paddle/index.d.ts +2 -0
- package/dist/subscription-paddle/index.js +4 -0
- package/dist/subscription-paddle/plan-switch-methods.d.ts +6 -0
- package/dist/subscription-paddle/plan-switch-methods.js +114 -0
- package/dist/subscription-paddle/price-methods.d.ts +15 -0
- package/dist/subscription-paddle/price-methods.js +105 -0
- package/dist/subscription-paddle/runtime.d.ts +42 -0
- package/dist/subscription-paddle/runtime.js +109 -0
- package/dist/subscription-paddle/subscription-state.d.ts +34 -0
- package/dist/subscription-paddle/subscription-state.js +48 -0
- package/dist/subscription-paddle/tenant-binding.d.ts +8 -0
- package/dist/subscription-paddle/tenant-binding.js +26 -0
- package/dist/subscription-paddle/verify-webhook.d.ts +4 -0
- package/dist/subscription-paddle/verify-webhook.js +55 -0
- package/dist/subscription-paddle/webhook-events.d.ts +9 -0
- package/dist/subscription-paddle/webhook-events.js +124 -0
- package/dist/template-resolver/handlers/collection-item.query.js +2 -2
- package/dist/template-resolver/handlers/collection-list.query.js +4 -2
- package/dist/template-resolver/handlers/collection-set.write.d.ts +1 -1
- package/dist/template-resolver/handlers/collection-shared.d.ts +11 -0
- package/dist/template-resolver/handlers/collection-shared.js +16 -0
- package/dist/template-resolver/handlers/copy-locale.write.d.ts +1 -1
- package/dist/template-resolver/handlers/discard-draft.write.d.ts +2 -2
- package/dist/template-resolver/handlers/import-bundle-system.write.d.ts +1 -1
- package/dist/template-resolver/handlers/import-bundle.write.d.ts +1 -1
- package/dist/template-resolver/handlers/patch-draft.write.d.ts +1 -1
- package/dist/template-resolver/handlers/reset-to-system.write.d.ts +1 -1
- package/dist/template-resolver/handlers/resource-link-pdf.write.d.ts +1 -1
- package/dist/template-resolver/handlers/resource-remove.write.d.ts +1 -1
- package/dist/template-resolver/handlers/resource-upload.write.d.ts +1 -1
- package/dist/template-resolver/handlers/send-test.write.d.ts +1 -1
- package/dist/template-resolver/handlers/set.write.d.ts +1 -1
- package/dist/template-resolver/handlers/toggle-status.write.d.ts +4 -4
- package/dist/template-resolver/handlers/upsert-system.write.d.ts +1 -1
- package/dist/template-resolver/handlers/upsert-tenant.write.d.ts +1 -1
- package/dist/template-resolver/web/client-plugin.d.ts +4 -0
- package/dist/template-resolver/web/client-plugin.js +134 -52
- package/dist/template-resolver/web/i18n.js +1 -1
- package/dist/tenant/handlers/add-member.write.d.ts +1 -1
- package/dist/tenant/handlers/cancel-invitation.write.d.ts +1 -1
- package/dist/tenant/handlers/create.write.d.ts +1 -1
- package/dist/tenant/handlers/remove-member.write.d.ts +1 -1
- package/dist/tenant/handlers/toggle-enabled.write.d.ts +2 -2
- package/dist/tenant/handlers/update-member-roles.write.d.ts +1 -1
- package/dist/tenant/handlers/update.write.d.ts +1 -1
- package/dist/tenant-handover/handlers/claim.write.d.ts +1 -1
- package/dist/tenant-lifecycle/handlers/cancel-destruction.write.d.ts +1 -1
- package/dist/tenant-lifecycle/handlers/request-destruction.write.d.ts +1 -1
- package/dist/tier-engine/handlers/set-tenant-tier.write.d.ts +1 -1
- package/dist/user/handlers/create.write.d.ts +1 -1
- package/dist/user/handlers/update.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/cancel-deletion.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/confirm-deletion-by-token.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/lift-restriction.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/request-deletion-by-email.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/request-deletion.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/request-export.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/restrict-account.write.d.ts +1 -1
- package/dist/user-data-rights/handlers/run-forget-cleanup.write.d.ts +1 -1
- package/dist/user-data-rights-defaults/hooks/file-ref.userdata-hook.js +2 -1
- package/dist/user-profile/handlers/change-email.write.d.ts +1 -1
- package/dist/waitlist/handlers/export-purge.write.d.ts +2 -2
- package/dist/waitlist/handlers/invite.write.d.ts +1 -1
- package/dist/waitlist/handlers/reject.write.d.ts +1 -1
- package/dist/waitlist/handlers/submit.write.d.ts +1 -1
- package/package.json +33 -17
- package/src/account-security/changes.json +6 -0
- package/src/auth-email-password/changes.json +6 -0
- package/src/billing-foundation/changes.json +30 -0
- package/src/cap-overview/changes.json +6 -0
- package/src/files/changes.json +18 -0
- package/src/inbound-mail-foundation/changes.json +143 -0
- package/src/inbound-provider-imap/changes.json +30 -0
- package/src/jobs/changes.json +18 -0
- package/src/subscription-paddle/changes.json +15 -0
- package/src/template-resolver/changes.json +12 -0
- package/dist/subscription-dodo/client.d.ts +0 -17
- package/dist/subscription-dodo/client.js +0 -31
- package/dist/subscription-dodo/constants.d.ts +0 -12
- package/dist/subscription-dodo/constants.js +0 -19
- package/dist/subscription-dodo/feature.d.ts +0 -37
- package/dist/subscription-dodo/feature.js +0 -144
- package/dist/subscription-dodo/index.d.ts +0 -2
- package/dist/subscription-dodo/index.js +0 -4
- package/dist/subscription-dodo/plugin-methods.d.ts +0 -23
- package/dist/subscription-dodo/plugin-methods.js +0 -260
- package/dist/subscription-dodo/runtime.d.ts +0 -27
- package/dist/subscription-dodo/runtime.js +0 -89
- package/dist/subscription-dodo/verify-webhook.d.ts +0 -37
- package/dist/subscription-dodo/verify-webhook.js +0 -189
- package/src/subscription-dodo/changes.json +0 -14
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
// login of the outgoing server are checked before the transaction opens; only then the account
|
|
3
3
|
// stream and its credential secret are written, both on the request transaction, so a failure
|
|
4
4
|
// leaves neither behind.
|
|
5
|
-
import { InboundAuthError, InboundMailAuthMethods, InboundMailFoundationHandlers, inboundCredentialSecretKey, } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
5
|
+
import { findMailboxByAddress, InboundAuthError, InboundMailAccountStatuses, InboundMailAuthMethods, InboundMailFoundationHandlers, inboundCredentialSecretKey, } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
6
6
|
import { requireSecretsContext } from "@cosmicdrift/kumiko-bundled-features/secrets";
|
|
7
|
-
import {
|
|
7
|
+
import { ROLES } from "@cosmicdrift/kumiko-framework/auth";
|
|
8
|
+
import { createSystemUser, defineWriteHandler, } from "@cosmicdrift/kumiko-framework/engine";
|
|
8
9
|
import { UnprocessableError, writeFailure } from "@cosmicdrift/kumiko-framework/errors";
|
|
9
10
|
import * as z from "zod";
|
|
10
11
|
import { IMAP_CONNECT_ERRORS, IMAP_PROVIDER_KEY, SMTP_CONNECT_ERRORS } from "./constants.js";
|
|
@@ -22,7 +23,14 @@ export const connectMailboxSchema = imapCredentialDocumentSchema
|
|
|
22
23
|
password: z.string().min(1).max(1000),
|
|
23
24
|
smtpHost: z.union([z.literal(""), smtpHostSchema]).nullish(),
|
|
24
25
|
smtpPort: z.number().int().min(1).max(65535),
|
|
26
|
+
trustedAuthservId: z.string().trim().max(255).nullish(),
|
|
25
27
|
});
|
|
28
|
+
function isReopenableByThisForm(existing, ownerUserId) {
|
|
29
|
+
return (existing.status === InboundMailAccountStatuses.disconnected &&
|
|
30
|
+
existing.provider === IMAP_PROVIDER_KEY &&
|
|
31
|
+
existing.authMethod === InboundMailAuthMethods.password &&
|
|
32
|
+
existing.ownerUserId === ownerUserId);
|
|
33
|
+
}
|
|
26
34
|
const connectedAccountSchema = z.object({ accountId: z.string() });
|
|
27
35
|
// Matched on the mapped error text, which also carries the host, so only markers no host name
|
|
28
36
|
// contains: a bare "tls" or "ssl" would misread a host like ssl.example.com.
|
|
@@ -30,7 +38,6 @@ const connectedAccountSchema = z.object({ accountId: z.string() });
|
|
|
30
38
|
const TLS_FAILURE = /certificate|self[- ]signed|wrong[ _]version[ _]number|EPROTO|ERR_SSL|ERR_TLS/i;
|
|
31
39
|
// A fixed preview: any slice of the JSON document would expose the host or the user.
|
|
32
40
|
export const CREDENTIAL_PREVIEW = "IMAP login";
|
|
33
|
-
const SECRET_TRANSACTION_REASON = "the credential secret is written on the request transaction so a failed account connect rolls it back too";
|
|
34
41
|
// Most hosters name the outgoing server like the incoming one, or with smtp. for imap.
|
|
35
42
|
export function deriveSmtpHost(imapHost) {
|
|
36
43
|
return /^imap\./i.test(imapHost) ? `smtp.${imapHost.slice("imap.".length)}` : imapHost;
|
|
@@ -91,36 +98,78 @@ export async function checkMailboxLogin(doc, log) {
|
|
|
91
98
|
}
|
|
92
99
|
return { isSuccess: true, data: null };
|
|
93
100
|
}
|
|
94
|
-
export const
|
|
101
|
+
export const SECRET_TRANSACTION_REASON = "the credential secret is written on the request transaction so a failed account connect rolls it back too";
|
|
102
|
+
// Shared by the admin form (shared mailbox) and the member form (personal mailbox, owner = caller).
|
|
103
|
+
// A disconnected password mailbox of the same scope and owner is brought back under its old account id,
|
|
104
|
+
// so cursor, seen anchors and threads survive; anything else keeps connect-account's conflict answer.
|
|
105
|
+
export async function connectPasswordMailbox(handlerName, event, ctx, mailbox, scope) {
|
|
106
|
+
const { displayName, address, credentialDocument } = mailbox;
|
|
107
|
+
const ownerUserId = scope === "user" ? event.user.id : null;
|
|
108
|
+
const existing = await findMailboxByAddress(ctx, event.user.tenantId, address);
|
|
109
|
+
const reopened = existing !== undefined && isReopenableByThisForm(existing, ownerUserId);
|
|
110
|
+
let accountId;
|
|
111
|
+
if (reopened) {
|
|
112
|
+
accountId = existing.id;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
const accountFields = {
|
|
116
|
+
provider: IMAP_PROVIDER_KEY,
|
|
117
|
+
authMethod: InboundMailAuthMethods.password,
|
|
118
|
+
displayName,
|
|
119
|
+
address,
|
|
120
|
+
scope,
|
|
121
|
+
};
|
|
122
|
+
// connect-account is admin-only, so a member's personal mailbox goes through the system identity
|
|
123
|
+
// with the owner taken from this session, like the OAuth callback does.
|
|
124
|
+
const connected = scope === "user"
|
|
125
|
+
? await ctx.dispatch.writeAs(createSystemUser(ctx.user.tenantId, [ROLES.SystemAdmin]), InboundMailFoundationHandlers.connectAccount, { ...accountFields, ownerUserIdOverride: event.user.id })
|
|
126
|
+
: await ctx.dispatch.write(InboundMailFoundationHandlers.connectAccount, accountFields);
|
|
127
|
+
if (!connected.isSuccess)
|
|
128
|
+
return connected;
|
|
129
|
+
accountId = connectedAccountSchema.parse(connected.data).accountId;
|
|
130
|
+
}
|
|
131
|
+
const secrets = requireSecretsContext({ secrets: ctx.services.secrets, user: ctx.user }, handlerName).withRunner(ctx.db.unsafeRaw());
|
|
132
|
+
await secrets.set(event.user.tenantId, inboundCredentialSecretKey(accountId), JSON.stringify(credentialDocument), {
|
|
133
|
+
redact: () => CREDENTIAL_PREVIEW,
|
|
134
|
+
hint: `IMAP credentials for inbound mail account ${accountId}`,
|
|
135
|
+
updatedBy: event.user.id,
|
|
136
|
+
});
|
|
137
|
+
if (reopened) {
|
|
138
|
+
// Secret first: reactivating a disconnected account requires the credential to exist.
|
|
139
|
+
const reactivated = await ctx.dispatch.write(InboundMailFoundationHandlers.reactivateAccount, {
|
|
140
|
+
accountId,
|
|
141
|
+
});
|
|
142
|
+
if (!reactivated.isSuccess)
|
|
143
|
+
return reactivated;
|
|
144
|
+
}
|
|
145
|
+
return { isSuccess: true, data: { accountId } };
|
|
146
|
+
}
|
|
147
|
+
export const createConnectMailboxHandler = ({ adminRoles }) => defineWriteHandler({
|
|
95
148
|
name: "connect-mailbox",
|
|
96
149
|
description: "Connects a shared IMAP mailbox with a password over implicit TLS: checks the IMAP login and the SMTP login of the outgoing server (given, or derived from the IMAP host) first, then creates the mail account and stores both servers, user and password as its credential secret in one step.",
|
|
97
150
|
// The payload carries the plaintext password: as a tool call it would reach the model provider.
|
|
98
151
|
agent: { expose: false },
|
|
99
152
|
schema: connectMailboxSchema,
|
|
100
|
-
access: { roles: [
|
|
153
|
+
access: { roles: [...adminRoles] },
|
|
101
154
|
// Each call opens a connection to a host the caller picks; the cap keeps the form from being
|
|
102
155
|
// used to scan ports or to guess passwords at someone else's mail server.
|
|
103
156
|
rateLimit: { per: "tenant+handler", limit: 10, windowSeconds: 600 },
|
|
104
157
|
escapeHatch: { grants: ["unsafeRaw"], reason: SECRET_TRANSACTION_REASON },
|
|
105
158
|
beforeTransaction: (event, ctx) => checkMailboxLogin(credentialDocumentOf(event.payload), ctx.obs.log),
|
|
106
159
|
handler: async (event, ctx) => {
|
|
107
|
-
const { displayName, address } = event.payload;
|
|
108
|
-
const connected = await ctx
|
|
109
|
-
provider: IMAP_PROVIDER_KEY,
|
|
110
|
-
authMethod: InboundMailAuthMethods.password,
|
|
111
|
-
displayName,
|
|
112
|
-
address,
|
|
113
|
-
scope: "shared",
|
|
114
|
-
});
|
|
160
|
+
const { displayName, address, trustedAuthservId } = event.payload;
|
|
161
|
+
const connected = await connectPasswordMailbox("connect-mailbox", event, ctx, { displayName, address, credentialDocument: credentialDocumentOf(event.payload) }, "shared");
|
|
115
162
|
if (!connected.isSuccess)
|
|
116
163
|
return connected;
|
|
117
|
-
const { accountId } =
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
164
|
+
const { accountId } = connected.data;
|
|
165
|
+
if (trustedAuthservId) {
|
|
166
|
+
const trusted = await ctx.dispatch.write(InboundMailFoundationHandlers.setTrustedAuthservId, {
|
|
167
|
+
accountId,
|
|
168
|
+
trustedAuthservId,
|
|
169
|
+
});
|
|
170
|
+
if (!trusted.isSuccess)
|
|
171
|
+
return trusted;
|
|
172
|
+
}
|
|
124
173
|
return { isSuccess: true, data: { accountId } };
|
|
125
174
|
},
|
|
126
175
|
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { InboundMailRoles } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
2
|
+
export declare const createConnectMyMailboxHandler: ({ memberRoles }: InboundMailRoles) => import("@cosmicdrift/kumiko-types/define-handler").WriteHandlerDefinition<"connect-my-mailbox", import("zod").ZodObject<{
|
|
3
|
+
host: import("zod").ZodString;
|
|
4
|
+
port: import("zod").ZodDefault<import("zod").ZodNumber>;
|
|
5
|
+
user: import("zod").ZodString;
|
|
6
|
+
displayName: import("zod").ZodString;
|
|
7
|
+
address: import("zod").ZodEmail;
|
|
8
|
+
password: import("zod").ZodString;
|
|
9
|
+
smtpHost: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodUnion<readonly [import("zod").ZodLiteral<"">, import("zod").ZodString]>>>;
|
|
10
|
+
smtpPort: import("zod").ZodNumber;
|
|
11
|
+
}, import("zod/v4/core").$strip>, {
|
|
12
|
+
accountId: string;
|
|
13
|
+
}, import("@cosmicdrift/kumiko-types/event-type-map").KumikoEventTypeMap, null, undefined>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// connect-my-mailbox: a member connects a personal password IMAP mailbox (owner = the caller).
|
|
2
|
+
// Same login check and secret write as connect-mailbox; the sender-check policy is tenant-wide and
|
|
3
|
+
// stays with the admin form.
|
|
4
|
+
import { defineWriteHandler } from "@cosmicdrift/kumiko-framework/engine";
|
|
5
|
+
import { checkMailboxLogin, connectMailboxSchema, connectPasswordMailbox, credentialDocumentOf, SECRET_TRANSACTION_REASON, } from "./connect-mailbox.js";
|
|
6
|
+
const connectMyMailboxSchema = connectMailboxSchema.omit({ trustedAuthservId: true });
|
|
7
|
+
const MY_MAILBOX_ESCAPE_REASON = `${SECRET_TRANSACTION_REASON}; the account is created with writeAs(system) on connect-account, which is admin-only, and the owner comes from the caller's session`;
|
|
8
|
+
export const createConnectMyMailboxHandler = ({ memberRoles }) => defineWriteHandler({
|
|
9
|
+
name: "connect-my-mailbox",
|
|
10
|
+
description: "Connects a personal IMAP mailbox of the caller with a password over implicit TLS: checks the IMAP login and the SMTP login of the outgoing server first, then creates the mail account owned by the caller and stores both servers, user and password as its credential secret in one step. A disconnected personal mailbox of the caller with the same address is reactivated under its old account id.",
|
|
11
|
+
// The payload carries the plaintext password: as a tool call it would reach the model provider.
|
|
12
|
+
agent: { expose: false },
|
|
13
|
+
schema: connectMyMailboxSchema,
|
|
14
|
+
access: { roles: [...memberRoles] },
|
|
15
|
+
// Each call opens a connection to a host the caller picks; per user, because any member may call it.
|
|
16
|
+
rateLimit: { per: "user", limit: 10, windowSeconds: 600 },
|
|
17
|
+
// connect-account is admin-only; the personal mailbox is created through the system identity. The owner
|
|
18
|
+
// is always event.user.id from the session, never a payload field.
|
|
19
|
+
escapeHatch: { grants: ["unsafeRaw", "systemIdentity"], reason: MY_MAILBOX_ESCAPE_REASON },
|
|
20
|
+
beforeTransaction: (event, ctx) => checkMailboxLogin(credentialDocumentOf(event.payload), ctx.obs.log),
|
|
21
|
+
handler: async (event, ctx) => {
|
|
22
|
+
const { displayName, address } = event.payload;
|
|
23
|
+
return connectPasswordMailbox("connect-my-mailbox", event, ctx, { displayName, address, credentialDocument: credentialDocumentOf(event.payload) }, "user");
|
|
24
|
+
},
|
|
25
|
+
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export declare const FEATURE_NAME = "inbound-provider-imap";
|
|
2
|
-
export
|
|
2
|
+
export { IMAP_PROVIDER_KEY } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
3
3
|
export declare const ImapHandlers: {
|
|
4
4
|
readonly connectMailbox: "inbound-provider-imap:write:connect-mailbox";
|
|
5
|
+
readonly connectMyMailbox: "inbound-provider-imap:write:connect-my-mailbox";
|
|
5
6
|
readonly reconnectMailbox: "inbound-provider-imap:write:reconnect-mailbox";
|
|
6
7
|
};
|
|
7
8
|
export declare const ImapQueries: {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export const FEATURE_NAME = "inbound-provider-imap";
|
|
2
|
-
export
|
|
2
|
+
export { IMAP_PROVIDER_KEY } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
3
3
|
export const ImapHandlers = {
|
|
4
4
|
connectMailbox: "inbound-provider-imap:write:connect-mailbox",
|
|
5
|
+
connectMyMailbox: "inbound-provider-imap:write:connect-my-mailbox",
|
|
5
6
|
reconnectMailbox: "inbound-provider-imap:write:reconnect-mailbox",
|
|
6
7
|
};
|
|
7
8
|
export const ImapQueries = {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
// smtpHost is the outgoing server for sending from the mailbox, with the same user and password
|
|
19
19
|
// over implicit TLS. Documents written before sending existed have none: sending reports
|
|
20
20
|
// "not set up" instead of guessing a host.
|
|
21
|
-
import { InboundAuthError, inboundCredentialSecretKey, } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
21
|
+
import { InboundAuthError, InboundCredentialNotStoredError, inboundCredentialSecretKey, } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
22
22
|
import { requireSecretsContext } from "@cosmicdrift/kumiko-bundled-features/secrets";
|
|
23
23
|
import * as z from "zod";
|
|
24
24
|
import { FEATURE_NAME, SMTP_SUBMISSION_PORT } from "./constants.js";
|
|
@@ -60,7 +60,7 @@ export async function readCredentialDocument(ctx, account) {
|
|
|
60
60
|
const secrets = requireSecretsContext({ secrets: ctx.secrets, auditUserId: ctx.auditUserId }, FEATURE_NAME);
|
|
61
61
|
const secret = await secrets.get(account.tenantId, inboundCredentialSecretKey(account.id));
|
|
62
62
|
if (!secret) {
|
|
63
|
-
throw new
|
|
63
|
+
throw new InboundCredentialNotStoredError(`${FEATURE_NAME}: no credential document in secret slot for account ${account.id} — ` +
|
|
64
64
|
`store the IMAP connection JSON under ${inboundCredentialSecretKey(account.id)} first`);
|
|
65
65
|
}
|
|
66
66
|
const parsed = parseImapCredentialDocument(secret.reveal());
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { RawInboundMessage, RejectedInboundMessage } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
2
|
+
import type { ImapFlow } from "imapflow";
|
|
3
|
+
export declare function downloadBatch(client: ImapFlow, batch: readonly number[], uidValidity: string, trustedAuthservId: string | null): Promise<{
|
|
4
|
+
readonly messages: RawInboundMessage[];
|
|
5
|
+
readonly rejected: RejectedInboundMessage[];
|
|
6
|
+
}>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { coerceDate, parseOrReject } from "./parse-message.js";
|
|
2
|
+
export async function downloadBatch(client, batch, uidValidity, trustedAuthservId) {
|
|
3
|
+
const messages = [];
|
|
4
|
+
const rejected = [];
|
|
5
|
+
if (batch.length === 0)
|
|
6
|
+
return { messages, rejected };
|
|
7
|
+
for await (const msg of client.fetch(batch.join(","), { uid: true, internalDate: true, source: true, envelope: true }, { uid: true })) {
|
|
8
|
+
if (!msg.source)
|
|
9
|
+
continue;
|
|
10
|
+
const parsed = await parseOrReject({
|
|
11
|
+
source: msg.source,
|
|
12
|
+
uid: msg.uid,
|
|
13
|
+
uidValidity,
|
|
14
|
+
internalDate: coerceDate(msg.internalDate ?? undefined),
|
|
15
|
+
envelope: msg.envelope,
|
|
16
|
+
trustedAuthservId,
|
|
17
|
+
});
|
|
18
|
+
if ("message" in parsed)
|
|
19
|
+
messages.push(parsed.message);
|
|
20
|
+
else
|
|
21
|
+
rejected.push(parsed.rejected);
|
|
22
|
+
}
|
|
23
|
+
return { messages, rejected };
|
|
24
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type InboundMailProviderPlugin } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
1
|
+
import { type InboundMailProviderPlugin, type InboundMailRoleOptions } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
2
2
|
export { IMAP_PROVIDER_KEY } from "./constants.ts";
|
|
3
3
|
export { setImapMailHostLookup } from "./imap-client.ts";
|
|
4
4
|
/** Exported for the live test (imap-live.integration.test.ts) —
|
|
5
5
|
* applications use the feature, never the plugin directly. */
|
|
6
6
|
export declare const imapInboundMailPlugin: InboundMailProviderPlugin;
|
|
7
|
-
export declare function createInboundProviderImapFeature(): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
7
|
+
export declare function createInboundProviderImapFeature(options?: InboundMailRoleOptions): import("@cosmicdrift/kumiko-types/feature").FeatureDefinition & {
|
|
8
8
|
readonly exports: void;
|
|
9
9
|
};
|
|
@@ -23,27 +23,36 @@
|
|
|
23
23
|
// (credential-document.ts), not tenant configuration, because one tenant
|
|
24
24
|
// can have multiple accounts with different hosts.
|
|
25
25
|
import { mailAllowedPrivateHostsEnvSchema } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
|
|
26
|
-
import { INBOUND_MAIL_PROVIDER_EXTENSION, } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
26
|
+
import { assertRolesMatchFoundation, INBOUND_MAIL_PROVIDER_EXTENSION, resolveInboundMailRoles, roleDedupeOptions, } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
27
27
|
import { defineFeature } from "@cosmicdrift/kumiko-framework/engine";
|
|
28
28
|
import { instantToLegacyDate } from "@cosmicdrift/kumiko-framework/time";
|
|
29
29
|
import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
|
|
30
|
-
import {
|
|
30
|
+
import { createConnectMailboxHandler } from "./connect-mailbox.js";
|
|
31
|
+
import { createConnectMyMailboxHandler } from "./connect-my-mailbox.js";
|
|
31
32
|
import { FEATURE_NAME, IMAP_PROVIDER_KEY } from "./constants.js";
|
|
32
33
|
import { readCredentialDocument } from "./credential-document.js";
|
|
34
|
+
import { downloadBatch } from "./download-batch.js";
|
|
35
|
+
import { fetchMessageContent } from "./fetch-content.js";
|
|
33
36
|
import { INBOUND_PROVIDER_IMAP_I18N } from "./i18n.js";
|
|
34
|
-
import { assertUidValidity,
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
37
|
+
import { assertUidValidity, closeOnAbort, connectOnce, createImapClient, IMAP_MAILBOX, imapMailHostGuard, mapImapError, parseImapCursor, } from "./imap-client.js";
|
|
38
|
+
import { buildProviderMessageId, coerceDate, parseOrReject } from "./parse-message.js";
|
|
39
|
+
import { createReconnectMailboxHandler } from "./reconnect-mailbox.js";
|
|
40
|
+
import { createReconnectPrefillQuery } from "./reconnect-prefill.query.js";
|
|
41
|
+
import { createImapScreens } from "./screens.js";
|
|
38
42
|
import { sendFromImapAccount } from "./send-mail.js";
|
|
39
43
|
export { IMAP_PROVIDER_KEY } from "./constants.js";
|
|
40
44
|
export { setImapMailHostLookup } from "./imap-client.js";
|
|
41
45
|
// =============================================================================
|
|
42
46
|
// fetch — inkrementeller UID-Sync
|
|
43
47
|
// =============================================================================
|
|
48
|
+
async function unknownUidsOf(uids, uidValidity, filterUnknownMessageIds) {
|
|
49
|
+
const unknownIds = await filterUnknownMessageIds(uids.map((uid) => buildProviderMessageId(uidValidity, uid)));
|
|
50
|
+
return uids.filter((uid) => unknownIds.has(buildProviderMessageId(uidValidity, uid)));
|
|
51
|
+
}
|
|
44
52
|
async function fetchMessages(ctx, account, cursor, opts) {
|
|
45
53
|
const doc = await readCredentialDocument(ctx, account);
|
|
46
54
|
const client = await createImapClient(doc, imapMailHostGuard());
|
|
55
|
+
const stopWatchingAbort = closeOnAbort(client, opts.signal);
|
|
47
56
|
let lock;
|
|
48
57
|
try {
|
|
49
58
|
await client.connect();
|
|
@@ -67,27 +76,19 @@ async function fetchMessages(ctx, account, cursor, opts) {
|
|
|
67
76
|
uids = (await client.search({ since: instantToLegacyDate(since) }, { uid: true })) || [];
|
|
68
77
|
}
|
|
69
78
|
uids.sort((a, b) => a - b);
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
source: msg.source,
|
|
80
|
-
uid: msg.uid,
|
|
81
|
-
uidValidity: serverUidValidity,
|
|
82
|
-
internalDate: coerceDate(msg.internalDate ?? undefined),
|
|
83
|
-
}));
|
|
84
|
-
if (msg.uid > maxUid)
|
|
85
|
-
maxUid = msg.uid;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
79
|
+
// Known mails (ingested or quarantined) are not downloaded again; the cursor still moves past them.
|
|
80
|
+
const unknown = opts.filterUnknownMessageIds
|
|
81
|
+
? await unknownUidsOf(uids, serverUidValidity, opts.filterUnknownMessageIds)
|
|
82
|
+
: uids;
|
|
83
|
+
const batch = unknown.slice(0, opts.maxMessages);
|
|
84
|
+
const hasMore = unknown.length > batch.length;
|
|
85
|
+
const { messages, rejected } = await downloadBatch(client, batch, serverUidValidity, account.trustedAuthservId ?? null);
|
|
86
|
+
// From the UIDs, not from what was downloaded: a known or skipped mail must not hold the cursor back.
|
|
87
|
+
const lastUid = Math.max(parsedCursor?.lastUid ?? 0, ...(hasMore ? batch : uids));
|
|
88
88
|
return {
|
|
89
89
|
messages,
|
|
90
|
-
|
|
90
|
+
...(rejected.length > 0 && { rejected }),
|
|
91
|
+
nextCursor: { uidValidity: serverUidValidity, lastUid },
|
|
91
92
|
hasMore,
|
|
92
93
|
};
|
|
93
94
|
}
|
|
@@ -95,6 +96,7 @@ async function fetchMessages(ctx, account, cursor, opts) {
|
|
|
95
96
|
throw err instanceof Error && "kind" in err ? err : mapImapError(err, doc.host);
|
|
96
97
|
}
|
|
97
98
|
finally {
|
|
99
|
+
stopWatchingAbort();
|
|
98
100
|
lock?.release();
|
|
99
101
|
await client.logout().catch(() => { });
|
|
100
102
|
}
|
|
@@ -116,23 +118,29 @@ async function watchMailbox(ctx, account, handlers) {
|
|
|
116
118
|
let nextUid = Number(mailbox.uidNext ?? 1);
|
|
117
119
|
const drainNew = async () => {
|
|
118
120
|
const messages = [];
|
|
121
|
+
const rejected = [];
|
|
119
122
|
let maxSeen = nextUid - 1;
|
|
120
123
|
for await (const msg of client.fetch(`${nextUid}:*`, { uid: true, internalDate: true, source: true }, { uid: true })) {
|
|
121
124
|
// `N:*` gotcha (see fetch): filter out the previous last message.
|
|
122
125
|
if (msg.uid < nextUid || !msg.source)
|
|
123
126
|
continue;
|
|
124
|
-
|
|
127
|
+
const parsed = await parseOrReject({
|
|
125
128
|
source: msg.source,
|
|
126
129
|
uid: msg.uid,
|
|
127
130
|
uidValidity,
|
|
128
131
|
internalDate: coerceDate(msg.internalDate ?? undefined),
|
|
129
|
-
|
|
132
|
+
trustedAuthservId: account.trustedAuthservId ?? null,
|
|
133
|
+
});
|
|
134
|
+
if ("message" in parsed)
|
|
135
|
+
messages.push(parsed.message);
|
|
136
|
+
else
|
|
137
|
+
rejected.push(parsed.rejected);
|
|
130
138
|
if (msg.uid > maxSeen)
|
|
131
139
|
maxSeen = msg.uid;
|
|
132
140
|
}
|
|
133
141
|
nextUid = maxSeen + 1;
|
|
134
|
-
if (messages.length > 0)
|
|
135
|
-
await handlers.onMessages(messages);
|
|
142
|
+
if (messages.length > 0 || rejected.length > 0)
|
|
143
|
+
await handlers.onMessages(messages, rejected);
|
|
136
144
|
};
|
|
137
145
|
client.on("exists", () => {
|
|
138
146
|
// skip: ignore delayed exists events after the watcher has stopped.
|
|
@@ -192,15 +200,17 @@ export const imapInboundMailPlugin = {
|
|
|
192
200
|
verify: async (ctx, account) => connectOnce(await readCredentialDocument(ctx, account), false),
|
|
193
201
|
probe: async (ctx, account) => connectOnce(await readCredentialDocument(ctx, account), true),
|
|
194
202
|
fetch: fetchMessages,
|
|
203
|
+
fetchContent: fetchMessageContent,
|
|
195
204
|
watch: watchMailbox,
|
|
196
205
|
send: sendFromImapAccount,
|
|
197
206
|
// No oauth block: password authentication runs through the credential
|
|
198
207
|
// form (connect-account + Secret-Write); XOAUTH2 token flows belong to
|
|
199
208
|
// the OAuth providers (M365/Gmail).
|
|
200
209
|
};
|
|
201
|
-
export function createInboundProviderImapFeature() {
|
|
210
|
+
export function createInboundProviderImapFeature(options = {}) {
|
|
211
|
+
const roles = resolveInboundMailRoles(options);
|
|
202
212
|
return defineFeature(FEATURE_NAME, (r) => {
|
|
203
|
-
r.describe('Registers the `"imap"` provider for `inbound-mail-foundation` using imapflow — password/app-password auth covers classic IMAP hosts without any OAuth (plus an XOAUTH2 fallback consuming an access token from the secret slot). Incremental sync via a UIDVALIDITY:lastUid cursor (UIDVALIDITY change triggers a cursor-invalid full resync), initial backfill bounded by the foundation backfill window, and live push via IMAP IDLE for the watch supervisor. Tenant admins connect a mailbox through the "Connect mailbox" form on the mail accounts list (`connect-mailbox`
|
|
213
|
+
r.describe('Registers the `"imap"` provider for `inbound-mail-foundation` using imapflow — password/app-password auth covers classic IMAP hosts without any OAuth (plus an XOAUTH2 fallback consuming an access token from the secret slot). Incremental sync via a UIDVALIDITY:lastUid cursor (UIDVALIDITY change triggers a cursor-invalid full resync), initial backfill bounded by the foundation backfill window, and live push via IMAP IDLE for the watch supervisor. Tenant admins connect a shared mailbox through the "Connect mailbox" form on the mail accounts list and members a personal one through the same form on "My mail accounts" (`connect-mailbox` and `connect-my-mailbox` check the IMAP login and the SMTP login of the outgoing server first, then creates the account and its credential secret in one transaction; `reconnect-mailbox` does the same check for an existing mailbox with a sign-in error and overwrites its credential secret); programmatic setups store the per-account connection JSON (host/port/secure/user/password, plus smtpHost/smtpPort for sending) in the account credential secret slot before the first sync. Implements the provider `send`: `sendMailFromAccount` sends over the SMTP server of the mailbox itself (implicit TLS, same login) with the mailbox address as From and stores a copy in its sent folder.');
|
|
204
214
|
r.uiHints({
|
|
205
215
|
displayLabel: "Inbound Mail · IMAP",
|
|
206
216
|
category: "notifications",
|
|
@@ -210,11 +220,13 @@ export function createInboundProviderImapFeature() {
|
|
|
210
220
|
r.requires({ features: ["secrets"] });
|
|
211
221
|
r.envSchema(mailAllowedPrivateHostsEnvSchema);
|
|
212
222
|
r.useExtension(INBOUND_MAIL_PROVIDER_EXTENSION, IMAP_PROVIDER_KEY, imapInboundMailPlugin);
|
|
213
|
-
r.
|
|
214
|
-
r.writeHandler(
|
|
215
|
-
r.
|
|
216
|
-
r.
|
|
217
|
-
r.
|
|
223
|
+
r.bootCheck(({ features }) => assertRolesMatchFoundation(FEATURE_NAME, roles, features));
|
|
224
|
+
r.writeHandler(createConnectMailboxHandler(roles));
|
|
225
|
+
r.writeHandler(createConnectMyMailboxHandler(roles));
|
|
226
|
+
r.writeHandler(createReconnectMailboxHandler(roles));
|
|
227
|
+
r.queryHandler(createReconnectPrefillQuery(roles));
|
|
228
|
+
for (const screen of createImapScreens(roles))
|
|
229
|
+
r.screen(screen);
|
|
218
230
|
r.translations({ keys: INBOUND_PROVIDER_IMAP_I18N });
|
|
219
|
-
}, { dedupeOptions:
|
|
231
|
+
}, { dedupeOptions: roleDedupeOptions(roles) });
|
|
220
232
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { InboundContentFetchResult, InboundMailContext, MailAccountRecord } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
2
|
+
export declare function fetchMessageContent(ctx: InboundMailContext, account: MailAccountRecord, providerMessageIds: readonly string[], opts?: {
|
|
3
|
+
readonly signal?: AbortSignal;
|
|
4
|
+
}): Promise<InboundContentFetchResult>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Re-downloads already imported mails whose content was stored as snippet only. A provider message
|
|
2
|
+
// id is "<uidValidity>:<uid>"; ids from another UIDVALIDITY or gone from the server are "missing"
|
|
3
|
+
// (nothing to reload, ever), mails the parser cannot read are "rejected".
|
|
4
|
+
import { InboundTransientError } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
5
|
+
import { readCredentialDocument } from "./credential-document.js";
|
|
6
|
+
import { closeOnAbort, createImapClient, IMAP_MAILBOX, imapMailHostGuard, mapImapError, } from "./imap-client.js";
|
|
7
|
+
import { coerceDate, parseOrReject } from "./parse-message.js";
|
|
8
|
+
function uidOf(providerMessageId, serverUidValidity) {
|
|
9
|
+
const separator = providerMessageId.lastIndexOf(":");
|
|
10
|
+
if (separator < 0 || providerMessageId.slice(0, separator) !== serverUidValidity)
|
|
11
|
+
return null;
|
|
12
|
+
const uid = Number(providerMessageId.slice(separator + 1));
|
|
13
|
+
return Number.isInteger(uid) && uid > 0 ? uid : null;
|
|
14
|
+
}
|
|
15
|
+
export async function fetchMessageContent(ctx, account, providerMessageIds, opts) {
|
|
16
|
+
const doc = await readCredentialDocument(ctx, account);
|
|
17
|
+
const client = await createImapClient(doc, imapMailHostGuard());
|
|
18
|
+
const stopWatchingAbort = closeOnAbort(client, opts?.signal);
|
|
19
|
+
let lock;
|
|
20
|
+
try {
|
|
21
|
+
await client.connect();
|
|
22
|
+
lock = await client.getMailboxLock(IMAP_MAILBOX);
|
|
23
|
+
const mailbox = client.mailbox;
|
|
24
|
+
if (typeof mailbox === "boolean")
|
|
25
|
+
throw new InboundTransientError("mailbox not open");
|
|
26
|
+
const serverUidValidity = String(mailbox.uidValidity);
|
|
27
|
+
const idByUid = new Map();
|
|
28
|
+
const missing = [];
|
|
29
|
+
for (const id of providerMessageIds) {
|
|
30
|
+
const uid = uidOf(id, serverUidValidity);
|
|
31
|
+
if (uid === null)
|
|
32
|
+
missing.push(id);
|
|
33
|
+
else
|
|
34
|
+
idByUid.set(uid, id);
|
|
35
|
+
}
|
|
36
|
+
const messages = [];
|
|
37
|
+
const rejected = [];
|
|
38
|
+
if (idByUid.size > 0) {
|
|
39
|
+
for await (const msg of client.fetch([...idByUid.keys()].join(","), { uid: true, internalDate: true, source: true, envelope: true }, { uid: true })) {
|
|
40
|
+
if (!msg.source)
|
|
41
|
+
continue;
|
|
42
|
+
const parsed = await parseOrReject({
|
|
43
|
+
source: msg.source,
|
|
44
|
+
uid: msg.uid,
|
|
45
|
+
uidValidity: serverUidValidity,
|
|
46
|
+
internalDate: coerceDate(msg.internalDate ?? undefined),
|
|
47
|
+
envelope: msg.envelope,
|
|
48
|
+
});
|
|
49
|
+
idByUid.delete(msg.uid);
|
|
50
|
+
if ("message" in parsed)
|
|
51
|
+
messages.push(parsed.message);
|
|
52
|
+
else
|
|
53
|
+
rejected.push(parsed.rejected);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// What the server did not return is gone (expunged since the import).
|
|
57
|
+
missing.push(...idByUid.values());
|
|
58
|
+
return { messages, missing, rejected };
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
throw err instanceof Error && "kind" in err ? err : mapImapError(err, doc.host);
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
stopWatchingAbort();
|
|
65
|
+
lock?.release();
|
|
66
|
+
await client.logout().catch(() => { });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IMAP_CONNECT_SCREEN_ID, IMAP_RECONNECT_SCREEN_ID, } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
1
|
+
import { IMAP_CONNECT_SCREEN_ID, IMAP_RECONNECT_SCREEN_ID, MY_IMAP_CONNECT_SCREEN_ID, MY_IMAP_RECONNECT_SCREEN_ID, } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
2
2
|
import { ACTION_FORM_ENTITY } from "@cosmicdrift/kumiko-framework/ui-types";
|
|
3
3
|
import { fieldLabelKey } from "@cosmicdrift/kumiko-renderer/headless";
|
|
4
4
|
import { FEATURE_NAME, IMAP_CONNECT_ERRORS, IMAP_RECONNECT_ERRORS, SMTP_CONNECT_ERRORS, } from "./constants.js";
|
|
@@ -6,6 +6,8 @@ const formFieldKey = (field) => fieldLabelKey(FEATURE_NAME, ACTION_FORM_ENTITY,
|
|
|
6
6
|
export const INBOUND_PROVIDER_IMAP_I18N = {
|
|
7
7
|
[`screen:${IMAP_CONNECT_SCREEN_ID}.title`]: { en: "Connect mailbox" },
|
|
8
8
|
[`screen:${IMAP_RECONNECT_SCREEN_ID}.title`]: { en: "Reconnect mailbox" },
|
|
9
|
+
[`screen:${MY_IMAP_CONNECT_SCREEN_ID}.title`]: { en: "Connect mailbox" },
|
|
10
|
+
[`screen:${MY_IMAP_RECONNECT_SCREEN_ID}.title`]: { en: "Reconnect mailbox" },
|
|
9
11
|
[formFieldKey("accountId")]: { en: "Mailbox" },
|
|
10
12
|
[formFieldKey("displayName")]: { en: "Name" },
|
|
11
13
|
[formFieldKey("address")]: { en: "Email address" },
|
|
@@ -20,6 +22,11 @@ export const INBOUND_PROVIDER_IMAP_I18N = {
|
|
|
20
22
|
"inboundMail.imap.connect.outgoingHint": {
|
|
21
23
|
en: "Replies go out from this address over your own mail server, with the same user name and password. Leave the field empty if the server is called like the IMAP server, with smtp. instead of imap. Usually 587, even when your provider lists 465/SSL.",
|
|
22
24
|
},
|
|
25
|
+
[formFieldKey("trustedAuthservId")]: { en: "Mail server ID" },
|
|
26
|
+
"inboundMail.imap.connect.senderCheck": { en: "Sender check" },
|
|
27
|
+
"inboundMail.imap.connect.senderCheckHint": {
|
|
28
|
+
en: "Identifier of the mail server from the Authentication-Results header, for example mx.example.com. Only with it the system checks whether a sender is genuine. Leave empty if unknown.",
|
|
29
|
+
},
|
|
23
30
|
"inboundMail.imap.connect.submit": { en: "Check and connect" },
|
|
24
31
|
"inboundMail.imap.reconnect.hint": {
|
|
25
32
|
en: "The sign-in is checked before saving. Then the system fetches the mail again.",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type MailHostGuardOptions } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
|
|
2
|
-
import { type
|
|
1
|
+
import { type MailHostGuardOptions, resolveMailConnectTarget } from "@cosmicdrift/kumiko-bundled-features/foundation-shared";
|
|
2
|
+
import { type SyncCursorPayload } from "@cosmicdrift/kumiko-bundled-features/inbound-mail-foundation";
|
|
3
3
|
import { ImapFlow } from "imapflow";
|
|
4
4
|
import type { ImapCredentialDocument } from "./credential-document.ts";
|
|
5
5
|
export declare const IMAP_MAILBOX = "INBOX";
|
|
@@ -7,6 +7,31 @@ export declare const IMAP_HOST_UNREACHABLE_MESSAGE = "IMAP host is not reachable
|
|
|
7
7
|
export declare function setImapMailHostLookup(fn: MailHostGuardOptions["lookupFn"]): void;
|
|
8
8
|
export declare function imapMailHostGuard(): MailHostGuardOptions;
|
|
9
9
|
export declare function createImapClient(doc: ImapCredentialDocument, hostGuard?: MailHostGuardOptions): Promise<ImapFlow>;
|
|
10
|
+
export declare function imapClientOptions(doc: ImapCredentialDocument, target: Awaited<ReturnType<typeof resolveMailConnectTarget>>): {
|
|
11
|
+
host: string;
|
|
12
|
+
port: number;
|
|
13
|
+
secure: boolean;
|
|
14
|
+
servername?: string | undefined;
|
|
15
|
+
tls?: {
|
|
16
|
+
servername: undefined;
|
|
17
|
+
} | undefined;
|
|
18
|
+
auth: {
|
|
19
|
+
user: string;
|
|
20
|
+
pass: string;
|
|
21
|
+
accessToken?: undefined;
|
|
22
|
+
} | {
|
|
23
|
+
pass?: undefined;
|
|
24
|
+
user: string;
|
|
25
|
+
accessToken: string;
|
|
26
|
+
};
|
|
27
|
+
connectionTimeout: number;
|
|
28
|
+
greetingTimeout: number;
|
|
29
|
+
socketTimeout: number;
|
|
30
|
+
logger: false;
|
|
31
|
+
emitLogs: boolean;
|
|
32
|
+
};
|
|
33
|
+
/** Drops the connection when the supervisor abandons the sync, so a hung command does not keep the socket open. */
|
|
34
|
+
export declare function closeOnAbort(client: ImapFlow, signal: AbortSignal | undefined): () => void;
|
|
10
35
|
/** Server-Fehler → typisierte Foundation-Fehlerklassen (Plan §2). */
|
|
11
36
|
export declare function connectOnce(doc: ImapCredentialDocument, examineInbox: boolean): Promise<void>;
|
|
12
37
|
export declare function mapImapError(err: unknown, host: string): Error;
|
|
@@ -19,24 +44,3 @@ export declare function parseImapCursor(cursor: SyncCursorPayload | null): ImapC
|
|
|
19
44
|
* foundation resets the cursor and performs a full resync within the
|
|
20
45
|
* backfill window (deduplication catches duplicates). */
|
|
21
46
|
export declare function assertUidValidity(cursor: ImapCursor | null, serverUidValidity: string): void;
|
|
22
|
-
/** Normalizes the References chain: mailparser returns string | string[]
|
|
23
|
-
* | undefined; when References is missing, In-Reply-To provides the thread
|
|
24
|
-
* anchor. */
|
|
25
|
-
export declare function normalizeReferences(parsed: {
|
|
26
|
-
references?: string | string[];
|
|
27
|
-
inReplyTo?: string;
|
|
28
|
-
}): string[];
|
|
29
|
-
/** imapflow provides internalDate as either a Date or string depending on
|
|
30
|
-
* the code path. The string form is deliberately discarded (no date parsing
|
|
31
|
-
* in feature code, no-date-api); toRawInboundMessage then falls back to the
|
|
32
|
-
* mailparser Date header, which is always a real Date. */
|
|
33
|
-
export declare function coerceDate(d: Date | string | undefined): Date | undefined;
|
|
34
|
-
/** providerMessageId: a UID is unique only within a UIDVALIDITY; together,
|
|
35
|
-
* they form the stable idempotency anchor. */
|
|
36
|
-
export declare function buildProviderMessageId(uidValidity: string, uid: number): string;
|
|
37
|
-
export declare function toRawInboundMessage(args: {
|
|
38
|
-
readonly source: Uint8Array;
|
|
39
|
-
readonly uid: number;
|
|
40
|
-
readonly uidValidity: string;
|
|
41
|
-
readonly internalDate: Date | undefined;
|
|
42
|
-
}): Promise<RawInboundMessage>;
|