import { Type } from 'class-transformer'; import { IsArray, IsInt, IsNotEmpty, IsObject, IsOptional, IsString, ValidateNested } from 'class-validator'; import { InlineTemplateDto } from '../templates/template.dto'; /** An email attachment reference — bytes live in the media store under `contentRef`. */ export class AttachmentDto { @IsOptional() @IsString() filename?: string; @IsString() @IsNotEmpty() contentRef!: string; @IsOptional() @IsString() mimeType?: string; @IsOptional() @IsInt() sizeBytes?: number; } /** POST /v1/mail/internal — app-to-app mail (no SMTP). Provide EITHER `key` OR `inline`. */ export class MailInternalDto { @IsOptional() @IsString() @IsNotEmpty() key?: string; @IsOptional() @IsInt() version?: number; @IsOptional() @ValidateNested() @Type(() => InlineTemplateDto) inline?: InlineTemplateDto; @IsString() @IsNotEmpty() recipientUserId!: string; @IsOptional() @IsObject() vars?: Record; @IsOptional() @IsString() locale?: string; @IsString() @IsNotEmpty() idempotencyKey!: string; /** In-app attachment refs — stored as message parts so the recipient's inbox can render them. */ @IsOptional() @IsArray() @ValidateNested({ each: true }) @Type(() => AttachmentDto) attachments?: AttachmentDto[]; } /** POST /v1/mail/send — external email via SMTP + optional in-app mirror for a registered recipient. */ export class MailSendDto { @IsOptional() @IsString() @IsNotEmpty() key?: string; @IsOptional() @IsInt() version?: number; @IsOptional() @ValidateNested() @Type(() => InlineTemplateDto) inline?: InlineTemplateDto; @IsString() @IsNotEmpty() target!: string; @IsOptional() @IsObject() vars?: Record; @IsOptional() @IsString() locale?: string; @IsString() @IsNotEmpty() idempotencyKey!: string; @IsOptional() @IsString() purpose?: string; @IsOptional() @IsArray() @ValidateNested({ each: true }) @Type(() => AttachmentDto) attachments?: AttachmentDto[]; /** The registered recipient to mirror to; omit for a pre-registration send (email only). */ @IsOptional() @IsString() mirrorToUserId?: string; }