chore: add new fetaure
This commit is contained in:
@@ -212,6 +212,7 @@ export const enum EmailMessage {
|
|||||||
MESSAGE_MOVED_TO_INBOX_FROM_ARCHIVE_SUCCESSFULLY = "پیام با موفقیت از آرشیو به صندوق ورودی منتقل شد",
|
MESSAGE_MOVED_TO_INBOX_FROM_ARCHIVE_SUCCESSFULLY = "پیام با موفقیت از آرشیو به صندوق ورودی منتقل شد",
|
||||||
MESSAGE_MOVED_TO_INBOX_FROM_FAVORITE_SUCCESSFULLY = "پیام با موفقیت از علاقه مندی ها به صندوق ورودی منتقل شد",
|
MESSAGE_MOVED_TO_INBOX_FROM_FAVORITE_SUCCESSFULLY = "پیام با موفقیت از علاقه مندی ها به صندوق ورودی منتقل شد",
|
||||||
MESSAGE_MOVED_TO_INBOX_FROM_TRASH_SUCCESSFULLY = "پیام با موفقیت از سطل زباله به صندوق ورودی منتقل شد",
|
MESSAGE_MOVED_TO_INBOX_FROM_TRASH_SUCCESSFULLY = "پیام با موفقیت از سطل زباله به صندوق ورودی منتقل شد",
|
||||||
|
MESSAGE_MOVED_TO_INBOX_FROM_JUNK_SUCCESSFULLY = "پیام با موفقیت از جانک به صندوق ورودی منتقل شد",
|
||||||
MESSAGE_NOT_FOUND = "پیام یافت نشد",
|
MESSAGE_NOT_FOUND = "پیام یافت نشد",
|
||||||
|
|
||||||
// Bulk action messages
|
// Bulk action messages
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ export enum BulkActionType {
|
|||||||
UNARCHIVE = "unarchive",
|
UNARCHIVE = "unarchive",
|
||||||
RESTORE = "restore",
|
RESTORE = "restore",
|
||||||
JUNK = "junk",
|
JUNK = "junk",
|
||||||
|
NOTJUNK = "notjunk",
|
||||||
TRASH = "trash",
|
TRASH = "trash",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -214,10 +214,19 @@ export class EmailController {
|
|||||||
return this.emailService.moveMessageToJunk(userId, Number(params.messageId));
|
return this.emailService.moveMessageToJunk(userId, Number(params.messageId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Patch("messages/:messageId/not-junk")
|
||||||
|
@ApiOperation({ summary: "Move a message from junk back to inbox (not spam)" })
|
||||||
|
@ApiResponse({ status: 200, description: "Message moved from junk to inbox successfully" })
|
||||||
|
@ApiResponse({ status: 404, description: "Message not found in junk" })
|
||||||
|
@ApiResponse({ status: 403, description: "Not authorized to move message" })
|
||||||
|
moveMessageToInboxFromJunk(@UserDec("wildduckUserId") userId: string, @Param() params: MessageParamDto) {
|
||||||
|
return this.emailService.moveMessageToInboxFromJunk(userId, Number(params.messageId));
|
||||||
|
}
|
||||||
|
|
||||||
@Post("messages/bulk-action")
|
@Post("messages/bulk-action")
|
||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: "Perform bulk actions on multiple messages",
|
summary: "Perform bulk actions on multiple messages",
|
||||||
description: "Apply actions (seen, delete, archive, unarchive, favorite, unfavorite, junk, trash, restore) to multiple messages at once",
|
description: "Apply actions (seen, delete, archive, unarchive, favorite, unfavorite, junk, notjunk, trash, restore) to multiple messages at once",
|
||||||
})
|
})
|
||||||
@ApiResponse({ status: 200, description: "Bulk action completed successfully" })
|
@ApiResponse({ status: 200, description: "Bulk action completed successfully" })
|
||||||
@ApiResponse({ status: 206, description: "Bulk action partially completed" })
|
@ApiResponse({ status: 206, description: "Bulk action partially completed" })
|
||||||
@@ -226,4 +235,51 @@ export class EmailController {
|
|||||||
performBulkAction(@UserDec("wildduckUserId") userId: string, @Body() bulkActionDto: BulkActionDto) {
|
performBulkAction(@UserDec("wildduckUserId") userId: string, @Body() bulkActionDto: BulkActionDto) {
|
||||||
return this.emailService.performBulkAction(userId, bulkActionDto);
|
return this.emailService.performBulkAction(userId, bulkActionDto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // Domain Access Management Endpoints
|
||||||
|
// @Get("spam/domains/allowed")
|
||||||
|
// @ApiOperation({ summary: "List domains in allowlist (never marked as spam)" })
|
||||||
|
// @ApiResponse({ status: 200, description: "List of allowed domains" })
|
||||||
|
// listAllowedDomains(@UserDec("id") userId: string, @Query() query: ListDomainAccessQueryDto) {
|
||||||
|
// return this.emailSpamService.listAllowedDomains(userId, query);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Get("spam/domains/blocked")
|
||||||
|
// @ApiOperation({ summary: "List domains in blocklist (always marked as spam)" })
|
||||||
|
// @ApiResponse({ status: 200, description: "List of blocked domains" })
|
||||||
|
// listBlockedDomains(@UserDec("id") userId: string, @Query() query: ListDomainAccessQueryDto) {
|
||||||
|
// return this.emailSpamService.listBlockedDomains(userId, query);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Post("spam/domains/allowed")
|
||||||
|
// @ApiOperation({ summary: "Add domain to allowlist" })
|
||||||
|
// @ApiResponse({ status: 201, description: "Domain added to allowlist successfully" })
|
||||||
|
// @ApiResponse({ status: 400, description: "Invalid domain data" })
|
||||||
|
// addDomainToAllowlist(@UserDec("id") userId: string, @Body() createDomainDto: CreateDomainAccessDto) {
|
||||||
|
// return this.emailSpamService.addDomainToAllowlist(createDomainDto.domain, createDomainDto.description, userId);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Post("spam/domains/blocked")
|
||||||
|
// @ApiOperation({ summary: "Add domain to blocklist" })
|
||||||
|
// @ApiResponse({ status: 201, description: "Domain added to blocklist successfully" })
|
||||||
|
// @ApiResponse({ status: 400, description: "Invalid domain data" })
|
||||||
|
// addDomainToBlocklist(@UserDec("id") userId: string, @Body() createDomainDto: CreateDomainAccessDto) {
|
||||||
|
// return this.emailSpamService.addDomainToBlocklist(createDomainDto.domain, createDomainDto.description, userId);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Delete("spam/domains/allowed/:domain")
|
||||||
|
// @ApiOperation({ summary: "Remove domain from allowlist" })
|
||||||
|
// @ApiResponse({ status: 200, description: "Domain removed from allowlist successfully" })
|
||||||
|
// @ApiResponse({ status: 404, description: "Domain not found in allowlist" })
|
||||||
|
// removeDomainFromAllowlist(@UserDec("id") userId: string, @Param("domain") domain: string) {
|
||||||
|
// return this.emailSpamService.removeDomainFromAllowlist(domain, userId);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @Delete("spam/domains/blocked/:domain")
|
||||||
|
// @ApiOperation({ summary: "Remove domain from blocklist" })
|
||||||
|
// @ApiResponse({ status: 200, description: "Domain removed from blocklist successfully" })
|
||||||
|
// @ApiResponse({ status: 404, description: "Domain not found in blocklist" })
|
||||||
|
// removeDomainFromBlocklist(@UserDec("id") userId: string, @Param("domain") domain: string) {
|
||||||
|
// return this.emailSpamService.removeDomainFromBlocklist(domain, userId);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,21 +4,22 @@ import { Module } from "@nestjs/common";
|
|||||||
import { JwtModule } from "@nestjs/jwt";
|
import { JwtModule } from "@nestjs/jwt";
|
||||||
|
|
||||||
// import { EmailGatewayController } from "./controllers/email-gateway.controller";
|
// import { EmailGatewayController } from "./controllers/email-gateway.controller";
|
||||||
|
import { EMAIL_QUEUE_CONSTANTS } from "./constants/email-events.constant";
|
||||||
import { EmailController } from "./email.controller";
|
import { EmailController } from "./email.controller";
|
||||||
import { EmailGateway } from "./gateways/email.gateway";
|
import { EmailGateway } from "./gateways/email.gateway";
|
||||||
import { EmailMonitoringProcessor } from "./queue/email-monitoring.processor";
|
import { EmailMonitoringProcessor } from "./queue/email-monitoring.processor";
|
||||||
import { EmailHeadersService } from "./services/email-headers.service";
|
import { EmailHeadersService } from "./services/email-headers.service";
|
||||||
import { EmailMonitoringService } from "./services/email-monitoring.service";
|
import { EmailMonitoringService } from "./services/email-monitoring.service";
|
||||||
import { EmailNotificationService } from "./services/email-notification.service";
|
import { EmailNotificationService } from "./services/email-notification.service";
|
||||||
|
import { EmailSpamService } from "./services/email-spam.service";
|
||||||
import { EmailService } from "./services/email.service";
|
import { EmailService } from "./services/email.service";
|
||||||
import { MailboxResolverService } from "./services/mailbox-resolver.service";
|
import { MailboxResolverService } from "./services/mailbox-resolver.service";
|
||||||
import { jwtConfig } from "../../configs/jwt.config";
|
import { jwtConfig } from "../../configs/jwt.config";
|
||||||
import { MailServerModule } from "../mail-server/mail-server.module";
|
import { MailServerModule } from "../mail-server/mail-server.module";
|
||||||
import { TemplatesModule } from "../templates/templates.module";
|
import { TemplatesModule } from "../templates/templates.module";
|
||||||
|
import { WebSocketAuthService } from "./services/websocket-auth.service";
|
||||||
import { User } from "../users/entities/user.entity";
|
import { User } from "../users/entities/user.entity";
|
||||||
import { UsersModule } from "../users/users.module";
|
import { UsersModule } from "../users/users.module";
|
||||||
import { EMAIL_QUEUE_CONSTANTS } from "./constants/email-events.constant";
|
|
||||||
import { WebSocketAuthService } from "./services/websocket-auth.service";
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -34,6 +35,7 @@ import { WebSocketAuthService } from "./services/websocket-auth.service";
|
|||||||
controllers: [EmailController],
|
controllers: [EmailController],
|
||||||
providers: [
|
providers: [
|
||||||
EmailService,
|
EmailService,
|
||||||
|
EmailSpamService,
|
||||||
MailboxResolverService,
|
MailboxResolverService,
|
||||||
EmailHeadersService,
|
EmailHeadersService,
|
||||||
EmailGateway,
|
EmailGateway,
|
||||||
@@ -42,6 +44,14 @@ import { WebSocketAuthService } from "./services/websocket-auth.service";
|
|||||||
EmailMonitoringProcessor,
|
EmailMonitoringProcessor,
|
||||||
WebSocketAuthService,
|
WebSocketAuthService,
|
||||||
],
|
],
|
||||||
exports: [EmailService, MailboxResolverService, EmailHeadersService, EmailGateway, EmailMonitoringService, EmailNotificationService],
|
exports: [
|
||||||
|
EmailService,
|
||||||
|
EmailSpamService,
|
||||||
|
MailboxResolverService,
|
||||||
|
EmailHeadersService,
|
||||||
|
EmailGateway,
|
||||||
|
EmailMonitoringService,
|
||||||
|
EmailNotificationService,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class EmailModule {}
|
export class EmailModule {}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
export interface SpamActionOptions {
|
||||||
|
messageId: number;
|
||||||
|
wildduckUserId: string;
|
||||||
|
/**
|
||||||
|
* Whether to automatically add the sender's domain to allowlist/blocklist
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
manageDomainList?: boolean;
|
||||||
|
/**
|
||||||
|
* Tag to use for domain access control (defaults to user's business ID or 'default')
|
||||||
|
*/
|
||||||
|
domainTag?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MessageSenderInfo {
|
||||||
|
senderDomain: string;
|
||||||
|
senderEmail: string;
|
||||||
|
messageId: number;
|
||||||
|
}
|
||||||
@@ -0,0 +1,208 @@
|
|||||||
|
import { Injectable, Logger } from "@nestjs/common";
|
||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
|
import { EmailMessage } from "../../../common/enums/message.enum";
|
||||||
|
import { ListDomainAccessQueryDto } from "../../mail-server/DTO/domain-access.dto";
|
||||||
|
import { MailServerService } from "../../mail-server/services/mail-server.service";
|
||||||
|
import { MessageSenderInfo, SpamActionOptions } from "../interfaces/email-spam.interface";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class EmailSpamService {
|
||||||
|
private readonly logger = new Logger(EmailSpamService.name);
|
||||||
|
|
||||||
|
constructor(private readonly mailServerService: MailServerService) {}
|
||||||
|
|
||||||
|
async getMessageSenderInfo(userId: string, messageId: number): Promise<MessageSenderInfo | null> {
|
||||||
|
try {
|
||||||
|
const mailboxes = await firstValueFrom(this.mailServerService.mailboxes.listMailboxes(userId));
|
||||||
|
|
||||||
|
for (const mailbox of mailboxes.results) {
|
||||||
|
try {
|
||||||
|
const message = await firstValueFrom(this.mailServerService.messages.getMessage(userId, mailbox.id, messageId));
|
||||||
|
|
||||||
|
if (message && message.from && message.from.address) {
|
||||||
|
const senderEmail = message.from.address;
|
||||||
|
const senderDomain = senderEmail.split("@")[1]?.toLowerCase();
|
||||||
|
|
||||||
|
if (senderDomain) {
|
||||||
|
return {
|
||||||
|
senderDomain,
|
||||||
|
senderEmail,
|
||||||
|
messageId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (_error) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(`Failed to get sender info for message ${messageId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================
|
||||||
|
async markAsSpam(options: SpamActionOptions) {
|
||||||
|
const { messageId, wildduckUserId, manageDomainList = false, domainTag = "default" } = options;
|
||||||
|
|
||||||
|
this.logger.log(`Marking message ${messageId} as spam for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let domainBlocked = false;
|
||||||
|
|
||||||
|
if (manageDomainList) {
|
||||||
|
const senderInfo = await this.getMessageSenderInfo(wildduckUserId, messageId);
|
||||||
|
|
||||||
|
if (senderInfo) {
|
||||||
|
try {
|
||||||
|
await firstValueFrom(
|
||||||
|
this.mailServerService.domainAccess.addBlockedDomain(domainTag, {
|
||||||
|
domain: senderInfo.senderDomain,
|
||||||
|
description: `Auto-blocked due to spam report from message ${messageId}`,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
domainBlocked = true;
|
||||||
|
this.logger.log(`Added domain ${senderInfo.senderDomain} to blocklist for tag: ${domainTag}`);
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.warn(`Could not add domain to blocklist: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: EmailMessage.MESSAGE_MOVED_TO_JUNK_SUCCESSFULLY,
|
||||||
|
domainBlocked,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(`Failed to mark message ${messageId} as spam: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================
|
||||||
|
async markAsNotSpam(options: SpamActionOptions) {
|
||||||
|
const { messageId, wildduckUserId, manageDomainList = false, domainTag = "default" } = options;
|
||||||
|
|
||||||
|
this.logger.log(`Marking message ${messageId} as not spam for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let domainAllowed = false;
|
||||||
|
|
||||||
|
if (manageDomainList) {
|
||||||
|
const senderInfo = await this.getMessageSenderInfo(wildduckUserId, messageId);
|
||||||
|
|
||||||
|
if (senderInfo) {
|
||||||
|
try {
|
||||||
|
await firstValueFrom(
|
||||||
|
this.mailServerService.domainAccess.addAllowedDomain(domainTag, {
|
||||||
|
domain: senderInfo.senderDomain,
|
||||||
|
description: `Auto-allowed due to not-spam report from message ${messageId}`,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
domainAllowed = true;
|
||||||
|
this.logger.log(`Added domain ${senderInfo.senderDomain} to allowlist for tag: ${domainTag}`);
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.warn(`Could not add domain to allowlist: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: EmailMessage.MESSAGE_MOVED_TO_INBOX_FROM_JUNK_SUCCESSFULLY,
|
||||||
|
domainAllowed,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(`Failed to mark message ${messageId} as not spam: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================
|
||||||
|
async listAllowedDomains(domainTag = "default", query?: ListDomainAccessQueryDto) {
|
||||||
|
this.logger.log(`Listing allowed domains for tag: ${domainTag}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await firstValueFrom(this.mailServerService.domainAccess.listAllowedDomains(domainTag, query));
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(`Failed to list allowed domains: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================
|
||||||
|
async listBlockedDomains(domainTag = "default", query?: ListDomainAccessQueryDto) {
|
||||||
|
this.logger.log(`Listing blocked domains for tag: ${domainTag}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await firstValueFrom(this.mailServerService.domainAccess.listBlockedDomains(domainTag, query));
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(`Failed to list blocked domains: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================
|
||||||
|
async removeDomainFromAllowlist(domain: string, domainTag = "default") {
|
||||||
|
this.logger.log(`Removing domain ${domain} from allowlist for tag: ${domainTag}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await firstValueFrom(this.mailServerService.domainAccess.removeAllowedDomain(domainTag, domain));
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(`Failed to remove domain from allowlist: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================
|
||||||
|
async removeDomainFromBlocklist(domain: string, domainTag = "default") {
|
||||||
|
this.logger.log(`Removing domain ${domain} from blocklist for tag: ${domainTag}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await firstValueFrom(this.mailServerService.domainAccess.removeBlockedDomain(domainTag, domain));
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(`Failed to remove domain from blocklist: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================
|
||||||
|
async addDomainToAllowlist(domain: string, description?: string, domainTag = "default") {
|
||||||
|
this.logger.log(`Adding domain ${domain} to allowlist for tag: ${domainTag}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await firstValueFrom(
|
||||||
|
this.mailServerService.domainAccess.addAllowedDomain(domainTag, {
|
||||||
|
domain,
|
||||||
|
description: description || `Manually added to allowlist`,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(`Failed to add domain to allowlist: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================
|
||||||
|
async addDomainToBlocklist(domain: string, description?: string, domainTag = "default") {
|
||||||
|
this.logger.log(`Adding domain ${domain} to blocklist for tag: ${domainTag}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await firstValueFrom(
|
||||||
|
this.mailServerService.domainAccess.addBlockedDomain(domainTag, {
|
||||||
|
domain,
|
||||||
|
description: description || `Manually added to blocklist`,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(`Failed to add domain to blocklist: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import { firstValueFrom } from "rxjs";
|
|||||||
|
|
||||||
import { EmailHeadersService } from "./email-headers.service";
|
import { EmailHeadersService } from "./email-headers.service";
|
||||||
import { EmailNotificationService } from "./email-notification.service";
|
import { EmailNotificationService } from "./email-notification.service";
|
||||||
|
import { EmailSpamService } from "./email-spam.service";
|
||||||
import { MailboxResolverService } from "./mailbox-resolver.service";
|
import { MailboxResolverService } from "./mailbox-resolver.service";
|
||||||
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";
|
||||||
@@ -26,14 +27,15 @@ export class EmailService {
|
|||||||
private readonly templateProcessorService: TemplateProcessorService,
|
private readonly templateProcessorService: TemplateProcessorService,
|
||||||
private readonly userRepository: UserRepository,
|
private readonly userRepository: UserRepository,
|
||||||
private readonly emailHeadersService: EmailHeadersService,
|
private readonly emailHeadersService: EmailHeadersService,
|
||||||
|
private readonly emailSpamService: EmailSpamService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
//########################################################
|
//########################################################
|
||||||
async sendEmail(userEmailId: string, userId: string, sendEmailDto: SendEmailDto) {
|
async sendEmail(wildduckUserId: string, userId: string, sendEmailDto: SendEmailDto) {
|
||||||
this.logger.log(`Sending ${EmailType.GENERAL} email from user ${userEmailId} to ${sendEmailDto.to.map((t) => t.address).join(", ")}`);
|
this.logger.log(`Sending ${EmailType.GENERAL} email from user ${wildduckUserId} to ${sendEmailDto.to.map((t) => t.address).join(", ")}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const user = await this.userRepository.findOne({ wildduckUserId: userEmailId, deletedAt: null }, { populate: ["business"] });
|
const user = await this.userRepository.findOne({ wildduckUserId, deletedAt: null }, { populate: ["business"] });
|
||||||
if (!user) throw new BadRequestException(EmailMessage.USER_NOT_FOUND);
|
if (!user) throw new BadRequestException(EmailMessage.USER_NOT_FOUND);
|
||||||
this.logger.log(`Processing email through business template for business: ${user.business.id}`);
|
this.logger.log(`Processing email through business template for business: ${user.business.id}`);
|
||||||
|
|
||||||
@@ -64,14 +66,14 @@ export class EmailService {
|
|||||||
|
|
||||||
sendEmailDto.headers = [...headers];
|
sendEmailDto.headers = [...headers];
|
||||||
|
|
||||||
const response = await firstValueFrom(this.mailServerService.submission.submitMessage(userEmailId, sendEmailDto));
|
const response = await firstValueFrom(this.mailServerService.submission.submitMessage(wildduckUserId, sendEmailDto));
|
||||||
|
|
||||||
this.logger.log(`Email sent successfully: ${response.message.id} (Queue: ${response.message.queueId})`);
|
this.logger.log(`Email sent successfully: ${response.message.id} (Queue: ${response.message.queueId})`);
|
||||||
|
|
||||||
const sentMailboxId = await this.mailboxResolverService.getSentMailboxId(userId);
|
const sentMailboxId = await this.mailboxResolverService.getSentMailboxId(wildduckUserId);
|
||||||
|
|
||||||
await this.emailNotificationService.notifyEmailSent({
|
await this.emailNotificationService.notifyEmailSent({
|
||||||
userId,
|
userId: wildduckUserId,
|
||||||
messageId: parseInt(response.message.id),
|
messageId: parseInt(response.message.id),
|
||||||
mailboxId: sentMailboxId,
|
mailboxId: sentMailboxId,
|
||||||
recipients: sendEmailDto.to,
|
recipients: sendEmailDto.to,
|
||||||
@@ -85,7 +87,7 @@ export class EmailService {
|
|||||||
queueId: response.message.queueId,
|
queueId: response.message.queueId,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to send email for user ${userEmailId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(`Failed to send email for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,8 +111,8 @@ export class EmailService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//########################################################
|
//########################################################
|
||||||
async searchMessages(userId: string, query: SearchMessagesQueryDto) {
|
async searchMessages(wildduckUserId: string, query: SearchMessagesQueryDto) {
|
||||||
this.logger.log(`Searching messages for user ${userId} with query: ${query.q}`);
|
this.logger.log(`Searching messages for user ${wildduckUserId} with query: ${query.q}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Transform query parameters for WildDuck API compatibility
|
// Transform query parameters for WildDuck API compatibility
|
||||||
@@ -128,10 +130,10 @@ export class EmailService {
|
|||||||
|
|
||||||
this.logger.debug("Search query for WildDuck:", wildDuckQuery);
|
this.logger.debug("Search query for WildDuck:", wildDuckQuery);
|
||||||
|
|
||||||
const response = await firstValueFrom(this.mailServerService.messages.searchMessages(userId, wildDuckQuery));
|
const response = await firstValueFrom(this.mailServerService.messages.searchMessages(wildduckUserId, wildDuckQuery));
|
||||||
|
|
||||||
this.logger.log(
|
this.logger.log(
|
||||||
`Found ${response.results.length} messages (${response.total} total, page ${response.page}) matching search for user: ${userId}`,
|
`Found ${response.results.length} messages (${response.total} total, page ${response.page}) matching search for user: ${wildduckUserId}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -143,22 +145,22 @@ export class EmailService {
|
|||||||
query: response.query,
|
query: response.query,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to search messages for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(`Failed to search messages for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//########################################################
|
//########################################################
|
||||||
async listMessages(userId: string, query: MessageListQueryDto) {
|
async listMessages(wildduckUserId: string, query: MessageListQueryDto) {
|
||||||
try {
|
try {
|
||||||
const inboxMailboxId = await this.mailboxResolverService.getInboxMailboxId(userId);
|
const inboxMailboxId = await this.mailboxResolverService.getInboxMailboxId(wildduckUserId);
|
||||||
this.logger.log(`Listing messages in mailbox ${inboxMailboxId} for user: ${userId}`);
|
this.logger.log(`Listing messages in mailbox ${inboxMailboxId} for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
const wildDuckQuery = this.transformPaginationQuery(query);
|
const wildDuckQuery = this.transformPaginationQuery(query);
|
||||||
|
|
||||||
const response = await firstValueFrom(this.mailServerService.messages.listMessages(userId, inboxMailboxId, wildDuckQuery));
|
const response = await firstValueFrom(this.mailServerService.messages.listMessages(wildduckUserId, inboxMailboxId, wildDuckQuery));
|
||||||
|
|
||||||
this.logger.log(`Found ${response.total} total messages (page ${response.page}) in mailbox ${inboxMailboxId} for user: ${userId}`);
|
this.logger.log(`Found ${response.total} total messages (page ${response.page}) in mailbox ${inboxMailboxId} for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
results: response.results,
|
results: response.results,
|
||||||
@@ -169,44 +171,44 @@ export class EmailService {
|
|||||||
paginate: true,
|
paginate: true,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to list messages for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(`Failed to list messages for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//########################################################
|
//########################################################
|
||||||
async getMessage(userId: string, messageId: number) {
|
async getMessage(wildduckUserId: string, messageId: number) {
|
||||||
try {
|
try {
|
||||||
const messageLocation = await this.findMessageMailbox(userId, messageId);
|
const messageLocation = await this.findMessageMailbox(wildduckUserId, messageId);
|
||||||
|
|
||||||
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
||||||
|
|
||||||
this.logger.log(`Getting message ${messageId} from ${messageLocation.mailboxName} mailbox for user: ${userId}`);
|
this.logger.log(`Getting message ${messageId} from ${messageLocation.mailboxName} mailbox for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
await this.markMessageAsSeen(userId, messageId);
|
await this.markMessageAsSeen(wildduckUserId, messageId);
|
||||||
const message = await firstValueFrom(this.mailServerService.messages.getMessage(userId, messageLocation.mailboxId, messageId));
|
const message = await firstValueFrom(this.mailServerService.messages.getMessage(wildduckUserId, messageLocation.mailboxId, messageId));
|
||||||
|
|
||||||
this.logger.log(`Retrieved message ${messageId} from ${messageLocation.mailboxName} for user: ${userId}`);
|
this.logger.log(`Retrieved message ${messageId} from ${messageLocation.mailboxName} for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message,
|
message,
|
||||||
};
|
};
|
||||||
} 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 ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//########################################################
|
//########################################################
|
||||||
async deleteMessage(userId: string, messageId: number) {
|
async deleteMessage(wildduckUserId: string, messageId: number) {
|
||||||
try {
|
try {
|
||||||
const messageLocation = await this.findMessageMailbox(userId, messageId);
|
const messageLocation = await this.findMessageMailbox(wildduckUserId, messageId);
|
||||||
|
|
||||||
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
||||||
|
|
||||||
this.logger.log(`Deleting message ${messageId} from ${messageLocation.mailboxName} mailbox for user: ${userId}`);
|
this.logger.log(`Deleting message ${messageId} from ${messageLocation.mailboxName} mailbox for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
const result = await firstValueFrom(this.mailServerService.messages.deleteMessage(userId, messageLocation.mailboxId, messageId));
|
const result = await firstValueFrom(this.mailServerService.messages.deleteMessage(wildduckUserId, messageLocation.mailboxId, messageId));
|
||||||
|
|
||||||
this.logger.log(`Message ${messageId} deleted successfully from ${messageLocation.mailboxName}`);
|
this.logger.log(`Message ${messageId} deleted successfully from ${messageLocation.mailboxName}`);
|
||||||
|
|
||||||
@@ -215,17 +217,19 @@ export class EmailService {
|
|||||||
result,
|
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 ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
|
);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
async deleteAllMessages(userId: string, mailboxId: string) {
|
async deleteAllMessages(wildduckUserId: string, mailboxId: string) {
|
||||||
try {
|
try {
|
||||||
const result = await firstValueFrom(this.mailServerService.messages.deleteAllFromMailbox(userId, mailboxId));
|
const result = await firstValueFrom(this.mailServerService.messages.deleteAllFromMailbox(wildduckUserId, mailboxId));
|
||||||
|
|
||||||
this.logger.log(`All messages deleted successfully from ${mailboxId} for user: ${userId}`);
|
this.logger.log(`All messages deleted successfully from ${mailboxId} for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message: EmailMessage.ALL_MESSAGES_DELETED_SUCCESSFULLY,
|
message: EmailMessage.ALL_MESSAGES_DELETED_SUCCESSFULLY,
|
||||||
@@ -233,28 +237,28 @@ export class EmailService {
|
|||||||
result,
|
result,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to delete all messages for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(`Failed to delete all messages for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
async markMessageAsSeen(userId: string, messageId: number) {
|
async markMessageAsSeen(wildduckUserId: string, messageId: number) {
|
||||||
try {
|
try {
|
||||||
const messageLocation = await this.findMessageMailbox(userId, messageId);
|
const messageLocation = await this.findMessageMailbox(wildduckUserId, messageId);
|
||||||
|
|
||||||
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
||||||
|
|
||||||
this.logger.log(`Marking message ${messageId} as seen in ${messageLocation.mailboxName} mailbox for user: ${userId}`);
|
this.logger.log(`Marking message ${messageId} as seen in ${messageLocation.mailboxName} mailbox for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
const { updated } = await firstValueFrom(
|
const { updated } = await firstValueFrom(
|
||||||
this.mailServerService.messages.updateMessage(userId, messageLocation.mailboxId, messageId, { seen: true }),
|
this.mailServerService.messages.updateMessage(wildduckUserId, messageLocation.mailboxId, messageId, { seen: true }),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.logger.log(`Message ${messageId} marked as seen successfully in ${messageLocation.mailboxName}`);
|
this.logger.log(`Message ${messageId} marked as seen successfully in ${messageLocation.mailboxName}`);
|
||||||
|
|
||||||
await this.emailNotificationService.notifyEmailRead({
|
await this.emailNotificationService.notifyEmailRead({
|
||||||
userId,
|
userId: wildduckUserId,
|
||||||
messageId,
|
messageId,
|
||||||
mailboxId: messageLocation.mailboxId,
|
mailboxId: messageLocation.mailboxId,
|
||||||
});
|
});
|
||||||
@@ -266,20 +270,20 @@ export class EmailService {
|
|||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Failed to mark message ${messageId} as seen for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
`Failed to mark message ${messageId} as seen for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
);
|
);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
async getSentMessages(userId: string, query: MessageListQueryDto) {
|
async getSentMessages(wildduckUserId: string, query: MessageListQueryDto) {
|
||||||
try {
|
try {
|
||||||
const sentMailboxId = await this.mailboxResolverService.getSentMailboxId(userId);
|
const sentMailboxId = await this.mailboxResolverService.getSentMailboxId(wildduckUserId);
|
||||||
const wildDuckQuery = this.transformPaginationQuery(query);
|
const wildDuckQuery = this.transformPaginationQuery(query);
|
||||||
const response = await firstValueFrom(this.mailServerService.messages.listMessages(userId, sentMailboxId, wildDuckQuery));
|
const response = await firstValueFrom(this.mailServerService.messages.listMessages(wildduckUserId, sentMailboxId, wildDuckQuery));
|
||||||
|
|
||||||
this.logger.log(`Found ${response.total} sent messages (page ${response.page}) for user: ${userId}`);
|
this.logger.log(`Found ${response.total} sent messages (page ${response.page}) for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sentMails: response.results,
|
sentMails: response.results,
|
||||||
@@ -290,19 +294,19 @@ export class EmailService {
|
|||||||
paginate: true,
|
paginate: true,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to get sent messages for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(`Failed to get sent messages for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
async getTrashMessages(userId: string, query: MessageListQueryDto) {
|
async getTrashMessages(wildduckUserId: string, query: MessageListQueryDto) {
|
||||||
try {
|
try {
|
||||||
const trashMailboxId = await this.mailboxResolverService.getTrashMailboxId(userId);
|
const trashMailboxId = await this.mailboxResolverService.getTrashMailboxId(wildduckUserId);
|
||||||
const wildDuckQuery = this.transformPaginationQuery(query);
|
const wildDuckQuery = this.transformPaginationQuery(query);
|
||||||
const response = await firstValueFrom(this.mailServerService.messages.listMessages(userId, trashMailboxId, wildDuckQuery));
|
const response = await firstValueFrom(this.mailServerService.messages.listMessages(wildduckUserId, trashMailboxId, wildDuckQuery));
|
||||||
|
|
||||||
this.logger.log(`Found ${response.total} trash messages (page ${response.page}) for user: ${userId}`);
|
this.logger.log(`Found ${response.total} trash messages (page ${response.page}) for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
trashMails: response.results,
|
trashMails: response.results,
|
||||||
@@ -313,19 +317,19 @@ export class EmailService {
|
|||||||
paginate: true,
|
paginate: true,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to get trash messages for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(`Failed to get trash messages for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//==============================================
|
//==============================================
|
||||||
|
|
||||||
async getJunkMessages(userId: string, query: MessageListQueryDto) {
|
async getJunkMessages(wildduckUserId: string, query: MessageListQueryDto) {
|
||||||
try {
|
try {
|
||||||
const junkMailboxId = await this.mailboxResolverService.getJunkMailboxId(userId);
|
const junkMailboxId = await this.mailboxResolverService.getJunkMailboxId(wildduckUserId);
|
||||||
const wildDuckQuery = this.transformPaginationQuery(query);
|
const wildDuckQuery = this.transformPaginationQuery(query);
|
||||||
const response = await firstValueFrom(this.mailServerService.messages.listMessages(userId, junkMailboxId, wildDuckQuery));
|
const response = await firstValueFrom(this.mailServerService.messages.listMessages(wildduckUserId, junkMailboxId, wildDuckQuery));
|
||||||
|
|
||||||
this.logger.log(`Found ${response.total} junk messages (page ${response.page}) for user: ${userId}`);
|
this.logger.log(`Found ${response.total} junk messages (page ${response.page}) for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
junkMails: response.results,
|
junkMails: response.results,
|
||||||
@@ -336,19 +340,19 @@ export class EmailService {
|
|||||||
paginate: true,
|
paginate: true,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to get junk messages for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(`Failed to get junk messages for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//==============================================
|
//==============================================
|
||||||
|
|
||||||
async getArchivedMessages(userId: string, query: MessageListQueryDto) {
|
async getArchivedMessages(wildduckUserId: string, query: MessageListQueryDto) {
|
||||||
try {
|
try {
|
||||||
const archiveMailboxId = await this.mailboxResolverService.getArchiveMailboxId(userId);
|
const archiveMailboxId = await this.mailboxResolverService.getArchiveMailboxId(wildduckUserId);
|
||||||
const wildDuckQuery = this.transformPaginationQuery(query);
|
const wildDuckQuery = this.transformPaginationQuery(query);
|
||||||
const response = await firstValueFrom(this.mailServerService.messages.listMessages(userId, archiveMailboxId, wildDuckQuery));
|
const response = await firstValueFrom(this.mailServerService.messages.listMessages(wildduckUserId, archiveMailboxId, wildDuckQuery));
|
||||||
|
|
||||||
this.logger.log(`Found ${response.total} archived messages (page ${response.page}) for user: ${userId}`);
|
this.logger.log(`Found ${response.total} archived messages (page ${response.page}) for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
archiveMails: response.results,
|
archiveMails: response.results,
|
||||||
@@ -359,19 +363,19 @@ export class EmailService {
|
|||||||
paginate: true,
|
paginate: true,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to get archive messages for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(`Failed to get archive messages for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//==============================================
|
//==============================================
|
||||||
|
|
||||||
async getFavoriteMessages(userId: string, query: MessageListQueryDto) {
|
async getFavoriteMessages(wildduckUserId: string, query: MessageListQueryDto) {
|
||||||
try {
|
try {
|
||||||
const favoriteMailboxId = await this.mailboxResolverService.getFavoriteMailboxId(userId);
|
const favoriteMailboxId = await this.mailboxResolverService.getFavoriteMailboxId(wildduckUserId);
|
||||||
const wildDuckQuery = this.transformPaginationQuery(query);
|
const wildDuckQuery = this.transformPaginationQuery(query);
|
||||||
const response = await firstValueFrom(this.mailServerService.messages.listMessages(userId, favoriteMailboxId, wildDuckQuery));
|
const response = await firstValueFrom(this.mailServerService.messages.listMessages(wildduckUserId, favoriteMailboxId, wildDuckQuery));
|
||||||
|
|
||||||
this.logger.log(`Found ${response.total} favorite messages (page ${response.page}) for user: ${userId}`);
|
this.logger.log(`Found ${response.total} favorite messages (page ${response.page}) for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
favoriteMails: response.results,
|
favoriteMails: response.results,
|
||||||
@@ -382,20 +386,20 @@ export class EmailService {
|
|||||||
paginate: true,
|
paginate: true,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to get favorite messages for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(`Failed to get favorite messages for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
|
|
||||||
async getDraftsMessages(userId: string, query: MessageListQueryDto) {
|
async getDraftsMessages(wildduckUserId: string, query: MessageListQueryDto) {
|
||||||
try {
|
try {
|
||||||
const draftsMailboxId = await this.mailboxResolverService.getDraftsMailboxId(userId);
|
const draftsMailboxId = await this.mailboxResolverService.getDraftsMailboxId(wildduckUserId);
|
||||||
const wildDuckQuery = this.transformPaginationQuery(query);
|
const wildDuckQuery = this.transformPaginationQuery(query);
|
||||||
const response = await firstValueFrom(this.mailServerService.messages.listMessages(userId, draftsMailboxId, wildDuckQuery));
|
const response = await firstValueFrom(this.mailServerService.messages.listMessages(wildduckUserId, draftsMailboxId, wildDuckQuery));
|
||||||
|
|
||||||
this.logger.log(`Found ${response.total} draft messages (page ${response.page}) for user: ${userId}`);
|
this.logger.log(`Found ${response.total} draft messages (page ${response.page}) for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
draftsMail: response.results,
|
draftsMail: response.results,
|
||||||
@@ -406,18 +410,18 @@ export class EmailService {
|
|||||||
paginate: true,
|
paginate: true,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to get drafts messages for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(`Failed to get drafts messages for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
async updateDraft(userEmailId: string, messageId: number, updateDraftDto: UpdateDraftDto) {
|
async updateDraft(wildduckUserId: string, messageId: number, updateDraftDto: UpdateDraftDto) {
|
||||||
this.logger.log(`Updating draft ${messageId} for user ${userEmailId}`);
|
this.logger.log(`Updating draft ${messageId} for user ${wildduckUserId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const draftsMailboxId = await this.mailboxResolverService.getDraftsMailboxId(userEmailId);
|
const draftsMailboxId = await this.mailboxResolverService.getDraftsMailboxId(wildduckUserId);
|
||||||
const existingDraft = await firstValueFrom(this.mailServerService.messages.getMessage(userEmailId, draftsMailboxId, messageId));
|
const existingDraft = await firstValueFrom(this.mailServerService.messages.getMessage(wildduckUserId, draftsMailboxId, messageId));
|
||||||
|
|
||||||
const draftData: SendEmailDto = {
|
const draftData: SendEmailDto = {
|
||||||
// mailbox: updateDraftDto.mailbox,
|
// mailbox: updateDraftDto.mailbox,
|
||||||
@@ -444,7 +448,7 @@ export class EmailService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Process draft content through business template if available
|
// Process draft content through business template if available
|
||||||
const user = await this.userRepository.findOne({ wildduckUserId: userEmailId, deletedAt: null }, { populate: ["business"] });
|
const user = await this.userRepository.findOne({ wildduckUserId, deletedAt: null }, { populate: ["business"] });
|
||||||
|
|
||||||
if (user && user.business && (updateDraftDto.text || updateDraftDto.html)) {
|
if (user && user.business && (updateDraftDto.text || updateDraftDto.html)) {
|
||||||
const processedTemplate = await this.templateProcessorService.processEmailContent(user.business.id, user.id, {
|
const processedTemplate = await this.templateProcessorService.processEmailContent(user.business.id, user.id, {
|
||||||
@@ -466,7 +470,7 @@ export class EmailService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await firstValueFrom(this.mailServerService.submission.submitMessage(userEmailId, draftData));
|
const response = await firstValueFrom(this.mailServerService.submission.submitMessage(wildduckUserId, draftData));
|
||||||
|
|
||||||
this.logger.log(`Draft updated successfully: ${response.message.mailbox}`);
|
this.logger.log(`Draft updated successfully: ${response.message.mailbox}`);
|
||||||
|
|
||||||
@@ -477,44 +481,44 @@ export class EmailService {
|
|||||||
isDraft: true,
|
isDraft: true,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to update draft ${messageId} for user ${userEmailId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(
|
||||||
|
`Failed to update draft ${messageId} for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
|
);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
async sendDraft(userId: string, messageId: number) {
|
async sendDraft(wildduckUserId: string, messageId: number) {
|
||||||
this.logger.log(`Sending draft ${messageId} for user: ${userId}`);
|
this.logger.log(`Sending draft ${messageId} for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const draftsMailboxId = await this.mailboxResolverService.getDraftsMailboxId(userId);
|
const draftsMailboxId = await this.mailboxResolverService.getDraftsMailboxId(wildduckUserId);
|
||||||
const result = await firstValueFrom(
|
const result = await firstValueFrom(
|
||||||
this.mailServerService.messages.submitDraft(userId, draftsMailboxId, messageId, {
|
this.mailServerService.messages.submitDraft(wildduckUserId, draftsMailboxId, messageId, { deleteFiles: false }),
|
||||||
deleteFiles: false,
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
this.logger.log(`Draft ${messageId} sent successfully`);
|
this.logger.log(`Draft ${messageId} sent successfully`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message: EmailMessage.DRAFT_SENT_SUCCESSFULLY,
|
message: EmailMessage.DRAFT_SENT_SUCCESSFULLY,
|
||||||
messageId: result.id,
|
messageId: result.message.id,
|
||||||
queueId: result.queueId,
|
queueId: result.queueId,
|
||||||
result,
|
result,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to send draft ${messageId} for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(`Failed to send draft ${messageId} for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
async deleteDraft(userId: string, messageId: number) {
|
async deleteDraft(wildduckUserId: string, messageId: number) {
|
||||||
this.logger.log(`Deleting draft ${messageId} for user: ${userId}`);
|
this.logger.log(`Deleting draft ${messageId} for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const draftsMailboxId = await this.mailboxResolverService.getDraftsMailboxId(userId);
|
const draftsMailboxId = await this.mailboxResolverService.getDraftsMailboxId(wildduckUserId);
|
||||||
const result = await firstValueFrom(this.mailServerService.messages.deleteMessage(userId, draftsMailboxId, messageId));
|
const result = await firstValueFrom(this.mailServerService.messages.deleteMessage(wildduckUserId, draftsMailboxId, messageId));
|
||||||
|
|
||||||
this.logger.log(`Draft ${messageId} deleted successfully`);
|
this.logger.log(`Draft ${messageId} deleted successfully`);
|
||||||
|
|
||||||
@@ -523,26 +527,28 @@ export class EmailService {
|
|||||||
result,
|
result,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(`Failed to delete draft ${messageId} for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
this.logger.error(
|
||||||
|
`Failed to delete draft ${messageId} for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
|
);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
async moveMessageToArchive(userId: string, messageId: number) {
|
async moveMessageToArchive(wildduckUserId: string, messageId: number) {
|
||||||
this.logger.log(`Moving message ${messageId} to archive for user: ${userId}`);
|
this.logger.log(`Moving message ${messageId} to archive for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const messageLocation = await this.findMessageMailbox(userId, messageId);
|
const messageLocation = await this.findMessageMailbox(wildduckUserId, messageId);
|
||||||
|
|
||||||
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
||||||
|
|
||||||
const archiveMailboxId = await this.mailboxResolverService.getArchiveMailboxId(userId);
|
const archiveMailboxId = await this.mailboxResolverService.getArchiveMailboxId(wildduckUserId);
|
||||||
|
|
||||||
this.logger.log(`Moving message ${messageId} from ${messageLocation.mailboxName} to ${MailboxEnum.ARCHIVE} for user: ${userId}`);
|
this.logger.log(`Moving message ${messageId} from ${messageLocation.mailboxName} to ${MailboxEnum.ARCHIVE} for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
const result = await firstValueFrom(
|
const result = await firstValueFrom(
|
||||||
this.mailServerService.messages.updateMessage(userId, messageLocation.mailboxId, messageId, {
|
this.mailServerService.messages.updateMessage(wildduckUserId, messageLocation.mailboxId, messageId, {
|
||||||
moveTo: archiveMailboxId,
|
moveTo: archiveMailboxId,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -556,27 +562,27 @@ export class EmailService {
|
|||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Failed to move message ${messageId} to archive for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
`Failed to move message ${messageId} to archive for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
);
|
);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
async moveMessageToFavorite(userId: string, messageId: number) {
|
async moveMessageToFavorite(wildduckUserId: string, messageId: number) {
|
||||||
this.logger.log(`Moving message ${messageId} to favorite for user: ${userId}`);
|
this.logger.log(`Moving message ${messageId} to favorite for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const messageLocation = await this.findMessageMailbox(userId, messageId);
|
const messageLocation = await this.findMessageMailbox(wildduckUserId, messageId);
|
||||||
|
|
||||||
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
||||||
|
|
||||||
const favoriteMailboxId = await this.mailboxResolverService.getFavoriteMailboxId(userId);
|
const favoriteMailboxId = await this.mailboxResolverService.getFavoriteMailboxId(wildduckUserId);
|
||||||
|
|
||||||
this.logger.log(`Moving message ${messageId} from ${messageLocation.mailboxName} to ${MailboxEnum.FAVORITE} for user: ${userId}`);
|
this.logger.log(`Moving message ${messageId} from ${messageLocation.mailboxName} to ${MailboxEnum.FAVORITE} for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
const result = await firstValueFrom(
|
const result = await firstValueFrom(
|
||||||
this.mailServerService.messages.updateMessage(userId, messageLocation.mailboxId, messageId, {
|
this.mailServerService.messages.updateMessage(wildduckUserId, messageLocation.mailboxId, messageId, {
|
||||||
moveTo: favoriteMailboxId,
|
moveTo: favoriteMailboxId,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -590,26 +596,27 @@ export class EmailService {
|
|||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Failed to move message ${messageId} to favorite for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
`Failed to move message ${messageId} to favorite for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
);
|
);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async moveMessageToTrash(userId: string, messageId: number) {
|
//==============================================
|
||||||
this.logger.log(`Moving message ${messageId} to trash for user: ${userId}`);
|
async moveMessageToTrash(wildduckUserId: string, messageId: number) {
|
||||||
|
this.logger.log(`Moving message ${messageId} to trash for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const messageLocation = await this.findMessageMailbox(userId, messageId);
|
const messageLocation = await this.findMessageMailbox(wildduckUserId, messageId);
|
||||||
|
|
||||||
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
||||||
|
|
||||||
const trashMailboxId = await this.mailboxResolverService.getTrashMailboxId(userId);
|
const trashMailboxId = await this.mailboxResolverService.getTrashMailboxId(wildduckUserId);
|
||||||
|
|
||||||
this.logger.log(`Moving message ${messageId} from ${messageLocation.mailboxName} to ${MailboxEnum.TRASH} for user: ${userId}`);
|
this.logger.log(`Moving message ${messageId} from ${messageLocation.mailboxName} to ${MailboxEnum.TRASH} for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
const result = await firstValueFrom(
|
const result = await firstValueFrom(
|
||||||
this.mailServerService.messages.updateMessage(userId, messageLocation.mailboxId, messageId, {
|
this.mailServerService.messages.updateMessage(wildduckUserId, messageLocation.mailboxId, messageId, {
|
||||||
moveTo: trashMailboxId,
|
moveTo: trashMailboxId,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -623,22 +630,22 @@ export class EmailService {
|
|||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Failed to move message ${messageId} to trash for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
`Failed to move message ${messageId} to trash for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
);
|
);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
async moveMessageToInboxFromArchive(userId: string, messageId: number) {
|
async moveMessageToInboxFromArchive(wildduckUserId: string, messageId: number) {
|
||||||
this.logger.log(`Moving message ${messageId} from archive to inbox for user: ${userId}`);
|
this.logger.log(`Moving message ${messageId} from archive to inbox for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const inboxMailboxId = await this.mailboxResolverService.getInboxMailboxId(userId);
|
const inboxMailboxId = await this.mailboxResolverService.getInboxMailboxId(wildduckUserId);
|
||||||
const archiveMailboxId = await this.mailboxResolverService.getArchiveMailboxId(userId);
|
const archiveMailboxId = await this.mailboxResolverService.getArchiveMailboxId(wildduckUserId);
|
||||||
|
|
||||||
const result = await firstValueFrom(
|
const result = await firstValueFrom(
|
||||||
this.mailServerService.messages.updateMessage(userId, archiveMailboxId, messageId, {
|
this.mailServerService.messages.updateMessage(wildduckUserId, archiveMailboxId, messageId, {
|
||||||
moveTo: inboxMailboxId,
|
moveTo: inboxMailboxId,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -652,22 +659,22 @@ export class EmailService {
|
|||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Failed to move message ${messageId} from archive to inbox for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
`Failed to move message ${messageId} from archive to inbox for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
);
|
);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
async moveMessageToInboxFromFavorite(userId: string, messageId: number) {
|
async moveMessageToInboxFromFavorite(wildduckUserId: string, messageId: number) {
|
||||||
this.logger.log(`Moving message ${messageId} from favorite to inbox for user: ${userId}`);
|
this.logger.log(`Moving message ${messageId} from favorite to inbox for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const inboxMailboxId = await this.mailboxResolverService.getInboxMailboxId(userId);
|
const inboxMailboxId = await this.mailboxResolverService.getInboxMailboxId(wildduckUserId);
|
||||||
const favoriteMailboxId = await this.mailboxResolverService.getFavoriteMailboxId(userId);
|
const favoriteMailboxId = await this.mailboxResolverService.getFavoriteMailboxId(wildduckUserId);
|
||||||
|
|
||||||
const result = await firstValueFrom(
|
const result = await firstValueFrom(
|
||||||
this.mailServerService.messages.updateMessage(userId, favoriteMailboxId, messageId, {
|
this.mailServerService.messages.updateMessage(wildduckUserId, favoriteMailboxId, messageId, {
|
||||||
moveTo: inboxMailboxId,
|
moveTo: inboxMailboxId,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -681,22 +688,22 @@ export class EmailService {
|
|||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Failed to move message ${messageId} from favorite to inbox for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
`Failed to move message ${messageId} from favorite to inbox for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
);
|
);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
async moveMessageToInboxFromTrash(userId: string, messageId: number) {
|
async moveMessageToInboxFromTrash(wildduckUserId: string, messageId: number) {
|
||||||
this.logger.log(`Moving message ${messageId} from trash to inbox for user: ${userId}`);
|
this.logger.log(`Moving message ${messageId} from trash to inbox for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const inboxMailboxId = await this.mailboxResolverService.getInboxMailboxId(userId);
|
const inboxMailboxId = await this.mailboxResolverService.getInboxMailboxId(wildduckUserId);
|
||||||
const trashMailboxId = await this.mailboxResolverService.getTrashMailboxId(userId);
|
const trashMailboxId = await this.mailboxResolverService.getTrashMailboxId(wildduckUserId);
|
||||||
|
|
||||||
const result = await firstValueFrom(
|
const result = await firstValueFrom(
|
||||||
this.mailServerService.messages.updateMessage(userId, trashMailboxId, messageId, {
|
this.mailServerService.messages.updateMessage(wildduckUserId, trashMailboxId, messageId, {
|
||||||
moveTo: inboxMailboxId,
|
moveTo: inboxMailboxId,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -710,33 +717,44 @@ export class EmailService {
|
|||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Failed to move message ${messageId} from trash to inbox for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
`Failed to move message ${messageId} from trash to inbox for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
);
|
);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================
|
//==============================================
|
||||||
async moveMessageToJunk(userId: string, messageId: number) {
|
async moveMessageToJunk(wildduckUserId: string, messageId: number) {
|
||||||
this.logger.log(`Moving message ${messageId} to junk for user: ${userId}`);
|
this.logger.log(`Moving message ${messageId} to junk for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const messageLocation = await this.findMessageMailbox(userId, messageId);
|
const messageLocation = await this.findMessageMailbox(wildduckUserId, messageId);
|
||||||
|
|
||||||
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
if (!messageLocation) throw new BadRequestException(EmailMessage.MESSAGE_NOT_FOUND);
|
||||||
|
|
||||||
const junkMailboxId = await this.mailboxResolverService.getJunkMailboxId(userId);
|
const junkMailboxId = await this.mailboxResolverService.getJunkMailboxId(wildduckUserId);
|
||||||
|
|
||||||
this.logger.log(`Moving message ${messageId} from ${messageLocation.mailboxName} to ${MailboxEnum.Junk} for user: ${userId}`);
|
this.logger.log(`Moving message ${messageId} from ${messageLocation.mailboxName} to ${MailboxEnum.Junk} for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
const result = await firstValueFrom(
|
const result = await firstValueFrom(
|
||||||
this.mailServerService.messages.updateMessage(userId, messageLocation.mailboxId, messageId, {
|
this.mailServerService.messages.updateMessage(wildduckUserId, messageLocation.mailboxId, messageId, {
|
||||||
moveTo: junkMailboxId,
|
moveTo: junkMailboxId,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.logger.log(`Message ${messageId} moved to junk successfully from ${messageLocation.mailboxName}`);
|
this.logger.log(`Message ${messageId} moved to junk successfully from ${messageLocation.mailboxName}`);
|
||||||
|
|
||||||
|
const domainTag = await this.getUserBusinessId(wildduckUserId);
|
||||||
|
|
||||||
|
const spamResult = await this.emailSpamService.markAsSpam({
|
||||||
|
messageId,
|
||||||
|
wildduckUserId,
|
||||||
|
manageDomainList: true,
|
||||||
|
domainTag,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.logger.log(`Automatic domain management result for message ${messageId}: domainBlocked=${spamResult.domainBlocked}`);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: EmailMessage.MESSAGE_MOVED_TO_JUNK_SUCCESSFULLY,
|
message: EmailMessage.MESSAGE_MOVED_TO_JUNK_SUCCESSFULLY,
|
||||||
@@ -744,7 +762,47 @@ export class EmailService {
|
|||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Failed to move message ${messageId} to junk for user ${userId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
`Failed to move message ${messageId} to junk for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
|
);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================
|
||||||
|
async moveMessageToInboxFromJunk(wildduckUserId: string, messageId: number) {
|
||||||
|
this.logger.log(`Moving message ${messageId} from junk to inbox for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const inboxMailboxId = await this.mailboxResolverService.getInboxMailboxId(wildduckUserId);
|
||||||
|
const junkMailboxId = await this.mailboxResolverService.getJunkMailboxId(wildduckUserId);
|
||||||
|
|
||||||
|
const result = await firstValueFrom(
|
||||||
|
this.mailServerService.messages.updateMessage(wildduckUserId, junkMailboxId, messageId, {
|
||||||
|
moveTo: inboxMailboxId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.logger.log(`Message ${messageId} moved from junk to inbox successfully`);
|
||||||
|
|
||||||
|
const domainTag = await this.getUserBusinessId(wildduckUserId);
|
||||||
|
|
||||||
|
const notSpamResult = await this.emailSpamService.markAsNotSpam({
|
||||||
|
messageId,
|
||||||
|
wildduckUserId,
|
||||||
|
manageDomainList: true,
|
||||||
|
domainTag,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.logger.log(`Automatic domain management result for message ${messageId}: domainAllowed=${notSpamResult.domainAllowed}`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: EmailMessage.MESSAGE_MOVED_TO_INBOX_FROM_JUNK_SUCCESSFULLY,
|
||||||
|
result,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(
|
||||||
|
`Failed to move message ${messageId} from junk to inbox for user ${wildduckUserId}: ${error instanceof Error ? error.message : "Unknown error"}`,
|
||||||
);
|
);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
@@ -753,8 +811,8 @@ export class EmailService {
|
|||||||
//==============================================
|
//==============================================
|
||||||
// BULK ACTIONS
|
// BULK ACTIONS
|
||||||
//==============================================
|
//==============================================
|
||||||
async performBulkAction(userId: string, bulkActionDto: BulkActionDto) {
|
async performBulkAction(wildduckUserId: string, bulkActionDto: BulkActionDto) {
|
||||||
this.logger.log(`Performing bulk action ${bulkActionDto.action} on ${bulkActionDto.messageIds.length} messages for user: ${userId}`);
|
this.logger.log(`Performing bulk action ${bulkActionDto.action} on ${bulkActionDto.messageIds.length} messages for user: ${wildduckUserId}`);
|
||||||
|
|
||||||
const results = {
|
const results = {
|
||||||
successful: [] as number[],
|
successful: [] as number[],
|
||||||
@@ -766,31 +824,34 @@ export class EmailService {
|
|||||||
try {
|
try {
|
||||||
switch (bulkActionDto.action) {
|
switch (bulkActionDto.action) {
|
||||||
case BulkActionType.SEEN:
|
case BulkActionType.SEEN:
|
||||||
await this.markMessageAsSeen(userId, messageId);
|
await this.markMessageAsSeen(wildduckUserId, messageId);
|
||||||
break;
|
break;
|
||||||
case BulkActionType.DELETE:
|
case BulkActionType.DELETE:
|
||||||
await this.deleteMessage(userId, messageId);
|
await this.deleteMessage(wildduckUserId, messageId);
|
||||||
break;
|
break;
|
||||||
case BulkActionType.ARCHIVE:
|
case BulkActionType.ARCHIVE:
|
||||||
await this.moveMessageToArchive(userId, messageId);
|
await this.moveMessageToArchive(wildduckUserId, messageId);
|
||||||
break;
|
break;
|
||||||
case BulkActionType.UNARCHIVE:
|
case BulkActionType.UNARCHIVE:
|
||||||
await this.moveMessageToInboxFromArchive(userId, messageId);
|
await this.moveMessageToInboxFromArchive(wildduckUserId, messageId);
|
||||||
break;
|
break;
|
||||||
case BulkActionType.FAVORITE:
|
case BulkActionType.FAVORITE:
|
||||||
await this.moveMessageToFavorite(userId, messageId);
|
await this.moveMessageToFavorite(wildduckUserId, messageId);
|
||||||
break;
|
break;
|
||||||
case BulkActionType.UNFAVORITE:
|
case BulkActionType.UNFAVORITE:
|
||||||
await this.moveMessageToInboxFromFavorite(userId, messageId);
|
await this.moveMessageToInboxFromFavorite(wildduckUserId, messageId);
|
||||||
break;
|
break;
|
||||||
case BulkActionType.JUNK:
|
case BulkActionType.JUNK:
|
||||||
await this.moveMessageToJunk(userId, messageId);
|
await this.moveMessageToJunk(wildduckUserId, messageId);
|
||||||
|
break;
|
||||||
|
case BulkActionType.NOTJUNK:
|
||||||
|
await this.moveMessageToInboxFromJunk(wildduckUserId, messageId);
|
||||||
break;
|
break;
|
||||||
case BulkActionType.TRASH:
|
case BulkActionType.TRASH:
|
||||||
await this.moveMessageToTrash(userId, messageId);
|
await this.moveMessageToTrash(wildduckUserId, messageId);
|
||||||
break;
|
break;
|
||||||
case BulkActionType.RESTORE:
|
case BulkActionType.RESTORE:
|
||||||
await this.moveMessageToInboxFromTrash(userId, messageId);
|
await this.moveMessageToInboxFromTrash(wildduckUserId, messageId);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new BadRequestException(`Unknown action: ${bulkActionDto.action}`);
|
throw new BadRequestException(`Unknown action: ${bulkActionDto.action}`);
|
||||||
@@ -832,9 +893,6 @@ export class EmailService {
|
|||||||
|
|
||||||
//########################################################
|
//########################################################
|
||||||
|
|
||||||
/**
|
|
||||||
* Transform pagination query for WildDuck API compatibility
|
|
||||||
*/
|
|
||||||
private transformPaginationQuery(query: MessageListQueryDto): Record<string, unknown> {
|
private transformPaginationQuery(query: MessageListQueryDto): Record<string, unknown> {
|
||||||
const transformedQuery: Record<string, any> = { ...query };
|
const transformedQuery: Record<string, any> = { ...query };
|
||||||
|
|
||||||
@@ -898,6 +956,14 @@ export class EmailService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==============================================
|
||||||
|
private async getUserBusinessId(wildduckUserId: string) {
|
||||||
|
const user = await this.userRepository.findOne({ wildduckUserId, deletedAt: null }, { populate: ["business"] });
|
||||||
|
return user?.business?.id || "default";
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================
|
||||||
|
|
||||||
//########################################################
|
//########################################################
|
||||||
private generateHeadersForEmailType(user: User) {
|
private generateHeadersForEmailType(user: User) {
|
||||||
// const emailType = sendEmailDto.emailType || EmailType.GENERAL;
|
// const emailType = sendEmailDto.emailType || EmailType.GENERAL;
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
|
||||||
|
import { IsNotEmpty, IsOptional, IsString } from "class-validator";
|
||||||
|
|
||||||
|
export class CreateDomainAccessDto {
|
||||||
|
@ApiProperty({
|
||||||
|
description: "Domain name to add to the list",
|
||||||
|
example: "example.com",
|
||||||
|
})
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsString()
|
||||||
|
domain: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: "Optional description for this domain entry",
|
||||||
|
example: "Trusted business partner domain",
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ListDomainAccessQueryDto {
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: "Number of entries to return",
|
||||||
|
example: 20,
|
||||||
|
default: 20,
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
limit?: number;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description: "Page number for pagination",
|
||||||
|
example: 1,
|
||||||
|
default: 1,
|
||||||
|
})
|
||||||
|
@IsOptional()
|
||||||
|
page?: number;
|
||||||
|
}
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
// User DTOs
|
|
||||||
export * from "./create-user.dto";
|
|
||||||
export * from "./update-user.dto";
|
|
||||||
|
|
||||||
// Message DTOs
|
|
||||||
export * from "./message.dto";
|
|
||||||
|
|
||||||
// Mailbox DTOs
|
|
||||||
export * from "./mailbox.dto";
|
|
||||||
|
|
||||||
// Address DTOs
|
|
||||||
export * from "./address.dto";
|
|
||||||
|
|
||||||
// Authentication DTOs
|
|
||||||
export * from "./authenticate.dto";
|
|
||||||
|
|
||||||
// Filter DTOs
|
|
||||||
export * from "./filter.dto";
|
|
||||||
|
|
||||||
// Submission DTOs
|
|
||||||
export * from "./submission.dto";
|
|
||||||
|
|
||||||
// DKIM DTOs
|
|
||||||
export * from "./dkim.dto";
|
|
||||||
|
|
||||||
// Webhook DTOs
|
|
||||||
export * from "./webhook.dto";
|
|
||||||
|
|
||||||
// Two-Factor Authentication DTOs
|
|
||||||
export * from "./two-factor.dto";
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export interface AttachmentResponse {
|
||||||
|
success: File;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { WildDuckPaginatedResponse, WildDuckSuccessResponse } from "./wildduck-response.interface";
|
||||||
|
|
||||||
|
export interface DomainAccessEntry {
|
||||||
|
id: string;
|
||||||
|
domain: string;
|
||||||
|
description?: string;
|
||||||
|
created: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DomainAccessCreateResponse extends WildDuckSuccessResponse {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DomainAccessListResponse extends WildDuckPaginatedResponse {
|
||||||
|
results: DomainAccessEntry[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DomainAccessDetailsResponse extends WildDuckSuccessResponse, DomainAccessEntry {}
|
||||||
|
|
||||||
|
export interface DomainAccessListQueryDto {
|
||||||
|
limit?: number;
|
||||||
|
page?: number;
|
||||||
|
}
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
interface IMessage {
|
||||||
|
id: string;
|
||||||
|
mailbox: string;
|
||||||
|
size: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface MessageAttachment {
|
export interface MessageAttachment {
|
||||||
id: string;
|
id: string;
|
||||||
filename: string;
|
filename: string;
|
||||||
@@ -70,9 +76,7 @@ export interface MessageListResponse {
|
|||||||
|
|
||||||
export interface MessageUploadResponse {
|
export interface MessageUploadResponse {
|
||||||
success: true;
|
success: true;
|
||||||
id: number;
|
message: IMessage;
|
||||||
mailbox: string;
|
|
||||||
size: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageEventsEntry {
|
export interface MessageEventsEntry {
|
||||||
@@ -104,7 +108,7 @@ export interface MessageForwardResponse {
|
|||||||
|
|
||||||
export interface MessageSubmitResponse {
|
export interface MessageSubmitResponse {
|
||||||
success: true;
|
success: true;
|
||||||
id: string;
|
message: IMessage;
|
||||||
queueId: string;
|
queueId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { WildDuckAuthService } from "./services/wildduck-auth.service";
|
|||||||
import { WildDuckAutorepliesService } from "./services/wildduck-autoreplies.service";
|
import { WildDuckAutorepliesService } from "./services/wildduck-autoreplies.service";
|
||||||
import { WildDuckBaseService } from "./services/wildduck-base.service";
|
import { WildDuckBaseService } from "./services/wildduck-base.service";
|
||||||
import { WildDuckDKIMService } from "./services/wildduck-dkim.service";
|
import { WildDuckDKIMService } from "./services/wildduck-dkim.service";
|
||||||
|
import { WildDuckDomainAccessService } from "./services/wildduck-domain-access.service";
|
||||||
import { WildDuckExportService } from "./services/wildduck-export.service";
|
import { WildDuckExportService } from "./services/wildduck-export.service";
|
||||||
import { WildDuckFiltersService } from "./services/wildduck-filters.service";
|
import { WildDuckFiltersService } from "./services/wildduck-filters.service";
|
||||||
import { WildDuckHealthService } from "./services/wildduck-health.service";
|
import { WildDuckHealthService } from "./services/wildduck-health.service";
|
||||||
@@ -48,6 +49,7 @@ import { wildduckConfig } from "../../configs/wildduck.config";
|
|||||||
WildDuckAutorepliesService,
|
WildDuckAutorepliesService,
|
||||||
WildDuckExportService,
|
WildDuckExportService,
|
||||||
WildDuckTwoFactorService,
|
WildDuckTwoFactorService,
|
||||||
|
WildDuckDomainAccessService,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
MailServerService,
|
MailServerService,
|
||||||
@@ -69,6 +71,7 @@ import { wildduckConfig } from "../../configs/wildduck.config";
|
|||||||
WildDuckAutorepliesService,
|
WildDuckAutorepliesService,
|
||||||
WildDuckExportService,
|
WildDuckExportService,
|
||||||
WildDuckTwoFactorService,
|
WildDuckTwoFactorService,
|
||||||
|
WildDuckDomainAccessService,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class MailServerModule {}
|
export class MailServerModule {}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { WildDuckAuditService } from "./wildduck-audit.service";
|
|||||||
import { WildDuckAuthService } from "./wildduck-auth.service";
|
import { WildDuckAuthService } from "./wildduck-auth.service";
|
||||||
import { WildDuckAutorepliesService } from "./wildduck-autoreplies.service";
|
import { WildDuckAutorepliesService } from "./wildduck-autoreplies.service";
|
||||||
import { WildDuckDKIMService } from "./wildduck-dkim.service";
|
import { WildDuckDKIMService } from "./wildduck-dkim.service";
|
||||||
|
import { WildDuckDomainAccessService } from "./wildduck-domain-access.service";
|
||||||
import { WildDuckExportService } from "./wildduck-export.service";
|
import { WildDuckExportService } from "./wildduck-export.service";
|
||||||
import { WildDuckFiltersService } from "./wildduck-filters.service";
|
import { WildDuckFiltersService } from "./wildduck-filters.service";
|
||||||
import { WildDuckHealthService } from "./wildduck-health.service";
|
import { WildDuckHealthService } from "./wildduck-health.service";
|
||||||
@@ -42,6 +43,7 @@ export class MailServerService {
|
|||||||
private readonly autorepliesService: WildDuckAutorepliesService,
|
private readonly autorepliesService: WildDuckAutorepliesService,
|
||||||
private readonly exportService: WildDuckExportService,
|
private readonly exportService: WildDuckExportService,
|
||||||
private readonly twoFactorService: WildDuckTwoFactorService,
|
private readonly twoFactorService: WildDuckTwoFactorService,
|
||||||
|
private readonly domainAccessService: WildDuckDomainAccessService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
getMailServerInfo() {
|
getMailServerInfo() {
|
||||||
@@ -133,4 +135,8 @@ export class MailServerService {
|
|||||||
get twoFactor() {
|
get twoFactor() {
|
||||||
return this.twoFactorService;
|
return this.twoFactorService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get domainAccess() {
|
||||||
|
return this.domainAccessService;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import { Injectable } from "@nestjs/common";
|
||||||
|
import { Observable } from "rxjs";
|
||||||
|
|
||||||
|
import { WildDuckBaseService } from "./wildduck-base.service";
|
||||||
|
import { CreateDomainAccessDto, ListDomainAccessQueryDto } from "../DTO/domain-access.dto";
|
||||||
|
import { DomainAccessCreateResponse, DomainAccessListResponse } from "../interfaces/domain-access-response.interface";
|
||||||
|
import { WildDuckSuccessResponse } from "../interfaces/wildduck-response.interface";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class WildDuckDomainAccessService extends WildDuckBaseService {
|
||||||
|
/**
|
||||||
|
* List allowlisted domains for a tag
|
||||||
|
*/
|
||||||
|
listAllowedDomains(tag: string, query?: ListDomainAccessQueryDto): Observable<DomainAccessListResponse> {
|
||||||
|
return this.get<DomainAccessListResponse>(`/domainaccess/${tag}/allow`, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add domain to allowlist
|
||||||
|
*/
|
||||||
|
addAllowedDomain(tag: string, data: CreateDomainAccessDto): Observable<DomainAccessCreateResponse> {
|
||||||
|
return this.post<DomainAccessCreateResponse>(`/domainaccess/${tag}/allow`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove domain from allowlist
|
||||||
|
*/
|
||||||
|
removeAllowedDomain(tag: string, domain: string): Observable<WildDuckSuccessResponse> {
|
||||||
|
return this.delete<WildDuckSuccessResponse>(`/domainaccess/${tag}/allow/${domain}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List blocked domains for a tag
|
||||||
|
*/
|
||||||
|
listBlockedDomains(tag: string, query?: ListDomainAccessQueryDto): Observable<DomainAccessListResponse> {
|
||||||
|
return this.get<DomainAccessListResponse>(`/domainaccess/${tag}/block`, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add domain to blocklist
|
||||||
|
*/
|
||||||
|
addBlockedDomain(tag: string, data: CreateDomainAccessDto): Observable<DomainAccessCreateResponse> {
|
||||||
|
return this.post<DomainAccessCreateResponse>(`/domainaccess/${tag}/block`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove domain from blocklist
|
||||||
|
*/
|
||||||
|
removeBlockedDomain(tag: string, domain: string): Observable<WildDuckSuccessResponse> {
|
||||||
|
return this.delete<WildDuckSuccessResponse>(`/domainaccess/${tag}/block/${domain}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import { Observable } from "rxjs";
|
|||||||
|
|
||||||
import { WildDuckBaseService } from "./wildduck-base.service";
|
import { WildDuckBaseService } from "./wildduck-base.service";
|
||||||
import { ListMessagesQueryDto, SearchMessagesQueryDto, UpdateMessageDto, UploadMessageDto } from "../DTO/message.dto";
|
import { ListMessagesQueryDto, SearchMessagesQueryDto, UpdateMessageDto, UploadMessageDto } from "../DTO/message.dto";
|
||||||
|
import { AttachmentResponse } from "../interfaces/attachment.interface";
|
||||||
import {
|
import {
|
||||||
MessageDeleteAllResponse,
|
MessageDeleteAllResponse,
|
||||||
MessageDetails,
|
MessageDetails,
|
||||||
@@ -72,9 +73,9 @@ export class WildDuckMessagesService extends WildDuckBaseService {
|
|||||||
/**
|
/**
|
||||||
* Get message attachment
|
* Get message attachment
|
||||||
*/
|
*/
|
||||||
getMessageAttachment(userId: string, mailboxId: string, messageId: number, attachmentId: string): Observable<any> {
|
getMessageAttachment(userId: string, mailboxId: string, messageId: number, attachmentId: string): Observable<AttachmentResponse> {
|
||||||
// This returns binary content
|
// This returns binary content
|
||||||
return this.get<any>(`/users/${userId}/mailboxes/${mailboxId}/messages/${messageId}/attachments/${attachmentId}`);
|
return this.get<AttachmentResponse>(`/users/${userId}/mailboxes/${mailboxId}/messages/${messageId}/attachments/${attachmentId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Query } from "@nestj
|
|||||||
import { ApiOperation, ApiParam, ApiQuery, ApiResponse } from "@nestjs/swagger";
|
import { ApiOperation, ApiParam, ApiQuery, ApiResponse } from "@nestjs/swagger";
|
||||||
|
|
||||||
import { MailboxQueryDto } from "./DTO/mailbox.dto";
|
import { MailboxQueryDto } from "./DTO/mailbox.dto";
|
||||||
|
import { CreateMailboxDto, UpdateMailboxDto } from "./DTO/mailbox.dto";
|
||||||
import { MailboxService } from "./services/mailbox.service";
|
import { MailboxService } from "./services/mailbox.service";
|
||||||
import { AdminRoute } from "../../common/decorators/admin.decorator";
|
import { AdminRoute } from "../../common/decorators/admin.decorator";
|
||||||
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";
|
||||||
import { CreateMailboxDto, UpdateMailboxDto } from "../mail-server/DTO";
|
|
||||||
|
|
||||||
@AuthGuards()
|
@AuthGuards()
|
||||||
@Controller("mailbox")
|
@Controller("mailbox")
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Injectable, Logger, NotFoundException } from "@nestjs/common";
|
import { Injectable, Logger, NotFoundException } from "@nestjs/common";
|
||||||
import { Observable, catchError, map, throwError } from "rxjs";
|
import { Observable, catchError, map, throwError } from "rxjs";
|
||||||
|
|
||||||
import { CreateMailboxDto, UpdateMailboxDto } from "../../mail-server/DTO";
|
|
||||||
import { MailServerService } from "../../mail-server/services/mail-server.service";
|
import { MailServerService } from "../../mail-server/services/mail-server.service";
|
||||||
import { MailboxQueryDto } from "../DTO/mailbox.dto";
|
import { MailboxQueryDto } from "../DTO/mailbox.dto";
|
||||||
|
import { CreateMailboxDto, UpdateMailboxDto } from "../DTO/mailbox.dto";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MailboxService {
|
export class MailboxService {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { Business } from "../../businesses/entities/business.entity";
|
|||||||
import { DomainStatus } from "../../domains/enums/domain-status.enum";
|
import { DomainStatus } from "../../domains/enums/domain-status.enum";
|
||||||
import { DomainAutomationService } from "../../domains/services/domain-automation.service";
|
import { DomainAutomationService } from "../../domains/services/domain-automation.service";
|
||||||
import { DomainsService } from "../../domains/services/domains.service";
|
import { DomainsService } from "../../domains/services/domains.service";
|
||||||
import { UpdateUserDto } from "../../mail-server/DTO";
|
import { UpdateUserDto } from "../../mail-server/DTO/update-user.dto";
|
||||||
import { MailServerService } from "../../mail-server/services/mail-server.service";
|
import { MailServerService } from "../../mail-server/services/mail-server.service";
|
||||||
import { QuotaSyncService } from "../../quota-sync/services/quota-sync.service";
|
import { QuotaSyncService } from "../../quota-sync/services/quota-sync.service";
|
||||||
import { UserSettingsService } from "../../settings/services/user-settings.service";
|
import { UserSettingsService } from "../../settings/services/user-settings.service";
|
||||||
|
|||||||
Reference in New Issue
Block a user