diff --git a/packages/twenty-server/src/engine/core-modules/emailing-domain/drivers/aws-ses/services/__tests__/aws-ses-driver-domain-status.service.spec.ts b/packages/twenty-server/src/engine/core-modules/emailing-domain/drivers/aws-ses/services/__tests__/aws-ses-driver-domain-status.service.spec.ts new file mode 100644 index 0000000000..98ee10637f --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/emailing-domain/drivers/aws-ses/services/__tests__/aws-ses-driver-domain-status.service.spec.ts @@ -0,0 +1,94 @@ +import { type AwsSesClientProvider } from 'src/engine/core-modules/emailing-domain/drivers/aws-ses/providers/aws-ses-client.provider'; +import { AwsSesDriver } from 'src/engine/core-modules/emailing-domain/drivers/aws-ses/services/aws-ses-driver.service'; +import { type AwsSesHandleErrorService } from 'src/engine/core-modules/emailing-domain/drivers/aws-ses/services/aws-ses-handle-error.service'; +import { type AwsSesRegisterDomainService } from 'src/engine/core-modules/emailing-domain/drivers/aws-ses/services/aws-ses-register-domain.service'; +import { type AwsSesSendEmailService } from 'src/engine/core-modules/emailing-domain/drivers/aws-ses/services/aws-ses-send-email.service'; +import { type AwsSesDriverConfig } from 'src/engine/core-modules/emailing-domain/drivers/interfaces/driver-config.interface'; +import { EmailingDomainDriver } from 'src/engine/core-modules/emailing-domain/drivers/types/emailing-domain-driver.type'; +import { EmailingDomainStatus } from 'src/engine/core-modules/emailing-domain/drivers/types/emailing-domain-status.type'; +import { type UnsubscribeContentService } from 'src/engine/core-modules/emailing-domain/services/unsubscribe-content.service'; + +describe('AwsSesDriver getDomainStatus', () => { + const config: AwsSesDriverConfig = { + driver: EmailingDomainDriver.AWS_SES, + region: 'us-east-1', + accountId: '123456789012', + }; + + const setUp = (identityResponse: Record) => { + const send = jest.fn().mockResolvedValue(identityResponse); + const clientProvider = { + getSESClient: () => ({ send }), + } as unknown as AwsSesClientProvider; + + const driver = new AwsSesDriver( + config, + clientProvider, + {} as unknown as AwsSesHandleErrorService, + {} as unknown as AwsSesRegisterDomainService, + {} as unknown as AwsSesSendEmailService, + {} as unknown as UnsubscribeContentService, + ); + + return driver.getDomainStatus({ + domain: 'twenty.dev', + workspaceId: 'workspace-id', + }); + }; + + it('should report pending while SES is still waiting for the DKIM records', async () => { + const result = await setUp({ + VerifiedForSendingStatus: false, + DkimAttributes: { SigningEnabled: true, Status: 'PENDING', Tokens: [] }, + }); + + expect(result.status).toBe(EmailingDomainStatus.PENDING); + }); + + it('should report pending when a DKIM check fails temporarily', async () => { + const result = await setUp({ + VerifiedForSendingStatus: false, + DkimAttributes: { + SigningEnabled: true, + Status: 'TEMPORARY_FAILURE', + Tokens: [], + }, + }); + + expect(result.status).toBe(EmailingDomainStatus.PENDING); + }); + + it('should report failed when SES gave up on the DKIM records', async () => { + const result = await setUp({ + VerifiedForSendingStatus: false, + DkimAttributes: { SigningEnabled: true, Status: 'FAILED', Tokens: [] }, + }); + + expect(result.status).toBe(EmailingDomainStatus.FAILED); + }); + + it('should report verified once SES signs with DKIM', async () => { + const result = await setUp({ + VerifiedForSendingStatus: true, + DkimAttributes: { SigningEnabled: true, Status: 'SUCCESS', Tokens: [] }, + }); + + expect(result.status).toBe(EmailingDomainStatus.VERIFIED); + }); + + it('should mark every DKIM record pending while the domain is pending', async () => { + const result = await setUp({ + VerifiedForSendingStatus: false, + DkimAttributes: { + SigningEnabled: true, + Status: 'PENDING', + Tokens: ['token1', 'token2', 'token3'], + }, + }); + + expect(result.verificationRecords).toHaveLength(3); + expect( + result.verificationRecords.every((record) => record.status === 'pending'), + ).toBe(true); + }); +}); diff --git a/packages/twenty-server/src/engine/core-modules/emailing-domain/drivers/aws-ses/services/aws-ses-driver.service.ts b/packages/twenty-server/src/engine/core-modules/emailing-domain/drivers/aws-ses/services/aws-ses-driver.service.ts index ac89c383ac..bd283b637b 100644 --- a/packages/twenty-server/src/engine/core-modules/emailing-domain/drivers/aws-ses/services/aws-ses-driver.service.ts +++ b/packages/twenty-server/src/engine/core-modules/emailing-domain/drivers/aws-ses/services/aws-ses-driver.service.ts @@ -16,16 +16,16 @@ import { import { isNonEmptyString } from '@sniptt/guards'; +import { + EmailingDomainDriverException, + EmailingDomainDriverExceptionCode, +} from 'src/engine/core-modules/emailing-domain/drivers/exceptions/emailing-domain-driver.exception'; import { type AwsSesDriverConfig } from 'src/engine/core-modules/emailing-domain/drivers/interfaces/driver-config.interface'; import { type EmailingDomainDriverInterface, type EmailingDomainResourceInput, type EmailingDomainVerificationResult, } from 'src/engine/core-modules/emailing-domain/drivers/interfaces/emailing-domain-driver.interface'; -import { - EmailingDomainDriverException, - EmailingDomainDriverExceptionCode, -} from 'src/engine/core-modules/emailing-domain/drivers/exceptions/emailing-domain-driver.exception'; import { type EmailingDomainSendEmailRequest } from 'src/engine/core-modules/emailing-domain/drivers/types/emailing-domain-send-email-input.type'; import { type EmailingDomainSendEmailResult } from 'src/engine/core-modules/emailing-domain/drivers/types/emailing-domain-send-email-result.type'; import { UnsubscribeHostnameStatus } from 'src/engine/core-modules/emailing-domain/drivers/types/unsubscribe-hostname-status.type'; @@ -34,8 +34,8 @@ import { type UnsubscribeContentService } from 'src/engine/core-modules/emailing import { AWS_SES_RESOURCE_NAME_PREFIX } from 'src/engine/core-modules/emailing-domain/drivers/aws-ses/constants/aws-ses-resource-name-prefix.constant'; import { type AwsSesClientProvider } from 'src/engine/core-modules/emailing-domain/drivers/aws-ses/providers/aws-ses-client.provider'; -import { AwsSesRegisterDomainService } from 'src/engine/core-modules/emailing-domain/drivers/aws-ses/services/aws-ses-register-domain.service'; import { type AwsSesHandleErrorService } from 'src/engine/core-modules/emailing-domain/drivers/aws-ses/services/aws-ses-handle-error.service'; +import { AwsSesRegisterDomainService } from 'src/engine/core-modules/emailing-domain/drivers/aws-ses/services/aws-ses-register-domain.service'; import { type AwsSesSendEmailService } from 'src/engine/core-modules/emailing-domain/drivers/aws-ses/services/aws-ses-send-email.service'; import { EmailingDomainStatus } from 'src/engine/core-modules/emailing-domain/drivers/types/emailing-domain-status.type'; import { type VerificationRecordDTO } from 'src/engine/core-modules/emailing-domain/dtos/verification-record.dto'; @@ -376,10 +376,7 @@ export class AwsSesDriver implements EmailingDomainDriverInterface { return EmailingDomainStatus.VERIFIED; } - if ( - identityResponse.VerifiedForSendingStatus === false || - dkimStatus === 'FAILED' - ) { + if (dkimStatus === 'FAILED') { return EmailingDomainStatus.FAILED; }