diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql index 89b7c6fb52..4d96fd83e3 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql @@ -2655,6 +2655,7 @@ type ImapSmtpCaldavPublicConnectionParams { } type ImapSmtpCaldavPublicConnectionParameters { + name: String IMAP: ImapSmtpCaldavPublicConnectionParams SMTP: ImapSmtpCaldavPublicConnectionParams CALDAV: ImapSmtpCaldavPublicConnectionParams @@ -4660,6 +4661,7 @@ input SendEmailAttachmentInput { } input EmailAccountConnectionParameters { + name: String IMAP: ConnectionParametersInput SMTP: ConnectionParametersInput CALDAV: ConnectionParametersInput diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.ts b/packages/twenty-client-sdk/src/metadata/generated/schema.ts index 7f753e5233..6c41965cd7 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.ts @@ -2314,6 +2314,7 @@ export interface ImapSmtpCaldavPublicConnectionParams { } export interface ImapSmtpCaldavPublicConnectionParameters { + name?: Scalars['String'] IMAP?: ImapSmtpCaldavPublicConnectionParams SMTP?: ImapSmtpCaldavPublicConnectionParams CALDAV?: ImapSmtpCaldavPublicConnectionParams @@ -5490,6 +5491,7 @@ export interface ImapSmtpCaldavPublicConnectionParamsGenqlSelection{ } export interface ImapSmtpCaldavPublicConnectionParametersGenqlSelection{ + name?: boolean | number IMAP?: ImapSmtpCaldavPublicConnectionParamsGenqlSelection SMTP?: ImapSmtpCaldavPublicConnectionParamsGenqlSelection CALDAV?: ImapSmtpCaldavPublicConnectionParamsGenqlSelection @@ -6673,7 +6675,7 @@ export interface SendEmailInput {connectedAccountId: Scalars['String'],to: Scala export interface SendEmailAttachmentInput {id: Scalars['String'],name: Scalars['String']} -export interface EmailAccountConnectionParameters {IMAP?: (ConnectionParametersInput | null),SMTP?: (ConnectionParametersInput | null),CALDAV?: (ConnectionParametersInput | null)} +export interface EmailAccountConnectionParameters {name?: (Scalars['String'] | null),IMAP?: (ConnectionParametersInput | null),SMTP?: (ConnectionParametersInput | null),CALDAV?: (ConnectionParametersInput | null)} export interface ConnectionParametersInput {host: Scalars['String'],port: Scalars['Float'],username?: (Scalars['String'] | null),password?: (Scalars['String'] | null),connectionSecurity?: (EmailConnectionSecurity | null)} diff --git a/packages/twenty-client-sdk/src/metadata/generated/types.ts b/packages/twenty-client-sdk/src/metadata/generated/types.ts index 6918aa6cf7..2892301514 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/types.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/types.ts @@ -5228,6 +5228,9 @@ export default { ] }, "ImapSmtpCaldavPublicConnectionParameters": { + "name": [ + 1 + ], "IMAP": [ 293 ], @@ -11885,6 +11888,9 @@ export default { ] }, "EmailAccountConnectionParameters": { + "name": [ + 1 + ], "IMAP": [ 493 ], diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 7c486b397e..817a7320be 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -1548,6 +1548,7 @@ export type EmailAccountConnectionParameters = { CALDAV?: InputMaybe; IMAP?: InputMaybe; SMTP?: InputMaybe; + name?: InputMaybe; }; export enum EmailConnectionSecurity { @@ -2052,6 +2053,7 @@ export type ImapSmtpCaldavPublicConnectionParameters = { CALDAV?: Maybe; IMAP?: Maybe; SMTP?: Maybe; + name?: Maybe; }; export type ImapSmtpCaldavPublicConnectionParams = { @@ -7724,7 +7726,7 @@ export type GetConnectedImapSmtpCaldavAccountQueryVariables = Exact<{ }>; -export type GetConnectedImapSmtpCaldavAccountQuery = { __typename?: 'Query', getConnectedImapSmtpCaldavAccount: { __typename?: 'ConnectedImapSmtpCaldavAccount', id: string, handle: string, provider: string, userWorkspaceId: string, connectionParameters?: { __typename?: 'ImapSmtpCaldavPublicConnectionParameters', IMAP?: { __typename?: 'ImapSmtpCaldavPublicConnectionParams', host: string, port: number, connectionSecurity?: EmailConnectionSecurity | null, username?: string | null } | null, SMTP?: { __typename?: 'ImapSmtpCaldavPublicConnectionParams', host: string, username?: string | null, port: number, connectionSecurity?: EmailConnectionSecurity | null } | null, CALDAV?: { __typename?: 'ImapSmtpCaldavPublicConnectionParams', host: string, port: number, connectionSecurity?: EmailConnectionSecurity | null, username?: string | null } | null } | null } }; +export type GetConnectedImapSmtpCaldavAccountQuery = { __typename?: 'Query', getConnectedImapSmtpCaldavAccount: { __typename?: 'ConnectedImapSmtpCaldavAccount', id: string, handle: string, provider: string, userWorkspaceId: string, connectionParameters?: { __typename?: 'ImapSmtpCaldavPublicConnectionParameters', name?: string | null, IMAP?: { __typename?: 'ImapSmtpCaldavPublicConnectionParams', host: string, port: number, connectionSecurity?: EmailConnectionSecurity | null, username?: string | null } | null, SMTP?: { __typename?: 'ImapSmtpCaldavPublicConnectionParams', host: string, username?: string | null, port: number, connectionSecurity?: EmailConnectionSecurity | null } | null, CALDAV?: { __typename?: 'ImapSmtpCaldavPublicConnectionParams', host: string, port: number, connectionSecurity?: EmailConnectionSecurity | null, username?: string | null } | null } | null } }; export type MyCalendarChannelsQueryVariables = Exact<{ connectedAccountId?: InputMaybe; @@ -8979,7 +8981,7 @@ export const UpdateCalendarChannelDocument = {"kind":"Document","definitions":[{ export const UpdateMessageChannelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateMessageChannel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateMessageChannelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateMessageChannel"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"contactAutoCreationPolicy"}},{"kind":"Field","name":{"kind":"Name","value":"excludeNonProfessionalEmails"}},{"kind":"Field","name":{"kind":"Name","value":"excludeGroupEmails"}},{"kind":"Field","name":{"kind":"Name","value":"messageFolderImportPolicy"}}]}}]}}]} as unknown as DocumentNode; export const UpdateMessageFolderDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateMessageFolder"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateMessageFolderInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateMessageFolder"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"isSynced"}}]}}]}}]} as unknown as DocumentNode; export const UpdateMessageFoldersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateMessageFolders"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateMessageFoldersInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateMessageFolders"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"isSynced"}},{"kind":"Field","name":{"kind":"Name","value":"pendingSyncAction"}}]}}]}}]} as unknown as DocumentNode; -export const GetConnectedImapSmtpCaldavAccountDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetConnectedImapSmtpCaldavAccount"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getConnectedImapSmtpCaldavAccount"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"handle"}},{"kind":"Field","name":{"kind":"Name","value":"provider"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"connectionParameters"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"IMAP"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"host"}},{"kind":"Field","name":{"kind":"Name","value":"port"}},{"kind":"Field","name":{"kind":"Name","value":"connectionSecurity"}},{"kind":"Field","name":{"kind":"Name","value":"username"}}]}},{"kind":"Field","name":{"kind":"Name","value":"SMTP"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"host"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"port"}},{"kind":"Field","name":{"kind":"Name","value":"connectionSecurity"}}]}},{"kind":"Field","name":{"kind":"Name","value":"CALDAV"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"host"}},{"kind":"Field","name":{"kind":"Name","value":"port"}},{"kind":"Field","name":{"kind":"Name","value":"connectionSecurity"}},{"kind":"Field","name":{"kind":"Name","value":"username"}}]}}]}}]}}]}}]} as unknown as DocumentNode; +export const GetConnectedImapSmtpCaldavAccountDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetConnectedImapSmtpCaldavAccount"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"getConnectedImapSmtpCaldavAccount"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"handle"}},{"kind":"Field","name":{"kind":"Name","value":"provider"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"connectionParameters"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"IMAP"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"host"}},{"kind":"Field","name":{"kind":"Name","value":"port"}},{"kind":"Field","name":{"kind":"Name","value":"connectionSecurity"}},{"kind":"Field","name":{"kind":"Name","value":"username"}}]}},{"kind":"Field","name":{"kind":"Name","value":"SMTP"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"host"}},{"kind":"Field","name":{"kind":"Name","value":"username"}},{"kind":"Field","name":{"kind":"Name","value":"port"}},{"kind":"Field","name":{"kind":"Name","value":"connectionSecurity"}}]}},{"kind":"Field","name":{"kind":"Name","value":"CALDAV"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"host"}},{"kind":"Field","name":{"kind":"Name","value":"port"}},{"kind":"Field","name":{"kind":"Name","value":"connectionSecurity"}},{"kind":"Field","name":{"kind":"Name","value":"username"}}]}}]}}]}}]}}]} as unknown as DocumentNode; export const MyCalendarChannelsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"MyCalendarChannels"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"connectedAccountId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"myCalendarChannels"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"connectedAccountId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"connectedAccountId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"handle"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"syncStage"}},{"kind":"Field","name":{"kind":"Name","value":"syncStageStartedAt"}},{"kind":"Field","name":{"kind":"Name","value":"isContactAutoCreationEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"contactAutoCreationPolicy"}},{"kind":"Field","name":{"kind":"Name","value":"isSyncEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"connectedAccountId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode; export const MyConnectedAccountsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"MyConnectedAccounts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"myConnectedAccounts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"handle"}},{"kind":"Field","name":{"kind":"Name","value":"provider"}},{"kind":"Field","name":{"kind":"Name","value":"authFailedAt"}},{"kind":"Field","name":{"kind":"Name","value":"archivedAt"}},{"kind":"Field","name":{"kind":"Name","value":"scopes"}},{"kind":"Field","name":{"kind":"Name","value":"handleAliases"}},{"kind":"Field","name":{"kind":"Name","value":"lastSignedInAt"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"connectionProviderId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"lastCredentialsRefreshedAt"}},{"kind":"Field","name":{"kind":"Name","value":"connectionParameters"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"IMAP"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"host"}},{"kind":"Field","name":{"kind":"Name","value":"port"}},{"kind":"Field","name":{"kind":"Name","value":"connectionSecurity"}},{"kind":"Field","name":{"kind":"Name","value":"username"}}]}},{"kind":"Field","name":{"kind":"Name","value":"SMTP"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"host"}},{"kind":"Field","name":{"kind":"Name","value":"port"}},{"kind":"Field","name":{"kind":"Name","value":"connectionSecurity"}},{"kind":"Field","name":{"kind":"Name","value":"username"}}]}},{"kind":"Field","name":{"kind":"Name","value":"CALDAV"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"host"}},{"kind":"Field","name":{"kind":"Name","value":"username"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode; export const MyMessageChannelsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"MyMessageChannels"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"connectedAccountId"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"myMessageChannels"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"connectedAccountId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"connectedAccountId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"handle"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"isContactAutoCreationEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"contactAutoCreationPolicy"}},{"kind":"Field","name":{"kind":"Name","value":"messageFolderImportPolicy"}},{"kind":"Field","name":{"kind":"Name","value":"excludeNonProfessionalEmails"}},{"kind":"Field","name":{"kind":"Name","value":"excludeGroupEmails"}},{"kind":"Field","name":{"kind":"Name","value":"isSyncEnabled"}},{"kind":"Field","name":{"kind":"Name","value":"syncStatus"}},{"kind":"Field","name":{"kind":"Name","value":"syncStage"}},{"kind":"Field","name":{"kind":"Name","value":"syncStageStartedAt"}},{"kind":"Field","name":{"kind":"Name","value":"connectedAccountId"}},{"kind":"Field","name":{"kind":"Name","value":"connectedAccount"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"handle"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode; diff --git a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsConnectionForm.tsx b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsConnectionForm.tsx index 6da5bef26d..439f1866ab 100644 --- a/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsConnectionForm.tsx +++ b/packages/twenty-front/src/modules/settings/accounts/components/SettingsAccountsConnectionForm.tsx @@ -97,6 +97,22 @@ export const SettingsAccountsConnectionForm = ({
+ ( + + )} + /> + { if (isDefined(connectedAccount)) { reset({ + name: connectedAccount.connectionParameters?.name || '', handle: connectedAccount.handle || '', IMAP: { ...DEFAULT_PROTOCOL_VALUES.IMAP, @@ -168,7 +171,10 @@ export const useImapSmtpCaldavConnectionForm = ({ ? { id: connectedAccountId } : {}), handle: formValues.handle, - connectionParameters, + connectionParameters: { + ...connectionParameters, + name: formValues.name, + }, }, }); if (!isDefined(data)) return; diff --git a/packages/twenty-front/src/modules/settings/accounts/validation-schemas/connectionImapSmtpCalDav.ts b/packages/twenty-front/src/modules/settings/accounts/validation-schemas/connectionImapSmtpCalDav.ts index 8e5667c943..685656a820 100644 --- a/packages/twenty-front/src/modules/settings/accounts/validation-schemas/connectionImapSmtpCalDav.ts +++ b/packages/twenty-front/src/modules/settings/accounts/validation-schemas/connectionImapSmtpCalDav.ts @@ -32,6 +32,7 @@ const connectionParameters = z export const connectionImapSmtpCalDav = z .object({ + name: z.string().trim(), handle: z.email('Invalid email address'), IMAP: connectionParameters.optional(), SMTP: connectionParameters.optional(), @@ -52,6 +53,7 @@ export const connectionImapSmtpCalDav = z export const connectionImapSmtpCalDavUpdate = z .object({ + name: z.string().trim(), handle: z.email('Invalid email address'), IMAP: connectionParameters.optional(), SMTP: connectionParameters.optional(), diff --git a/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/dtos/imap-smtp-caldav-connected-account.dto.ts b/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/dtos/imap-smtp-caldav-connected-account.dto.ts index 7bd7ed6b8a..63f6cc306a 100644 --- a/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/dtos/imap-smtp-caldav-connected-account.dto.ts +++ b/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/dtos/imap-smtp-caldav-connected-account.dto.ts @@ -23,6 +23,9 @@ class PublicConnectionParamsDTO { @ObjectType('ImapSmtpCaldavPublicConnectionParameters') class ImapSmtpCaldavPublicConnectionParametersDTO { + @Field(() => String, { nullable: true }) + name?: string | null; + @Field(() => PublicConnectionParamsDTO, { nullable: true }) IMAP?: PublicConnectionParamsDTO; diff --git a/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/dtos/imap-smtp-caldav-connection.input.ts b/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/dtos/imap-smtp-caldav-connection.input.ts index a7ebc7e351..c05a3689f2 100644 --- a/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/dtos/imap-smtp-caldav-connection.input.ts +++ b/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/dtos/imap-smtp-caldav-connection.input.ts @@ -32,6 +32,9 @@ export class ConnectionParametersInput { @InputType('EmailAccountConnectionParameters') export class EmailAccountConnectionParametersInput { + @Field(() => String, { nullable: true }) + name?: string | null; + @Field(() => ConnectionParametersInput, { nullable: true }) IMAP?: ConnectionParametersInput; diff --git a/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/services/imap-smtp-caldav-connection.service.ts b/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/services/imap-smtp-caldav-connection.service.ts index 8c9e279124..2f40a97a72 100644 --- a/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/services/imap-smtp-caldav-connection.service.ts +++ b/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/services/imap-smtp-caldav-connection.service.ts @@ -3,8 +3,9 @@ import { Injectable, Logger } from '@nestjs/common'; import { msg } from '@lingui/core/macro'; import { ImapFlow } from 'imapflow'; import { createTransport } from 'nodemailer'; +import { isNonEmptyString } from '@sniptt/guards'; import { ACCOUNT_TYPES } from 'twenty-shared/constants'; -import { assertUnreachable } from 'twenty-shared/utils'; +import { assertUnreachable, isDefined } from 'twenty-shared/utils'; import { UserInputError } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { type EmailAccountConnectionParametersInput } from 'src/engine/core-modules/imap-smtp-caldav-connection/dtos/imap-smtp-caldav-connection.input'; @@ -224,6 +225,14 @@ export class ImapSmtpCaldavService { }): Promise { const validatedParams: PlaintextImapSmtpCaldavParams = {}; + if (isDefined(connectionParameters.name)) { + const trimmedName = connectionParameters.name.trim(); + + validatedParams.name = isNonEmptyString(trimmedName) ? trimmedName : null; + } else if (isDefined(existingConnectionParameters?.name)) { + validatedParams.name = existingConnectionParameters.name; + } + for (const protocol of ACCOUNT_TYPES) { const params = connectionParameters[protocol]; diff --git a/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/types/imap-smtp-caldav-connection.type.ts b/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/types/imap-smtp-caldav-connection.type.ts index 37923774b6..18c0c101bd 100644 --- a/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/types/imap-smtp-caldav-connection.type.ts +++ b/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/types/imap-smtp-caldav-connection.type.ts @@ -27,6 +27,7 @@ export type AccountType = (typeof ACCOUNT_TYPES)[number]; export { EmailConnectionSecurity } from 'src/engine/core-modules/imap-smtp-caldav-connection/enums/email-connection-security.enum'; export type ImapSmtpCaldavParams = { + name?: string | null; IMAP?: ConnectionParameters; SMTP?: ConnectionParameters; CALDAV?: ConnectionParameters; diff --git a/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/utils/build-public-connection-parameters.util.ts b/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/utils/build-public-connection-parameters.util.ts index f0f566e27c..4f299cafa3 100644 --- a/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/utils/build-public-connection-parameters.util.ts +++ b/packages/twenty-server/src/engine/core-modules/imap-smtp-caldav-connection/utils/build-public-connection-parameters.util.ts @@ -14,6 +14,7 @@ type PublicConnectionParams = { }; type PublicConnectionParameters = { + name?: string | null; IMAP?: PublicConnectionParams; SMTP?: PublicConnectionParams; CALDAV?: PublicConnectionParams; @@ -40,6 +41,8 @@ export const buildPublicConnectionParameters = ( return result; }, - {}, + { + name: connectionParameters.name ?? null, + }, ); }; diff --git a/packages/twenty-server/src/engine/metadata-modules/connected-account/services/connected-account-token-encryption.service.ts b/packages/twenty-server/src/engine/metadata-modules/connected-account/services/connected-account-token-encryption.service.ts index c7d41aaf3b..106b40f63a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/connected-account/services/connected-account-token-encryption.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/connected-account/services/connected-account-token-encryption.service.ts @@ -125,7 +125,9 @@ export class ConnectedAccountTokenEncryptionService { connectionParameters: PlaintextImapSmtpCaldavParams; workspaceId: string; }): EncryptedImapSmtpCaldavParams { - const result: EncryptedImapSmtpCaldavParams = {}; + const result: EncryptedImapSmtpCaldavParams = { + name: connectionParameters.name ?? null, + }; for (const protocol of ACCOUNT_TYPES) { const params = connectionParameters[protocol]; @@ -150,7 +152,9 @@ export class ConnectedAccountTokenEncryptionService { connectionParameters: EncryptedImapSmtpCaldavParams; workspaceId: string; }): PlaintextImapSmtpCaldavParams { - const result: PlaintextImapSmtpCaldavParams = {}; + const result: PlaintextImapSmtpCaldavParams = { + name: connectionParameters.name ?? null, + }; for (const protocol of ACCOUNT_TYPES) { const params = connectionParameters[protocol]; diff --git a/packages/twenty-server/src/modules/messaging/message-outbound-manager/drivers/gmail/services/gmail-message-outbound.service.ts b/packages/twenty-server/src/modules/messaging/message-outbound-manager/drivers/gmail/services/gmail-message-outbound.service.ts index c1f8f34387..a2ac335749 100644 --- a/packages/twenty-server/src/modules/messaging/message-outbound-manager/drivers/gmail/services/gmail-message-outbound.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-outbound-manager/drivers/gmail/services/gmail-message-outbound.service.ts @@ -9,10 +9,10 @@ import { type MessageOutboundDriver } from 'src/modules/messaging/message-outbou import { GoogleOAuth2ClientProvider } from 'src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client.provider'; import { type ConnectedAccountEntity } from 'src/engine/metadata-modules/connected-account/entities/connected-account.entity'; -import { mimeEncode } from 'src/modules/messaging/message-import-manager/utils/mime-encode.util'; import { type SendMessageInput } from 'src/modules/messaging/message-outbound-manager/types/send-message-input.type'; import { type SendMessageResult } from 'src/modules/messaging/message-outbound-manager/types/send-message-result.type'; import { extractMessageIdFromBuffer } from 'src/modules/messaging/message-outbound-manager/utils/extract-message-id-from-buffer.util'; +import { formatMessageFromHeader } from 'src/modules/messaging/message-outbound-manager/utils/format-message-from-header.util'; import { toMailComposerOptions } from 'src/modules/messaging/message-outbound-manager/utils/to-mail-composer-options.util'; @Injectable() @@ -169,6 +169,10 @@ export class GmailMessageOutboundService implements MessageOutboundDriver { const fromEmail = gmailData.emailAddress; + if (!isNonEmptyString(fromEmail)) { + throw new Error('Gmail profile did not return an email address'); + } + const { data: peopleData } = await peopleClient.people.get({ resourceName: 'people/me', personFields: 'names', @@ -176,9 +180,10 @@ export class GmailMessageOutboundService implements MessageOutboundDriver { const fromName = peopleData?.names?.[0]?.displayName; - const from = isDefined(fromName) - ? `"${mimeEncode(fromName)}" <${fromEmail}>` - : `${fromEmail}`; + const from = formatMessageFromHeader({ + fromEmail, + fromName, + }); const mail = new MailComposer( toMailComposerOptions(from, sendMessageInput), diff --git a/packages/twenty-server/src/modules/messaging/message-outbound-manager/drivers/imap/services/imap-smtp-message-outbound.service.ts b/packages/twenty-server/src/modules/messaging/message-outbound-manager/drivers/imap/services/imap-smtp-message-outbound.service.ts index 13ff820410..697b5c5df2 100644 --- a/packages/twenty-server/src/modules/messaging/message-outbound-manager/drivers/imap/services/imap-smtp-message-outbound.service.ts +++ b/packages/twenty-server/src/modules/messaging/message-outbound-manager/drivers/imap/services/imap-smtp-message-outbound.service.ts @@ -18,6 +18,7 @@ import { SmtpClientProvider } from 'src/modules/messaging/message-import-manager import { type SendMessageInput } from 'src/modules/messaging/message-outbound-manager/types/send-message-input.type'; import { type SendMessageResult } from 'src/modules/messaging/message-outbound-manager/types/send-message-result.type'; import { extractMessageIdFromBuffer } from 'src/modules/messaging/message-outbound-manager/utils/extract-message-id-from-buffer.util'; +import { formatMessageFromHeader } from 'src/modules/messaging/message-outbound-manager/utils/format-message-from-header.util'; import { toMailComposerOptions } from 'src/modules/messaging/message-outbound-manager/utils/to-mail-composer-options.util'; @Injectable() @@ -46,13 +47,15 @@ export class ImapSmtpMessageOutboundService implements MessageOutboundDriver { this.assertHandleIsDefined(handle); - const messageBuffer = await this.compileRawMessage( - handle, - sendMessageInput, - ); + const from = formatMessageFromHeader({ + fromEmail: handle, + fromName: connectionParameters?.name, + }); + + const messageBuffer = await this.compileRawMessage(from, sendMessageInput); await smtpClient.sendMail({ - from: handle, + from, to: sendMessageInput.to, cc: sendMessageInput.cc, bcc: sendMessageInput.bcc, @@ -108,10 +111,12 @@ export class ImapSmtpMessageOutboundService implements MessageOutboundDriver { throw new Error('IMAP connection is required to create drafts'); } - const messageBuffer = await this.compileRawMessage( - handle, - sendMessageInput, - ); + const from = formatMessageFromHeader({ + fromEmail: handle, + fromName: connectionParameters?.name, + }); + + const messageBuffer = await this.compileRawMessage(from, sendMessageInput); const imapClient = await this.imapClientProvider.getClient( connectedAccount.id, diff --git a/packages/twenty-server/src/modules/messaging/message-outbound-manager/utils/__tests__/format-message-from-header.util.spec.ts b/packages/twenty-server/src/modules/messaging/message-outbound-manager/utils/__tests__/format-message-from-header.util.spec.ts new file mode 100644 index 0000000000..049d3e7cf2 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-outbound-manager/utils/__tests__/format-message-from-header.util.spec.ts @@ -0,0 +1,30 @@ +import { formatMessageFromHeader } from 'src/modules/messaging/message-outbound-manager/utils/format-message-from-header.util'; + +describe('formatMessageFromHeader', () => { + it('should format name and email when name is provided', () => { + expect( + formatMessageFromHeader({ + fromEmail: 'user@example.com', + fromName: 'Test User', + }), + ).toBe('=?UTF-8?B?VGVzdCBVc2Vy?= '); + }); + + it('should fall back to the bare email when name is missing', () => { + expect( + formatMessageFromHeader({ + fromEmail: 'user@example.com', + fromName: null, + }), + ).toBe('user@example.com'); + }); + + it('should fall back to the bare email when name is blank', () => { + expect( + formatMessageFromHeader({ + fromEmail: 'user@example.com', + fromName: '', + }), + ).toBe('user@example.com'); + }); +}); diff --git a/packages/twenty-server/src/modules/messaging/message-outbound-manager/utils/format-message-from-header.util.ts b/packages/twenty-server/src/modules/messaging/message-outbound-manager/utils/format-message-from-header.util.ts new file mode 100644 index 0000000000..c5e95915d0 --- /dev/null +++ b/packages/twenty-server/src/modules/messaging/message-outbound-manager/utils/format-message-from-header.util.ts @@ -0,0 +1,15 @@ +import { isNonEmptyString } from '@sniptt/guards'; + +import { mimeEncode } from 'src/modules/messaging/message-import-manager/utils/mime-encode.util'; + +export const formatMessageFromHeader = ({ + fromEmail, + fromName, +}: { + fromEmail: string; + fromName?: string | null; +}) => { + return isNonEmptyString(fromName) + ? `${mimeEncode(fromName)} <${fromEmail}>` + : fromEmail; +};