Files
dmail-api/src/modules/email/services/mailbox-resolver.service.ts
T
2025-07-12 12:13:26 +03:30

172 lines
5.0 KiB
TypeScript

import { Injectable, Logger, NotFoundException } from "@nestjs/common";
import { firstValueFrom } from "rxjs";
import { MailboxInfo } from "../../mail-server/interfaces/mailboxes-response.interface";
import { MailServerService } from "../../mail-server/services/mail-server.service";
import { MailboxEnum } from "../../mailbox/enums/mailbox.enum";
export interface UserMailboxIds {
inbox: string;
sent: string;
drafts: string;
trash: string;
junk: string;
archive: string;
favorite: string;
}
@Injectable()
export class MailboxResolverService {
private readonly logger = new Logger(MailboxResolverService.name);
private readonly mailboxCache = new Map<string, UserMailboxIds>();
private readonly cacheExpiry = new Map<string, number>();
private readonly CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
constructor(private readonly mailServerService: MailServerService) {}
/**
* Get user mailbox IDs with caching
*/
async getUserMailboxIds(userId: string): Promise<UserMailboxIds> {
const cached = this.getCachedMailboxIds(userId);
if (cached) return cached;
this.logger.log(`Fetching mailbox IDs for user: ${userId}`);
try {
const mailboxes = await firstValueFrom(this.mailServerService.mailboxes.listMailboxes(userId));
const mailboxIds: UserMailboxIds = {
inbox: this.findMailboxId(mailboxes.results, MailboxEnum.INBOX),
sent: this.findMailboxId(mailboxes.results, MailboxEnum.SENT),
drafts: this.findMailboxId(mailboxes.results, MailboxEnum.DRAFTS),
trash: this.findMailboxId(mailboxes.results, MailboxEnum.TRASH),
junk: this.findMailboxId(mailboxes.results, MailboxEnum.Junk, false),
archive: this.findMailboxId(mailboxes.results, MailboxEnum.ARCHIVE, false),
favorite: this.findMailboxId(mailboxes.results, MailboxEnum.FAVORITE, false),
};
this.cacheMailboxIds(userId, mailboxIds);
this.logger.log(`Mailbox IDs cached for user: ${userId}`);
return mailboxIds;
} catch (error) {
this.logger.error(`Failed to fetch mailbox IDs for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
throw error;
}
}
/**
* Get specific mailbox ID
*/
async getMailboxId(userId: string, mailboxType: keyof UserMailboxIds): Promise<string> {
const mailboxIds = await this.getUserMailboxIds(userId);
const mailboxId = mailboxIds[mailboxType];
if (!mailboxId) {
throw new NotFoundException(`${mailboxType} mailbox not found for user ${userId}`);
}
return mailboxId;
}
/**
* Get drafts mailbox ID
*/
async getDraftsMailboxId(userId: string): Promise<string> {
return this.getMailboxId(userId, "drafts");
}
/**
* Get inbox mailbox ID
*/
async getInboxMailboxId(userId: string): Promise<string> {
return this.getMailboxId(userId, "inbox");
}
/**
* Get sent mailbox ID
*/
async getSentMailboxId(userId: string): Promise<string> {
return this.getMailboxId(userId, "sent");
}
/**
* Get trash mailbox ID
*/
async getTrashMailboxId(userId: string): Promise<string> {
return this.getMailboxId(userId, "trash");
}
async getJunkMailboxId(userId: string): Promise<string> {
return this.getMailboxId(userId, "junk");
}
async getArchiveMailboxId(userId: string): Promise<string> {
return this.getMailboxId(userId, "archive");
}
async getFavoriteMailboxId(userId: string): Promise<string> {
return this.getMailboxId(userId, "favorite");
}
/**
* Clear cache for a specific user
*/
clearUserCache(userId: string): void {
this.mailboxCache.delete(userId);
this.cacheExpiry.delete(userId);
this.logger.log(`Cache cleared for user: ${userId}`);
}
/**
* Clear all cache
*/
clearAllCache(): void {
this.mailboxCache.clear();
this.cacheExpiry.clear();
this.logger.log("All mailbox cache cleared");
}
/**
* Get cached mailbox IDs if not expired
*/
private getCachedMailboxIds(userId: string): UserMailboxIds | null {
const cached = this.mailboxCache.get(userId);
const expiry = this.cacheExpiry.get(userId);
if (cached && expiry && Date.now() < expiry) {
this.logger.debug(`Using cached mailbox IDs for user: ${userId}`);
return cached;
}
if (cached) {
this.logger.debug(`Cache expired for user: ${userId}`);
this.clearUserCache(userId);
}
return null;
}
/**
* Cache mailbox IDs with expiry
*/
private cacheMailboxIds(userId: string, mailboxIds: UserMailboxIds): void {
this.mailboxCache.set(userId, mailboxIds);
this.cacheExpiry.set(userId, Date.now() + this.CACHE_DURATION);
}
/**
* Find mailbox ID by name
*/
private findMailboxId(mailboxes: MailboxInfo[], mailboxName: string, required: boolean = true): string {
const mailbox = mailboxes.find((mb) => mb.name === mailboxName || mb.path === mailboxName || mb.specialUse === mailboxName);
if (!mailbox && required) {
throw new NotFoundException(`${mailboxName} mailbox not found`);
}
return mailbox?.id || "";
}
}