diff --git a/src/modules/email/DTO/send-email.dto.ts b/src/modules/email/DTO/send-email.dto.ts index f8ac7cc..ec7069c 100644 --- a/src/modules/email/DTO/send-email.dto.ts +++ b/src/modules/email/DTO/send-email.dto.ts @@ -1,6 +1,18 @@ import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger"; import { Type } from "class-transformer"; -import { IsArray, IsBoolean, IsDateString, IsEmail, IsEnum, IsNotEmpty, IsNumber, IsOptional, IsString, ValidateNested } from "class-validator"; +import { + IsArray, + IsBoolean, + IsDateString, + IsEmail, + IsEnum, + IsNotEmpty, + IsNumber, + IsOptional, + IsString, + ValidateIf, + ValidateNested, +} from "class-validator"; import { EmailMessage } from "../../../common/enums/message.enum"; // import { Priority } from "../enums/email-header.enum"; @@ -157,11 +169,13 @@ export class SendEmailDto { @ApiPropertyOptional({ description: "Message subject. If not then resolved from Reference message (optional)", example: "Test email" }) subject: string; + @ValidateIf((o) => !o.isDraft) @IsNotEmpty({ message: EmailMessage.TEXT_CONTENT_REQUIRED }) @IsString({ message: EmailMessage.TEXT_CONTENT_MUST_BE_STRING }) @ApiPropertyOptional({ description: "Plaintext message (optional)" }) text: string; + @ValidateIf((o) => !o.isDraft) @IsNotEmpty({ message: EmailMessage.HTML_CONTENT_REQUIRED }) @IsString({ message: EmailMessage.HTML_CONTENT_MUST_BE_STRING }) @ApiPropertyOptional({ description: "HTML formatted message (optional)" }) diff --git a/src/modules/email/services/email.service.ts b/src/modules/email/services/email.service.ts index 412275d..9a3b418 100644 --- a/src/modules/email/services/email.service.ts +++ b/src/modules/email/services/email.service.ts @@ -480,14 +480,8 @@ export class EmailService { const draftsMailboxId = await this.mailboxResolverService.getDraftsMailboxId(wildduckUserId); const existingDraft = await firstValueFrom(this.mailServerService.messages.getMessage(wildduckUserId, draftsMailboxId, messageId)); - // Delete the existing draft first to avoid incrementing the count - try { - await firstValueFrom(this.mailServerService.messages.deleteMessage(wildduckUserId, draftsMailboxId, messageId)); - this.logger.log(`Existing draft message ${messageId} deleted before update`); - } catch (error) { - this.logger.warn(`Failed to delete existing draft message ${messageId}: ${error instanceof Error ? error.message : String(error)}`); - // Continue with update even if deletion fails - } + await firstValueFrom(this.mailServerService.messages.deleteMessage(wildduckUserId, draftsMailboxId, messageId)); + this.logger.log(`Existing draft message ${messageId} deleted before update`); const draftData: SendEmailDto = { from: updateDraftDto.from || { address: existingDraft.from?.address || "" }, @@ -505,8 +499,6 @@ export class EmailService { ip: updateDraftDto.ip, isDraft: true, uploadOnly: true, - // Remove the draft reference since we deleted the original - // This will create a new draft instead of trying to update the deleted one }; const user = await this.userRepository.findOne({ wildduckUserId, deletedAt: null }, { populate: ["business"] }); @@ -547,23 +539,14 @@ export class EmailService { async sendDraft(wildduckUserId: string, userId: string, messageId: number) { const draftsMailboxId = await this.mailboxResolverService.getDraftsMailboxId(wildduckUserId); - // Get message details before sending (for notification) const message = await firstValueFrom(this.mailServerService.messages.getMessage(wildduckUserId, draftsMailboxId, messageId)); - // Submit the draft for delivery const result = await firstValueFrom( this.mailServerService.messages.submitDraft(wildduckUserId, draftsMailboxId, messageId, { deleteFiles: false }), ); - // Delete the draft from drafts folder after successful submission - // This ensures the draft count decreases properly - try { - await firstValueFrom(this.mailServerService.messages.deleteMessage(wildduckUserId, draftsMailboxId, messageId)); - this.logger.log(`Draft message ${messageId} deleted from drafts folder after sending`); - } catch (error) { - this.logger.warn(`Failed to delete draft message ${messageId} from drafts folder: ${error instanceof Error ? error.message : String(error)}`); - // Don't fail the entire operation if deletion fails - } + await firstValueFrom(this.mailServerService.messages.deleteMessage(wildduckUserId, draftsMailboxId, messageId)); + this.logger.log(`Draft message ${messageId} deleted from drafts folder after sending`); await this.emailNotificationService.notifyEmailSentFromDraft({ wildduckUserId,