import { Inject, Injectable, Logger, OnApplicationBootstrap, } from "@nestjs/common"; import { ClientProxy } from "@nestjs/microservices"; import { SendEmailDto } from "./dtos/email.dto"; import { isBrokerConnected, publishConfirmed } from "./broker.util"; @Injectable() export class EmailClientService implements OnApplicationBootstrap { private readonly logger = new Logger(EmailClientService.name); constructor( @Inject("EMAIL_SERVICE") private readonly emailClient: ClientProxy, ) {} private readonly enabled = process.env.RABBITMQ_ENABLED !== "false"; async onApplicationBootstrap() { if (!this.enabled) return; this.emailClient .connect() .then(() => this.logger.log("connected to Email service")) .catch((err) => { console.error("Error happened at Email service", err); }); } async sendEmail(dto: SendEmailDto): Promise<{ queued: boolean }> { if (!this.enabled) { this.logger.warn(`RABBITMQ disabled — skipped EMAIL to=${dto.to}`); return { queued: false }; } const queued = await publishConfirmed( this.emailClient, "send-email", { to: dto.to, subject: dto.subject, text: dto.text, html: dto.html, appKey: "IFHCRS-LICENSE-MANAGEMENT", }, this.logger, ); // Publisher-confirmed: RabbitMQ has taken ownership of the message. Still NOT // delivery — the consumer and the SMTP hop are downstream and invisible here. this.logger.log( `EMAIL publish to RabbitMQ [${process.env.EMAIL_QUEUE ?? "email_queue"}] pattern='send-email' confirmed=${queued}`, ); // Recipient + content are PII — debug only. this.logger.debug(`EMAIL payload to=${dto.to} subject="${dto.subject}"`); return { queued }; } /** * Connection state for the health endpoint. `null` means the broker client did * not expose its manager — reported as "unknown" rather than assumed healthy. */ get brokerConnected(): boolean | null { if (!this.enabled) return false; return isBrokerConnected(this.emailClient); } }