chore: changes
This commit is contained in:
@@ -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 req = ctx.switchToHttp().getRequest<FastifyRequest>();
|
||||||
const user = req.user;
|
const user = req.user;
|
||||||
|
|
||||||
|
|||||||
@@ -186,6 +186,14 @@ export const enum EmailMessage {
|
|||||||
SEND_TIME_MUST_BE_DATE = "زمان ارسال باید یک تاریخ معتبر باشد",
|
SEND_TIME_MUST_BE_DATE = "زمان ارسال باید یک تاریخ معتبر باشد",
|
||||||
UPLOAD_ONLY_MUST_BE_BOOLEAN = "حالت فقط آپلود باید بولین باشد",
|
UPLOAD_ONLY_MUST_BE_BOOLEAN = "حالت فقط آپلود باید بولین باشد",
|
||||||
ENVELOPE_MUST_BE_VALID = "envelope باید معتبر باشد",
|
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 {
|
export const enum SmsMessage {
|
||||||
|
|||||||
@@ -18,6 +18,15 @@ export class LocalJwtStrategy extends PassportStrategy(Strategy, LOCAL_JWT_STRAT
|
|||||||
}
|
}
|
||||||
|
|
||||||
async validate(payload: ITokenPayload) {
|
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,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ApiProperty } from "@nestjs/swagger";
|
import { ApiProperty } from "@nestjs/swagger";
|
||||||
import { Transform } from "class-transformer";
|
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";
|
import { EmailMessage } from "../../../common/enums/message.enum";
|
||||||
|
|
||||||
@@ -42,6 +42,6 @@ export class UserMailboxParamDto {
|
|||||||
export class UserMailboxMessageParamDto {
|
export class UserMailboxMessageParamDto {
|
||||||
@ApiProperty({ description: "Message ID", example: "12345" })
|
@ApiProperty({ description: "Message ID", example: "12345" })
|
||||||
@Transform(({ value }) => parseInt(value))
|
@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;
|
messageId: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 { ApiOperation, ApiResponse } from "@nestjs/swagger";
|
||||||
|
|
||||||
import { QueueIdParamDto, UserMailboxMessageParamDto } from "./DTO/email-params.dto";
|
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 { AuthGuards } from "../../common/decorators/auth-guard.decorator";
|
||||||
import { UserDec } from "../../common/decorators/user.decorator";
|
import { UserDec } from "../../common/decorators/user.decorator";
|
||||||
|
|
||||||
@Controller("email")
|
|
||||||
@AuthGuards()
|
@AuthGuards()
|
||||||
|
@Controller("email")
|
||||||
export class EmailController {
|
export class EmailController {
|
||||||
constructor(private readonly emailService: EmailService) {}
|
constructor(private readonly emailService: EmailService) {}
|
||||||
|
|
||||||
@@ -19,8 +19,8 @@ export class EmailController {
|
|||||||
@ApiResponse({ status: 201, description: "Email sent successfully" })
|
@ApiResponse({ status: 201, description: "Email sent successfully" })
|
||||||
@ApiResponse({ status: 400, description: "Invalid email data" })
|
@ApiResponse({ status: 400, description: "Invalid email data" })
|
||||||
@ApiResponse({ status: 403, description: "Not authorized to send email" })
|
@ApiResponse({ status: 403, description: "Not authorized to send email" })
|
||||||
sendEmail(@UserDec("id") userId: string, @Body() sendEmailDto: SendEmailDto) {
|
sendEmail(@UserDec("wildduckUserId") userEmailId: string, @Body() sendEmailDto: SendEmailDto) {
|
||||||
return this.emailService.sendEmail(userId, sendEmailDto);
|
return this.emailService.sendEmail(userEmailId, sendEmailDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get("status/:queueId")
|
@Get("status/:queueId")
|
||||||
@@ -35,7 +35,7 @@ export class EmailController {
|
|||||||
@ApiOperation({ summary: "List messages in a inbox" })
|
@ApiOperation({ summary: "List messages in a inbox" })
|
||||||
@ApiResponse({ status: 200, description: "List of messages" })
|
@ApiResponse({ status: 200, description: "List of messages" })
|
||||||
@ApiResponse({ status: 404, description: "Mailbox not found" })
|
@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);
|
return this.emailService.listMessages(userId, inboxId, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ export class EmailController {
|
|||||||
@ApiOperation({ summary: "Get a specific message" })
|
@ApiOperation({ summary: "Get a specific message" })
|
||||||
@ApiResponse({ status: 200, description: "Message details" })
|
@ApiResponse({ status: 200, description: "Message details" })
|
||||||
@ApiResponse({ status: 404, description: "Message not found" })
|
@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);
|
return this.emailService.getMessage(userId, inboxId, params.messageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,14 +51,38 @@ export class EmailController {
|
|||||||
@ApiOperation({ summary: "Delete a message" })
|
@ApiOperation({ summary: "Delete a message" })
|
||||||
@ApiResponse({ status: 200, description: "Message deleted successfully" })
|
@ApiResponse({ status: 200, description: "Message deleted successfully" })
|
||||||
@ApiResponse({ status: 404, description: "Message not found" })
|
@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);
|
return this.emailService.deleteMessage(userId, inboxId, params.messageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get("search")
|
@Get("search")
|
||||||
@ApiOperation({ summary: "Search messages across all mailboxes" })
|
@ApiOperation({ summary: "Search messages across all mailboxes" })
|
||||||
@ApiResponse({ status: 200, description: "Search results" })
|
@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);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { firstValueFrom } from "rxjs";
|
|||||||
|
|
||||||
import { EmailMessage } from "../../../common/enums/message.enum";
|
import { EmailMessage } from "../../../common/enums/message.enum";
|
||||||
import { MailServerService } from "../../mail-server/services/mail-server.service";
|
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 { MessageListQueryDto, SearchMessagesQueryDto } from "../DTO/email-query.dto";
|
||||||
import { SendEmailDto } from "../DTO/send-email.dto";
|
import { SendEmailDto } from "../DTO/send-email.dto";
|
||||||
|
|
||||||
@@ -13,12 +12,12 @@ export class EmailService {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly mailServerService: MailServerService,
|
private readonly mailServerService: MailServerService,
|
||||||
private readonly userService: UsersService,
|
// private readonly userService: UsersService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
//########################################################
|
//########################################################
|
||||||
async sendEmail(userId: string, sendEmailDto: SendEmailDto) {
|
async sendEmail(userEmailId: string, sendEmailDto: SendEmailDto) {
|
||||||
const userEmailId = await this.userService.getUserEmailIdFromId(userId);
|
// const userEmailId = await this.userService.getUserEmailIdFromId(userId);
|
||||||
|
|
||||||
this.logger.log(`Sending email from user ${userEmailId} to ${sendEmailDto.to.map((t) => t.address).join(", ")}`);
|
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}`);
|
this.logger.log(`Listing messages in mailbox ${inboxId} for user: ${userId}`);
|
||||||
|
|
||||||
try {
|
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 {
|
return {
|
||||||
message: EmailMessage.MESSAGES_LISTED_SUCCESSFULLY,
|
message: EmailMessage.MESSAGES_LISTED_SUCCESSFULLY,
|
||||||
...response,
|
results,
|
||||||
|
count,
|
||||||
|
paginate: true,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
@@ -104,17 +105,17 @@ export class EmailService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//########################################################
|
//########################################################
|
||||||
async getMessage(userId: string, mailboxId: string, messageId: number) {
|
async getMessage(userId: string, inboxId: string, messageId: number) {
|
||||||
this.logger.log(`Getting message ${messageId} from mailbox ${mailboxId} for user: ${userId}`);
|
this.logger.log(`Getting message ${messageId} from inbox ${inboxId} for user: ${userId}`);
|
||||||
|
|
||||||
try {
|
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}`);
|
this.logger.log(`Retrieved message ${messageId} for user: ${userId}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message: EmailMessage.MESSAGE_RETRIEVED_SUCCESSFULLY,
|
message,
|
||||||
...response,
|
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to get message ${messageId} for user ${userId}: ${error instanceof Error ? error.message : "Unknown 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) {
|
async deleteMessage(userId: string, inboxId: string, messageId: number) {
|
||||||
this.logger.log(`Deleting message ${messageId} from mailbox ${mailboxId} for user: ${userId}`);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await firstValueFrom(this.mailServerService.messages.deleteMessage(userId, mailboxId, messageId));
|
const result = await firstValueFrom(this.mailServerService.messages.deleteMessage(userId, inboxId, messageId));
|
||||||
|
|
||||||
this.logger.log(`Deleted message ${messageId} for user: ${userId}`);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
success: true,
|
||||||
message: EmailMessage.MESSAGE_DELETED_SUCCESSFULLY,
|
message: EmailMessage.MESSAGE_DELETED_SUCCESSFULLY,
|
||||||
...response,
|
result,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to delete message ${messageId} for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(`Failed to delete message ${messageId} for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
throw 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user