From 814f6e62ded6b2dbe8779f7ff7198895f43a1cbb Mon Sep 17 00:00:00 2001 From: Lucas Smith Date: Thu, 26 Mar 2026 13:31:26 +1100 Subject: [PATCH] fix: replace z.string().email() with RFC 5322 compliant ZEmail/zEmail (#2655) --- .../dialogs/assistant-confirmation-dialog.tsx | 3 +- .../dialogs/envelope-distribute-dialog.tsx | 6 +-- .../organisation-member-invite-dialog.tsx | 11 +++-- .../dialogs/sign-field-email-dialog.tsx | 6 +-- .../configure-document-view.types.ts | 3 +- .../embed-direct-template-client-page.tsx | 3 +- .../forms/email-preferences-form.tsx | 3 +- .../app/components/forms/forgot-password.tsx | 3 +- .../forms/send-confirmation-email.tsx | 3 +- apps/remix/app/components/forms/signin.tsx | 3 +- apps/remix/app/components/forms/signup.tsx | 3 +- .../app/components/general/claim-account.tsx | 3 +- .../direct-template-configure-form.tsx | 3 +- .../document-signing-complete-dialog.tsx | 5 +- .../envelope-editor-settings-dialog.tsx | 6 +-- .../admin-document-recipient-item-table.tsx | 3 +- packages/api/v1/schema.ts | 19 ++++---- packages/auth/server/types/email-password.ts | 10 ++-- .../emails/send-confirmation-email.ts | 3 +- .../internal/bulk-send-template.handler.ts | 3 +- packages/lib/types/default-recipients.ts | 4 +- packages/lib/types/document-audit-logs.ts | 3 +- packages/lib/types/document-meta.ts | 3 +- .../lib/types/embed-direct-template-schema.ts | 3 +- .../lib/types/embed-document-sign-schema.ts | 3 +- .../types/embed-multisign-document-schema.ts | 3 +- packages/lib/types/recipient.ts | 3 +- packages/lib/utils/envelope-signing.ts | 3 +- packages/lib/utils/recipients.ts | 4 +- packages/lib/utils/zod.ts | 46 +++++++++++++++++++ .../admin-router/update-recipient.types.ts | 4 +- .../server/admin-router/update-user.types.ts | 4 +- .../distribute-document.types.ts | 3 +- .../create-embedding-document.types.ts | 3 +- .../update-embedding-document.types.ts | 3 +- .../create-organisation-email.types.ts | 4 +- .../envelope-router/create-envelope.types.ts | 5 +- ...reate-organisation-member-invites.types.ts | 4 +- .../update-organisation-settings.types.ts | 3 +- .../find-recipient-suggestions.types.ts | 4 +- .../trpc/server/recipient-router/schema.ts | 16 +++---- packages/trpc/server/team-router/schema.ts | 3 +- .../team-router/update-team-settings.types.ts | 3 +- .../trpc/server/template-router/schema.ts | 7 +-- .../document-flow/add-signers.types.ts | 6 +-- .../document-flow/add-subject.types.ts | 6 +-- packages/ui/primitives/document-flow/types.ts | 3 +- ...d-template-placeholder-recipients.types.ts | 3 +- .../add-template-settings.types.tsx | 6 +-- 49 files changed, 172 insertions(+), 95 deletions(-) create mode 100644 packages/lib/utils/zod.ts diff --git a/apps/remix/app/components/dialogs/assistant-confirmation-dialog.tsx b/apps/remix/app/components/dialogs/assistant-confirmation-dialog.tsx index f148633e9..b6c38e4d0 100644 --- a/apps/remix/app/components/dialogs/assistant-confirmation-dialog.tsx +++ b/apps/remix/app/components/dialogs/assistant-confirmation-dialog.tsx @@ -5,6 +5,7 @@ import { Trans, useLingui } from '@lingui/react/macro'; import { useForm } from 'react-hook-form'; import { z } from 'zod'; +import { zEmail } from '@documenso/lib/utils/zod'; import { Button } from '@documenso/ui/primitives/button'; import { Dialog, @@ -43,7 +44,7 @@ type ConfirmationDialogProps = { const ZNextSignerFormSchema = z.object({ name: z.string().min(1, 'Name is required'), - email: z.string().email('Invalid email address'), + email: zEmail('Invalid email address'), }); type TNextSignerFormSchema = z.infer; diff --git a/apps/remix/app/components/dialogs/envelope-distribute-dialog.tsx b/apps/remix/app/components/dialogs/envelope-distribute-dialog.tsx index 93e59ec67..c72634134 100644 --- a/apps/remix/app/components/dialogs/envelope-distribute-dialog.tsx +++ b/apps/remix/app/components/dialogs/envelope-distribute-dialog.tsx @@ -16,6 +16,7 @@ import { useCurrentOrganisation } from '@documenso/lib/client-only/providers/org import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc'; import { extractDocumentAuthMethods } from '@documenso/lib/utils/document-auth'; import { getRecipientsWithMissingFields } from '@documenso/lib/utils/recipients'; +import { ZEmail } from '@documenso/lib/utils/zod'; import { trpc, trpc as trpcReact } from '@documenso/trpc/react'; import { DocumentSendEmailMessageHelper } from '@documenso/ui/components/document/document-send-email-message-helper'; import { cn } from '@documenso/ui/lib/utils'; @@ -62,10 +63,7 @@ export type EnvelopeDistributeDialogProps = { export const ZEnvelopeDistributeFormSchema = z.object({ meta: z.object({ emailId: z.string().nullable(), - emailReplyTo: z.preprocess( - (val) => (val === '' ? undefined : val), - z.string().email().optional(), - ), + emailReplyTo: z.preprocess((val) => (val === '' ? undefined : val), ZEmail.optional()), subject: z.string(), message: z.string(), distributionMethod: z diff --git a/apps/remix/app/components/dialogs/organisation-member-invite-dialog.tsx b/apps/remix/app/components/dialogs/organisation-member-invite-dialog.tsx index acc52ca08..5126c5c72 100644 --- a/apps/remix/app/components/dialogs/organisation-member-invite-dialog.tsx +++ b/apps/remix/app/components/dialogs/organisation-member-invite-dialog.tsx @@ -17,6 +17,7 @@ import { IS_BILLING_ENABLED, SUPPORT_EMAIL } from '@documenso/lib/constants/app' import { ORGANISATION_MEMBER_ROLE_HIERARCHY } from '@documenso/lib/constants/organisations'; import { ORGANISATION_MEMBER_ROLE_MAP } from '@documenso/lib/constants/organisations-translations'; import { INTERNAL_CLAIM_ID } from '@documenso/lib/types/subscription'; +import { ZEmail } from '@documenso/lib/utils/zod'; import { trpc } from '@documenso/trpc/react'; import { ZCreateOrganisationMemberInvitesRequestSchema } from '@documenso/trpc/server/organisation-router/create-organisation-member-invites.types'; import { cn } from '@documenso/ui/lib/utils'; @@ -94,7 +95,7 @@ type TabTypes = 'INDIVIDUAL' | 'BULK'; const ZImportOrganisationMemberSchema = z.array( z.object({ - email: z.string().email(), + email: ZEmail, organisationRole: z.nativeEnum(OrganisationMemberRole), }), ); @@ -329,12 +330,12 @@ export const OrganisationMemberInviteDialog = ({ onValueChange={(value) => setInvitationType(value as TabTypes)} > - + Invite Members - + Bulk Import @@ -382,7 +383,7 @@ export const OrganisationMemberInviteDialog = ({ )}