From c739e0bd5963947a1f1d5d40be8807ed7ecddc67 Mon Sep 17 00:00:00 2001 From: mahyargdz Date: Wed, 23 Jul 2025 14:46:15 +0330 Subject: [PATCH] chore: add unread event for webscoket --- src/modules/email/gateways/email.gateway.ts | 6 +++ .../services/email-notification.service.ts | 35 +++++++++++++ src/modules/email/services/email.service.ts | 5 ++ .../mailbox/services/mailbox.service.ts | 49 ++++--------------- 4 files changed, 55 insertions(+), 40 deletions(-) diff --git a/src/modules/email/gateways/email.gateway.ts b/src/modules/email/gateways/email.gateway.ts index f50dc60..d363084 100644 --- a/src/modules/email/gateways/email.gateway.ts +++ b/src/modules/email/gateways/email.gateway.ts @@ -134,6 +134,12 @@ export class EmailGateway implements OnGatewayInit, OnGatewayConnection, OnGatew async notifyEmailRead(userId: string, data: EmailStatusPayload) { return await this.sendUserNotification(userId, WEBSOCKET_EVENTS.EMAIL_READ, data, `Message ${data.messageId} marked as read`); } + + //************************************************************************ */ + async notifyEmailUnread(userId: string, data: EmailStatusPayload) { + return await this.sendUserNotification(userId, WEBSOCKET_EVENTS.EMAIL_UNREAD, data, `Message ${data.messageId} marked as unread`); + } + //************************************************************************ */ async notifyEmailDeleted(userId: string, data: EmailDeletePayload) { return await this.sendUserNotification(userId, WEBSOCKET_EVENTS.EMAIL_DELETED, data, `Message ${data.messageId} deleted`); diff --git a/src/modules/email/services/email-notification.service.ts b/src/modules/email/services/email-notification.service.ts index 0e6b088..5e7ae71 100644 --- a/src/modules/email/services/email-notification.service.ts +++ b/src/modules/email/services/email-notification.service.ts @@ -58,6 +58,41 @@ export class EmailNotificationService { } } + //************************************************************************ */ + async notifyEmailUnread(params: EmailStatusNotificationParams) { + try { + const em = this.em.fork(); + const user = await em.findOne(User, { + wildduckUserId: params.userId, + emailEnabled: true, + deletedAt: null, + }); + + if (!user) { + this.logger.warn(`User not found with wildduckUserId: ${params.userId}`); + return; + } + + const payload: EmailStatusPayload = { + userId: user.id, + messageId: params.messageId, + mailboxId: params.mailboxId, + timestamp: new Date().toISOString(), + }; + + const success = await this.emailGateway.notifyEmailUnread(user.id, payload); + await this.updateUnreadCount(params.userId); + + if (success) { + this.logger.log(`Email unread notification dispatched for user ${user.id}: message ${params.messageId}`); + } else { + this.logger.warn(`Failed to dispatch email unread notification for user ${user.id}: user not connected`); + } + } catch (error) { + this.logger.error(`Failed to notify email unread for user ${params.userId}:`, error); + } + } + //************************************************************************ */ async notifyEmailRead(params: EmailStatusNotificationParams) { try { diff --git a/src/modules/email/services/email.service.ts b/src/modules/email/services/email.service.ts index b60a87a..4e0b52d 100644 --- a/src/modules/email/services/email.service.ts +++ b/src/modules/email/services/email.service.ts @@ -237,6 +237,11 @@ export class EmailService { async markMessageAsUnseen(wildduckUserId: string, messageId: number, mailboxId: string) { const { updated } = await firstValueFrom(this.mailServerService.messages.updateMessage(wildduckUserId, mailboxId, messageId, { seen: false })); + await this.emailNotificationService.notifyEmailUnread({ + userId: wildduckUserId, + messageId, + mailboxId, + }); return { success: true, message: EmailMessage.MESSAGE_MARKED_AS_UNSEEN_SUCCESSFULLY, diff --git a/src/modules/mailbox/services/mailbox.service.ts b/src/modules/mailbox/services/mailbox.service.ts index addf24b..16fc1eb 100644 --- a/src/modules/mailbox/services/mailbox.service.ts +++ b/src/modules/mailbox/services/mailbox.service.ts @@ -11,9 +11,7 @@ export class MailboxService { constructor(private readonly mailServerService: MailServerService) {} - /** - * List all mailboxes for a user - */ + //######################################################## listMailboxes(userId: string, query?: MailboxQueryDto): Observable { this.logger.log(`Listing mailboxes for user: ${userId}`); @@ -29,50 +27,27 @@ export class MailboxService { ); } - /** - * Get mailbox message counts for a user - */ + //######################################################## getMailboxCounts(userId: string) { - this.logger.log(`Getting mailbox counts for user: ${userId}`); - return this.mailServerService.mailboxes.listMailboxes(userId, { counters: true }).pipe( map((response) => { - this.logger.log(`Found ${response.results.length} mailboxes with counts for user: ${userId}`); - const mailboxes = response.results.map((mailbox) => ({ id: mailbox.id, name: mailbox.name, - path: mailbox.path, - specialUse: mailbox.specialUse, - total: mailbox.total || 0, unseen: mailbox.unseen || 0, - size: mailbox.size || 0, + total: mailbox.total || 0, })); - const totalMailboxes = mailboxes.length; - const totalMessages = mailboxes.reduce((sum, mailbox) => sum + mailbox.total, 0); - const totalUnseen = mailboxes.reduce((sum, mailbox) => sum + mailbox.unseen, 0); - const totalSize = mailboxes.reduce((sum, mailbox) => sum + mailbox.size, 0); - - return { - mailboxes, - totalMailboxes, - totalMessages, - totalUnseen, - totalSize, - }; + return { mailboxes }; }), catchError((error) => { - this.logger.error(`Failed to get mailbox counts for user ${userId}: ${error.message}`); return throwError(() => error); }), ); } - /** - * Get a specific mailbox - */ - getMailbox(userId: string, mailboxId: string): Observable { + //######################################################## + getMailbox(userId: string, mailboxId: string) { this.logger.log(`Getting mailbox ${mailboxId} for user: ${userId}`); return this.mailServerService.mailboxes.getMailbox(userId, mailboxId).pipe( @@ -90,9 +65,7 @@ export class MailboxService { ); } - /** - * Create a new mailbox - */ + //######################################################## createMailbox(userId: string, createMailboxDto: CreateMailboxDto): Observable { this.logger.log(`Creating mailbox "${createMailboxDto.path}" for user: ${userId}`); @@ -108,9 +81,7 @@ export class MailboxService { ); } - /** - * Update a mailbox - */ + //######################################################## updateMailbox(userId: string, mailboxId: string, updateMailboxDto: UpdateMailboxDto): Observable { this.logger.log(`Updating mailbox ${mailboxId} for user: ${userId}`); @@ -129,9 +100,7 @@ export class MailboxService { ); } - /** - * Delete a mailbox - */ + //######################################################## deleteMailbox(userId: string, mailboxId: string): Observable { this.logger.log(`Deleting mailbox ${mailboxId} for user: ${userId}`);