172 lines
5.0 KiB
TypeScript
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 || "";
|
|
}
|
|
}
|