import { Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { EmailConfig } from './email.config'; @Injectable() export class EmailService { private readonly logger = new Logger(EmailService.name); private readonly config: EmailConfig; constructor(configService: ConfigService) { this.config = new EmailConfig(configService); } async sendOtpEmail( email: string, otp: string, firstName?: string, ): Promise { try { this.logger.log(`📧 Attempting to send OTP email to: ${email}`); const greeting = firstName ? `Hi ${firstName}` : 'Hello'; const payload = { sender: { email: this.config.otpEmail, name: 'StreamFlix', }, to: [{ email, name: firstName || email }], templateId: this.config.otpTemplateId, params: { GREETING: greeting, OTP: otp, }, }; this.logger.log('📧 OTP Email payload:', { sender: payload.sender, to: payload.to, templateId: payload.templateId, params: payload.params, }); const response = await fetch('https://api.brevo.com/v3/smtp/email', { method: 'POST', headers: { 'api-key': this.config.apiKey, 'Content-Type': 'application/json', }, body: JSON.stringify(payload), }); const responseText = await response.text(); this.logger.log(`📧 Raw Response: ${responseText}`); if (!response.ok) { let error; try { error = JSON.parse(responseText); } catch { error = responseText; } this.logger.error('📧 Failed to send OTP email:', error); throw new Error('Failed to send OTP email'); } this.logger.log(`📧 ✅ OTP email sent successfully to ${email}`); } catch (error) { this.logger.error('📧 ❌ Error sending OTP email:', error); throw error; } } async sendWelcomeEmail( email: string, firstName: string, lastName: string, ): Promise { try { this.logger.log(`📧 Attempting to send welcome email to: ${email}`); const fullName = `${firstName} ${lastName}`.trim(); const payload = { sender: { email: this.config.welcomeEmail, name: 'StreamFlix', }, to: [{ email, name: fullName || email }], templateId: this.config.welcomeTemplateId, params: { FIRSTNAME: fullName || firstName || 'User', }, }; this.logger.log('📧 Welcome Email payload:', { sender: payload.sender, to: payload.to, templateId: payload.templateId, params: payload.params, }); const response = await fetch('https://api.brevo.com/v3/smtp/email', { method: 'POST', headers: { 'api-key': this.config.apiKey, 'Content-Type': 'application/json', }, body: JSON.stringify(payload), }); const responseText = await response.text(); this.logger.log(`📧 Raw Response: ${responseText}`); if (!response.ok) { let error; try { error = JSON.parse(responseText); } catch { error = responseText; } this.logger.error('📧 Failed to send welcome email:', error); throw new Error('Failed to send welcome email'); } this.logger.log(`📧 ✅ Welcome email sent successfully to ${email}`); } catch (error) { this.logger.error('📧 ❌ Error sending welcome email:', error); throw error; } } async send2FACode( email: string, name: string, code: string, ipAddress?: string, userAgent?: string, location?: string, ): Promise { try { this.logger.log(`📧 Attempting to send 2FA code to: ${email}`); const payload = { sender: { email: this.config.otpEmail, name: 'StreamFlix Security', }, to: [{ email, name: name || email }], templateId: parseInt(process.env.BREVO_2FA_CODE_TEMPLATE_ID || '4', 10), params: { adminName: name, verificationCode: code, expiryMinutes: process.env.TWO_FA_CODE_EXPIRY_MINUTES || '10', location: location || 'Unknown Location', ipAddress: ipAddress || 'Unknown', deviceInfo: userAgent || 'Unknown device', timestamp: new Date().toLocaleString('en-US', { dateStyle: 'long', timeStyle: 'short', }), supportUrl: process.env.SUPPORT_URL || '#', securityUrl: process.env.SECURITY_URL || '#', privacyUrl: process.env.PRIVACY_URL || '#', currentYear: new Date().getFullYear().toString(), companyAddress: process.env.COMPANY_ADDRESS || '', }, }; this.logger.log('📧 2FA Code Email payload:', { sender: payload.sender, to: payload.to, templateId: payload.templateId, params: { ...payload.params, verificationCode: '******' }, // Hide code in logs }); const response = await fetch('https://api.brevo.com/v3/smtp/email', { method: 'POST', headers: { 'api-key': this.config.apiKey, 'Content-Type': 'application/json', }, body: JSON.stringify(payload), }); const responseText = await response.text(); this.logger.log(`📧 Raw Response: ${responseText}`); if (!response.ok) { let error; try { error = JSON.parse(responseText); } catch { error = responseText; } this.logger.error('📧 Failed to send 2FA code email:', error); throw new Error('Failed to send 2FA code email'); } this.logger.log(`📧 ✅ 2FA code sent successfully to ${email}`); } catch (error) { this.logger.error('📧 ❌ Error sending 2FA code:', error); throw error; } } }