import { Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { getVerificationEmailTemplate, getPasswordResetTemplate, getWelcomeEmailTemplate, } from './templates'; export interface EmailOptions { to: string; subject: string; html: string; text?: string; cc?: string[]; bcc?: string[]; replyTo?: string; } @Injectable() export class EmailService { private readonly logger = new Logger(EmailService.name); private readonly endpoint: string; constructor(private readonly configService: ConfigService) { this.endpoint = this.configService.get('EMAIL_API_URL') || 'https://email.routes.hiffi.com/superlabs/v1/send'; this.logger.log(`Email service initialized → ${this.endpoint}`); } async sendEmail(options: EmailOptions): Promise { const payload: Record = { to: [options.to], subject: options.subject, html: options.html, }; if (options.text) payload.text = options.text; if (options.cc && options.cc.length > 0) payload.cc = options.cc; if (options.bcc && options.bcc.length > 0) payload.bcc = options.bcc; if (options.replyTo) payload.reply_to = options.replyTo; try { const res = await fetch(this.endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload), }); const data = await res.json().catch(() => null); if (!res.ok || !data?.ok) { const errMsg = data?.error || `HTTP ${res.status}`; this.logger.error(`Failed to send email to ${options.to}: ${errMsg}`); return false; } this.logger.log(`Email sent successfully to ${options.to}`); return true; } catch (error: any) { this.logger.error(`Email API request failed for ${options.to}: ${error.message}`); return false; } } // ========================================== // EMAIL VERIFICATION // ========================================== async sendVerificationEmail(email: string, token: string, name?: string): Promise { const frontendUrl = this.configService.get('FRONTEND_URL') || 'http://localhost:3000'; const verificationUrl = `${frontendUrl}/verify-email?token=${token}`; const html = getVerificationEmailTemplate({ verificationUrl, name }); const text = `Welcome to RE-QuestN! Please verify your email by clicking this link: ${verificationUrl}`; return this.sendEmail({ to: email, subject: 'Verify Your Email - RE-QuestN', html, text, }); } // ========================================== // PASSWORD RESET // ========================================== async sendPasswordResetEmail(email: string, resetUrl: string): Promise { const html = getPasswordResetTemplate({ resetUrl }); const text = `Reset your password by clicking this link: ${resetUrl}. This link will expire in 1 hour.`; return this.sendEmail({ to: email, subject: 'Reset Your Password - RE-QuestN', html, text, }); } // ========================================== // WELCOME EMAIL // ========================================== async sendWelcomeEmail(email: string, name?: string): Promise { const frontendUrl = this.configService.get('FRONTEND_URL') || 'http://localhost:3000'; const html = getWelcomeEmailTemplate({ name, frontendUrl }); const text = `Welcome to RE-QuestN, ${name || 'User'}! Your real estate journey starts now.`; return this.sendEmail({ to: email, subject: 'Welcome to RE-QuestN!', html, text, }); } }