chore: changes

This commit is contained in:
mahyargdz
2025-07-09 16:59:26 +03:30
parent 092abd2895
commit 784f168e8c
6 changed files with 120 additions and 31 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ declare module "fastify" {
}
}
export const UserDec = createParamDecorator((data: keyof ITokenPayload | undefined, ctx: ExecutionContext) => {
export const UserDec = createParamDecorator((data: keyof ITokenPayload, ctx: ExecutionContext) => {
const req = ctx.switchToHttp().getRequest<FastifyRequest>();
const user = req.user;
+8
View File
@@ -186,6 +186,14 @@ export const enum EmailMessage {
SEND_TIME_MUST_BE_DATE = "زمان ارسال باید یک تاریخ معتبر باشد",
UPLOAD_ONLY_MUST_BE_BOOLEAN = "حالت فقط آپلود باید بولین باشد",
ENVELOPE_MUST_BE_VALID = "envelope باید معتبر باشد",
// Message operations
MESSAGE_MARKED_AS_SEEN_SUCCESSFULLY = "پیام با موفقیت به عنوان خوانده شده علامت گذاری شد",
MESSAGE_MARK_AS_SEEN_FAILED = "علامت گذاری پیام با خطا مواجه شد",
SENT_MESSAGES_RETRIEVED_SUCCESSFULLY = "پیام های ارسالی با موفقیت دریافت شد",
SENT_MESSAGES_RETRIEVAL_FAILED = "دریافت پیام های ارسالی با خطا مواجه شد",
TRASH_MESSAGES_RETRIEVED_SUCCESSFULLY = "پیام های حذف شده با موفقیت دریافت شد",
TRASH_MESSAGES_RETRIEVAL_FAILED = "دریافت پیام های حذف شده با خطا مواجه شد",
}
export const enum SmsMessage {
@@ -18,6 +18,15 @@ export class LocalJwtStrategy extends PassportStrategy(Strategy, LOCAL_JWT_STRAT
}
async validate(payload: ITokenPayload) {
return { id: payload.id, role: payload.role };
return {
id: payload.id,
role: payload.role,
inboxId: payload.inboxId,
draftsId: payload.draftsId,
junkId: payload.junkId,
sentId: payload.sentId,
trashId: payload.trashId,
wildduckUserId: payload.wildduckUserId,
};
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
import { ApiProperty } from "@nestjs/swagger";
import { Transform } from "class-transformer";
import { IsNotEmpty, IsNumberString, IsString } from "class-validator";
import { IsNotEmpty, IsNumber, IsNumberString, IsString } from "class-validator";
import { EmailMessage } from "../../../common/enums/message.enum";
@@ -42,6 +42,6 @@ export class UserMailboxParamDto {
export class UserMailboxMessageParamDto {
@ApiProperty({ description: "Message ID", example: "12345" })
@Transform(({ value }) => parseInt(value))
@IsNumberString({ no_symbols: true }, { message: EmailMessage.MESSAGE_ID_MUST_BE_NUMBER })
@IsNumber({}, { message: EmailMessage.MESSAGE_ID_MUST_BE_NUMBER })
messageId: number;
}
+32 -8
View File
@@ -1,4 +1,4 @@
import { Body, Controller, Delete, Get, Param, Post, Query } from "@nestjs/common";
import { Body, Controller, Delete, Get, Param, Patch, Post, Query } from "@nestjs/common";
import { ApiOperation, ApiResponse } from "@nestjs/swagger";
import { QueueIdParamDto, UserMailboxMessageParamDto } from "./DTO/email-params.dto";
@@ -9,8 +9,8 @@ import { EmailService } from "./services/email.service";
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
import { UserDec } from "../../common/decorators/user.decorator";
@Controller("email")
@AuthGuards()
@Controller("email")
export class EmailController {
constructor(private readonly emailService: EmailService) {}
@@ -19,8 +19,8 @@ export class EmailController {
@ApiResponse({ status: 201, description: "Email sent successfully" })
@ApiResponse({ status: 400, description: "Invalid email data" })
@ApiResponse({ status: 403, description: "Not authorized to send email" })
sendEmail(@UserDec("id") userId: string, @Body() sendEmailDto: SendEmailDto) {
return this.emailService.sendEmail(userId, sendEmailDto);
sendEmail(@UserDec("wildduckUserId") userEmailId: string, @Body() sendEmailDto: SendEmailDto) {
return this.emailService.sendEmail(userEmailId, sendEmailDto);
}
@Get("status/:queueId")
@@ -35,7 +35,7 @@ export class EmailController {
@ApiOperation({ summary: "List messages in a inbox" })
@ApiResponse({ status: 200, description: "List of messages" })
@ApiResponse({ status: 404, description: "Mailbox not found" })
listMessages(@UserDec("id") userId: string, @UserDec("inboxId") inboxId: string, @Query() query: MessageListQueryDto) {
listMessages(@UserDec("wildduckUserId") userId: string, @UserDec("inboxId") inboxId: string, @Query() query: MessageListQueryDto) {
return this.emailService.listMessages(userId, inboxId, query);
}
@@ -43,7 +43,7 @@ export class EmailController {
@ApiOperation({ summary: "Get a specific message" })
@ApiResponse({ status: 200, description: "Message details" })
@ApiResponse({ status: 404, description: "Message not found" })
getMessage(@UserDec("id") userId: string, @UserDec("inboxId") inboxId: string, @Param() params: UserMailboxMessageParamDto) {
getMessage(@UserDec("wildduckUserId") userId: string, @UserDec("inboxId") inboxId: string, @Param() params: UserMailboxMessageParamDto) {
return this.emailService.getMessage(userId, inboxId, params.messageId);
}
@@ -51,14 +51,38 @@ export class EmailController {
@ApiOperation({ summary: "Delete a message" })
@ApiResponse({ status: 200, description: "Message deleted successfully" })
@ApiResponse({ status: 404, description: "Message not found" })
deleteMessage(@UserDec("id") userId: string, @UserDec("inboxId") inboxId: string, @Param() params: UserMailboxMessageParamDto) {
deleteMessage(@UserDec("wildduckUserId") userId: string, @UserDec("inboxId") inboxId: string, @Param() params: UserMailboxMessageParamDto) {
return this.emailService.deleteMessage(userId, inboxId, params.messageId);
}
@Get("search")
@ApiOperation({ summary: "Search messages across all mailboxes" })
@ApiResponse({ status: 200, description: "Search results" })
searchMessages(@UserDec("id") userId: string, @Query() query: SearchMessagesQueryDto) {
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, @UserDec("inboxId") inboxId: string, @Param() params: UserMailboxMessageParamDto) {
return this.emailService.markMessageAsSeen(userId, inboxId, Number(params.messageId));
}
@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, @UserDec("sentId") sentId: string, @Query() query: MessageListQueryDto) {
return this.emailService.getSentMessages(userId, sentId, 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, @UserDec("trashId") trashId: string, @Query() query: MessageListQueryDto) {
return this.emailService.getTrashMessages(userId, trashId, query);
}
}
+67 -19
View File
@@ -3,7 +3,6 @@ import { firstValueFrom } from "rxjs";
import { EmailMessage } from "../../../common/enums/message.enum";
import { MailServerService } from "../../mail-server/services/mail-server.service";
import { UsersService } from "../../users/services/users.service";
import { MessageListQueryDto, SearchMessagesQueryDto } from "../DTO/email-query.dto";
import { SendEmailDto } from "../DTO/send-email.dto";
@@ -13,12 +12,12 @@ export class EmailService {
constructor(
private readonly mailServerService: MailServerService,
private readonly userService: UsersService,
// private readonly userService: UsersService,
) {}
//########################################################
async sendEmail(userId: string, sendEmailDto: SendEmailDto) {
const userEmailId = await this.userService.getUserEmailIdFromId(userId);
async sendEmail(userEmailId: string, sendEmailDto: SendEmailDto) {
// const userEmailId = await this.userService.getUserEmailIdFromId(userId);
this.logger.log(`Sending email from user ${userEmailId} to ${sendEmailDto.to.map((t) => t.address).join(", ")}`);
@@ -87,13 +86,15 @@ export class EmailService {
this.logger.log(`Listing messages in mailbox ${inboxId} for user: ${userId}`);
try {
const response = await firstValueFrom(this.mailServerService.messages.listMessages(userId, inboxId, query));
const { results, total: count } = await firstValueFrom(this.mailServerService.messages.listMessages(userId, inboxId, query));
this.logger.log(`Found ${response.results.length} messages in mailbox ${inboxId} for user: ${userId}`);
this.logger.log(`Found ${count} messages in mailbox ${inboxId} for user: ${userId}`);
return {
message: EmailMessage.MESSAGES_LISTED_SUCCESSFULLY,
...response,
results,
count,
paginate: true,
};
} catch (error) {
this.logger.error(
@@ -104,17 +105,17 @@ export class EmailService {
}
//########################################################
async getMessage(userId: string, mailboxId: string, messageId: number) {
this.logger.log(`Getting message ${messageId} from mailbox ${mailboxId} for user: ${userId}`);
async getMessage(userId: string, inboxId: string, messageId: number) {
this.logger.log(`Getting message ${messageId} from inbox ${inboxId} for user: ${userId}`);
try {
const response = await firstValueFrom(this.mailServerService.messages.getMessage(userId, mailboxId, messageId));
await this.markMessageAsSeen(userId, inboxId, messageId);
const message = await firstValueFrom(this.mailServerService.messages.getMessage(userId, inboxId, messageId));
this.logger.log(`Retrieved message ${messageId} for user: ${userId}`);
return {
message: EmailMessage.MESSAGE_RETRIEVED_SUCCESSFULLY,
...response,
message,
};
} catch (error) {
this.logger.error(`Failed to get message ${messageId} for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -123,21 +124,68 @@ export class EmailService {
}
//########################################################
async deleteMessage(userId: string, mailboxId: string, messageId: number) {
this.logger.log(`Deleting message ${messageId} from mailbox ${mailboxId} for user: ${userId}`);
async deleteMessage(userId: string, inboxId: string, messageId: number) {
try {
const response = await firstValueFrom(this.mailServerService.messages.deleteMessage(userId, mailboxId, messageId));
this.logger.log(`Deleted message ${messageId} for user: ${userId}`);
const result = await firstValueFrom(this.mailServerService.messages.deleteMessage(userId, inboxId, messageId));
return {
success: true,
message: EmailMessage.MESSAGE_DELETED_SUCCESSFULLY,
...response,
result,
};
} catch (error) {
this.logger.error(`Failed to delete message ${messageId} for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
throw error;
}
}
//==============================================
async markMessageAsSeen(userId: string, inboxId: string, messageId: number) {
try {
const result = await firstValueFrom(this.mailServerService.messages.updateMessage(userId, inboxId, messageId, { seen: true }));
return {
success: true,
message: EmailMessage.MESSAGE_MARKED_AS_SEEN_SUCCESSFULLY,
data: result,
};
} catch (error) {
this.logger.error(
`Failed to mark message ${messageId} as seen for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`,
);
throw error;
}
}
//==============================================
async getSentMessages(userId: string, sentId: string, query: MessageListQueryDto) {
try {
const result = await firstValueFrom(this.mailServerService.messages.listMessages(userId, sentId, query));
return {
success: true,
message: EmailMessage.SENT_MESSAGES_RETRIEVED_SUCCESSFULLY,
data: result,
};
} catch (error) {
this.logger.error(`Failed to get sent messages for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
throw error;
}
}
//==============================================
async getTrashMessages(userId: string, trashId: string, query: MessageListQueryDto) {
try {
const result = await firstValueFrom(this.mailServerService.messages.listMessages(userId, trashId, query));
return {
success: true,
message: EmailMessage.TRASH_MESSAGES_RETRIEVED_SUCCESSFULLY,
data: result,
};
} catch (error) {
this.logger.error(`Failed to get trash messages for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
throw error;
}
}
}