Files
dmail-api/src/modules/email/email.controller.ts
T
2025-07-21 10:22:58 +03:30

294 lines
16 KiB
TypeScript

import { Body, Controller, Delete, Get, Param, Patch, Post, Query } from "@nestjs/common";
import { ApiOperation, ApiResponse } from "@nestjs/swagger";
import { BulkActionDto } from "./DTO/bulk-actions.dto";
import { MailboxIdQueryDto, MessageParamDto, QueueIdParamDto } from "./DTO/email-params.dto";
import { MessageListQueryDto } from "./DTO/email-query.dto";
import { SearchMessagesQueryDto } from "./DTO/email-query.dto";
import { SendEmailDto, UpdateDraftDto } from "./DTO/send-email.dto";
import { EmailService } from "./services/email.service";
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
import { UserDec } from "../../common/decorators/user.decorator";
@AuthGuards()
@Controller("email")
export class EmailController {
constructor(private readonly emailService: EmailService) {}
@Post("send")
@ApiOperation({
summary: "Send an email with configurable headers based on type",
description:
"Send emails with automatic anti-threading and anti-spam headers. Supports different email types: general, transactional, marketing, anti-threading. Marketing emails require listId and unsubscribeUrl.",
})
@ApiResponse({ status: 201, description: "Email sent successfully" })
@ApiResponse({ status: 400, description: "Invalid email data or missing required fields for email type" })
@ApiResponse({ status: 403, description: "Not authorized to send email" })
sendEmail(@UserDec("wildduckUserId") userEmailId: string, @UserDec("id") userId: string, @Body() sendEmailDto: SendEmailDto) {
return this.emailService.sendEmail(userEmailId, userId, sendEmailDto);
}
@Get("status/:queueId")
@ApiOperation({ summary: "Get email delivery status" })
@ApiResponse({ status: 200, description: "Email delivery status" })
@ApiResponse({ status: 404, description: "Email not found" })
getEmailStatus(@Param() params: QueueIdParamDto) {
return this.emailService.getEmailStatus(params.queueId);
}
@Get("messages/:messageId")
@ApiOperation({ summary: "Get a specific message" })
@ApiResponse({ status: 200, description: "Message details" })
@ApiResponse({ status: 404, description: "Message not found" })
getMessage(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto, @Query() query: MailboxIdQueryDto) {
return this.emailService.getMessage(userId, params.messageId, query.mailbox);
}
@Delete("messages/:messageId")
@ApiOperation({ summary: "Delete a message" })
@ApiResponse({ status: 200, description: "Message deleted successfully" })
@ApiResponse({ status: 404, description: "Message not found" })
deleteMessage(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto, @Query() query: MailboxIdQueryDto) {
return this.emailService.deleteMessage(userId, params.messageId, query.mailbox);
}
@Get("search")
@ApiOperation({ summary: "Search messages across all mailboxes" })
@ApiResponse({ status: 200, description: "Search results" })
searchMessages(@UserDec("wildduckUserId") userId: string, @Query() query: SearchMessagesQueryDto) {
return this.emailService.searchMessages(userId, query);
}
@Patch("messages/:messageId/seen")
@ApiOperation({ summary: "Mark a message as seen" })
@ApiResponse({ status: 200, description: "Message marked as seen successfully" })
@ApiResponse({ status: 404, description: "Message not found" })
markMessageAsSeen(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto, @Query() query: MailboxIdQueryDto) {
return this.emailService.markMessageAsSeen(userId, Number(params.messageId), query.mailbox);
}
@Patch("messages/:messageId/unseen")
@ApiOperation({ summary: "Mark a message as unseen" })
@ApiResponse({ status: 200, description: "Message marked as unseen successfully" })
@ApiResponse({ status: 404, description: "Message not found" })
markMessageAsUnseen(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto, @Query() query: MailboxIdQueryDto) {
return this.emailService.markMessageAsUnseen(userId, Number(params.messageId), query.mailbox);
}
@Get("messages/inbox")
@ApiOperation({ summary: "List messages in a inbox" })
@ApiResponse({ status: 200, description: "List of messages" })
@ApiResponse({ status: 404, description: "Mailbox not found" })
listMessages(@UserDec("wildduckUserId") userId: string, @Query() query: MessageListQueryDto) {
return this.emailService.listMessages(userId, query);
}
@Get("messages/sent")
@ApiOperation({ summary: "List messages in sent mailbox" })
@ApiResponse({ status: 200, description: "List of sent messages" })
@ApiResponse({ status: 404, description: "Sent mailbox not found" })
getSentMessages(@UserDec("wildduckUserId") userId: string, @Query() query: MessageListQueryDto) {
return this.emailService.getSentMessages(userId, query);
}
@Get("messages/trash")
@ApiOperation({ summary: "List messages in trash mailbox" })
@ApiResponse({ status: 200, description: "List of trash messages" })
@ApiResponse({ status: 404, description: "Trash mailbox not found" })
getTrashMessages(@UserDec("wildduckUserId") userId: string, @Query() query: MessageListQueryDto) {
return this.emailService.getTrashMessages(userId, query);
}
@Get("messages/junk")
@ApiOperation({ summary: "List messages in junk mailbox" })
@ApiResponse({ status: 200, description: "List of junk messages" })
@ApiResponse({ status: 404, description: "junk mailbox not found" })
getJunkMessages(@UserDec("wildduckUserId") userId: string, @Query() query: MessageListQueryDto) {
return this.emailService.getJunkMessages(userId, query);
}
@Get("messages/archive")
@ApiOperation({ summary: "List messages in archive mailbox" })
@ApiResponse({ status: 200, description: "List of archive messages" })
@ApiResponse({ status: 404, description: "archive mailbox not found" })
getArchiveMessages(@UserDec("wildduckUserId") userId: string, @Query() query: MessageListQueryDto) {
return this.emailService.getArchivedMessages(userId, query);
}
@Get("messages/favorite")
@ApiOperation({ summary: "List messages in favorite mailbox" })
@ApiResponse({ status: 200, description: "List of favorite messages" })
@ApiResponse({ status: 404, description: "favorite mailbox not found" })
getFavoriteMessages(@UserDec("wildduckUserId") userId: string, @Query() query: MessageListQueryDto) {
return this.emailService.getFavoriteMessages(userId, query);
}
@Get("messages/drafts")
@ApiOperation({ summary: "List messages in drafts mailbox" })
@ApiResponse({ status: 200, description: "List of drafts messages" })
@ApiResponse({ status: 404, description: "Drafts mailbox not found" })
getDraftsMessages(@UserDec("wildduckUserId") userId: string, @Query() query: MessageListQueryDto) {
return this.emailService.getDraftsMessages(userId, query);
}
@Patch("messages/drafts/:messageId")
@ApiOperation({ summary: "Update an existing draft" })
@ApiResponse({ status: 200, description: "Draft updated successfully" })
@ApiResponse({ status: 400, description: "Invalid draft data" })
@ApiResponse({ status: 404, description: "Draft not found" })
@ApiResponse({ status: 403, description: "Not authorized to update draft" })
updateDraft(@UserDec("wildduckUserId") userEmailId: string, @Param() params: MessageParamDto, @Body() updateDraftDto: UpdateDraftDto) {
return this.emailService.updateDraft(userEmailId, Number(params.messageId), updateDraftDto);
}
@Post("messages/drafts/:messageId/send")
@ApiOperation({ summary: "Send a draft message" })
@ApiResponse({ status: 200, description: "Draft sent successfully" })
@ApiResponse({ status: 404, description: "Draft not found" })
@ApiResponse({ status: 403, description: "Not authorized to send draft" })
sendDraft(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto) {
return this.emailService.sendDraft(userId, Number(params.messageId));
}
@Delete("messages/drafts/:messageId")
@ApiOperation({ summary: "Delete a draft message" })
@ApiResponse({ status: 200, description: "Draft deleted successfully" })
@ApiResponse({ status: 404, description: "Draft not found" })
@ApiResponse({ status: 403, description: "Not authorized to delete draft" })
deleteDraft(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto) {
return this.emailService.deleteDraft(userId, Number(params.messageId));
}
@Patch("messages/:messageId/archive")
@ApiOperation({ summary: "Move a message to archive mailbox" })
@ApiResponse({ status: 200, description: "Message moved to archive successfully" })
@ApiResponse({ status: 404, description: "Message not found" })
@ApiResponse({ status: 403, description: "Not authorized to move message" })
moveMessageToArchive(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto, @Query() query: MailboxIdQueryDto) {
return this.emailService.moveMessageToArchive(userId, Number(params.messageId), query.mailbox);
}
@Patch("messages/:messageId/favorite")
@ApiOperation({ summary: "Move a message to favorite mailbox" })
@ApiResponse({ status: 200, description: "Message moved to favorite successfully" })
@ApiResponse({ status: 404, description: "Message not found" })
@ApiResponse({ status: 403, description: "Not authorized to move message" })
moveMessageToFavorite(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto, @Query() query: MailboxIdQueryDto) {
return this.emailService.moveMessageToFavorite(userId, Number(params.messageId), query.mailbox);
}
@Patch("messages/:messageId/trash")
@ApiOperation({ summary: "Move a message to trash mailbox" })
@ApiResponse({ status: 200, description: "Message moved to trash successfully" })
@ApiResponse({ status: 404, description: "Message not found" })
@ApiResponse({ status: 403, description: "Not authorized to move message" })
moveMessageToTrash(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto, @Query() query: MailboxIdQueryDto) {
return this.emailService.moveMessageToTrash(userId, Number(params.messageId), query.mailbox);
}
@Patch("messages/:messageId/unarchive")
@ApiOperation({ summary: "Move a message from archive back to inbox" })
@ApiResponse({ status: 200, description: "Message moved from archive to inbox successfully" })
@ApiResponse({ status: 404, description: "Message not found in archive" })
@ApiResponse({ status: 403, description: "Not authorized to move message" })
moveMessageToInboxFromArchive(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto, @Query() query: MailboxIdQueryDto) {
return this.emailService.moveMessageToInboxFromArchive(userId, Number(params.messageId), query.mailbox);
}
@Patch("messages/:messageId/unfavorite")
@ApiOperation({ summary: "Move a message from favorite back to inbox" })
@ApiResponse({ status: 200, description: "Message moved from favorite to inbox successfully" })
@ApiResponse({ status: 404, description: "Message not found in favorite" })
@ApiResponse({ status: 403, description: "Not authorized to move message" })
moveMessageToInboxFromFavorite(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto, @Query() query: MailboxIdQueryDto) {
return this.emailService.moveMessageToInboxFromFavorite(userId, Number(params.messageId), query.mailbox);
}
@Patch("messages/:messageId/restore")
@ApiOperation({ summary: "Restore a message from trash back to inbox" })
@ApiResponse({ status: 200, description: "Message restored from trash to inbox successfully" })
@ApiResponse({ status: 404, description: "Message not found in trash" })
@ApiResponse({ status: 403, description: "Not authorized to restore message" })
moveMessageToInboxFromTrash(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto, @Query() query: MailboxIdQueryDto) {
return this.emailService.moveMessageToInboxFromTrash(userId, Number(params.messageId), query.mailbox);
}
@Patch("messages/:messageId/junk")
@ApiOperation({ summary: "Move a message to junk mailbox" })
@ApiResponse({ status: 200, description: "Message moved to junk successfully" })
@ApiResponse({ status: 404, description: "Message not found" })
@ApiResponse({ status: 403, description: "Not authorized to move message" })
moveMessageToJunk(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto, @Query() query: MailboxIdQueryDto) {
return this.emailService.moveMessageToJunk(userId, Number(params.messageId), query.mailbox);
}
@Patch("messages/:messageId/not-junk")
@ApiOperation({ summary: "Move a message from junk back to inbox (not spam)" })
@ApiResponse({ status: 200, description: "Message moved from junk to inbox successfully" })
@ApiResponse({ status: 404, description: "Message not found in junk" })
@ApiResponse({ status: 403, description: "Not authorized to move message" })
moveMessageToInboxFromJunk(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto, @Query() query: MailboxIdQueryDto) {
return this.emailService.moveMessageToInboxFromJunk(userId, Number(params.messageId), query.mailbox);
}
@Post("messages/bulk-action")
@ApiOperation({
summary: "Perform bulk actions on multiple messages",
description: "Apply actions (seen, delete, archive, unarchive, favorite, unfavorite, junk, notjunk, trash, restore) to multiple messages at once",
})
@ApiResponse({ status: 200, description: "Bulk action completed successfully" })
@ApiResponse({ status: 206, description: "Bulk action partially completed" })
@ApiResponse({ status: 400, description: "Invalid bulk action data" })
@ApiResponse({ status: 403, description: "Not authorized to perform bulk action" })
performBulkAction(@UserDec("wildduckUserId") userId: string, @Body() bulkActionDto: BulkActionDto, @Query() query: MailboxIdQueryDto) {
return this.emailService.performBulkAction(userId, bulkActionDto, query.mailbox);
}
// // Domain Access Management Endpoints
// @Get("spam/domains/allowed")
// @ApiOperation({ summary: "List domains in allowlist (never marked as spam)" })
// @ApiResponse({ status: 200, description: "List of allowed domains" })
// listAllowedDomains(@UserDec("id") userId: string, @Query() query: ListDomainAccessQueryDto) {
// return this.emailSpamService.listAllowedDomains(userId, query);
// }
// @Get("spam/domains/blocked")
// @ApiOperation({ summary: "List domains in blocklist (always marked as spam)" })
// @ApiResponse({ status: 200, description: "List of blocked domains" })
// listBlockedDomains(@UserDec("id") userId: string, @Query() query: ListDomainAccessQueryDto) {
// return this.emailSpamService.listBlockedDomains(userId, query);
// }
// @Post("spam/domains/allowed")
// @ApiOperation({ summary: "Add domain to allowlist" })
// @ApiResponse({ status: 201, description: "Domain added to allowlist successfully" })
// @ApiResponse({ status: 400, description: "Invalid domain data" })
// addDomainToAllowlist(@UserDec("id") userId: string, @Body() createDomainDto: CreateDomainAccessDto) {
// return this.emailSpamService.addDomainToAllowlist(createDomainDto.domain, createDomainDto.description, userId);
// }
// @Post("spam/domains/blocked")
// @ApiOperation({ summary: "Add domain to blocklist" })
// @ApiResponse({ status: 201, description: "Domain added to blocklist successfully" })
// @ApiResponse({ status: 400, description: "Invalid domain data" })
// addDomainToBlocklist(@UserDec("id") userId: string, @Body() createDomainDto: CreateDomainAccessDto) {
// return this.emailSpamService.addDomainToBlocklist(createDomainDto.domain, createDomainDto.description, userId);
// }
// @Delete("spam/domains/allowed/:domain")
// @ApiOperation({ summary: "Remove domain from allowlist" })
// @ApiResponse({ status: 200, description: "Domain removed from allowlist successfully" })
// @ApiResponse({ status: 404, description: "Domain not found in allowlist" })
// removeDomainFromAllowlist(@UserDec("id") userId: string, @Param("domain") domain: string) {
// return this.emailSpamService.removeDomainFromAllowlist(domain, userId);
// }
// @Delete("spam/domains/blocked/:domain")
// @ApiOperation({ summary: "Remove domain from blocklist" })
// @ApiResponse({ status: 200, description: "Domain removed from blocklist successfully" })
// @ApiResponse({ status: 404, description: "Domain not found in blocklist" })
// removeDomainFromBlocklist(@UserDec("id") userId: string, @Param("domain") domain: string) {
// return this.emailSpamService.removeDomainFromBlocklist(domain, userId);
// }
}