Email verification Backend
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import * as nodemailer from 'nodemailer';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import sharp from 'sharp';
|
||||
import { logError, logAuth, logStartup } from './Logger';
|
||||
import { EmailTemplateHelper, LocalizedSubjects } from './EmailTemplateHelper';
|
||||
|
||||
@@ -28,9 +29,14 @@ export class EmailService {
|
||||
private transporter!: nodemailer.Transporter;
|
||||
private config: EmailConfig;
|
||||
private templatesPath: string;
|
||||
private logoPath: string;
|
||||
private resizedLogoBuffer?: Buffer;
|
||||
|
||||
constructor() {
|
||||
this.templatesPath = path.join(__dirname, '../../Templates');
|
||||
this.logoPath = path.join(__dirname, '../../../assets/Logo.png');
|
||||
// Load logo asynchronously after initialization
|
||||
this.loadLogoBase64().catch(err => console.error('[EmailService] Error loading logo:', err));
|
||||
|
||||
this.config = {
|
||||
host: process.env.EMAIL_HOST || 'smtp.gmail.com',
|
||||
@@ -63,6 +69,32 @@ export class EmailService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and resize logo for email attachments - 32x32 pixels
|
||||
*/
|
||||
private async loadLogoBase64(): Promise<void> {
|
||||
try {
|
||||
if (fs.existsSync(this.logoPath)) {
|
||||
const logoBuffer = fs.readFileSync(this.logoPath);
|
||||
|
||||
// Resize to 60x60 pixels with high quality and centered
|
||||
this.resizedLogoBuffer = await sharp(logoBuffer)
|
||||
.resize(60, 60, {
|
||||
fit: 'contain',
|
||||
background: { r: 255, g: 255, b: 255, alpha: 1 },
|
||||
position: 'center'
|
||||
})
|
||||
.png()
|
||||
.toBuffer();
|
||||
|
||||
console.log(`[EmailService] ✅ Logo loaded and resized to 60x60`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[EmailService] ❌ Failed to load/resize logo:`, error);
|
||||
logError('Failed to load logo for emails', error instanceof Error ? error : new Error(String(error)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send email with template
|
||||
* @param options - Email options including template and data
|
||||
@@ -73,19 +105,29 @@ export class EmailService {
|
||||
let textContent = options.text;
|
||||
|
||||
if (options.template) {
|
||||
const templateResult = await this.loadTemplate(options.template, options.templateData || {});
|
||||
const templateResult = await this.loadTemplate(options.template, options.templateData);
|
||||
htmlContent = templateResult.html;
|
||||
textContent = templateResult.text;
|
||||
}
|
||||
|
||||
const mailOptions = {
|
||||
const mailOptions: any = {
|
||||
from: this.config.from,
|
||||
to: options.to,
|
||||
subject: options.subject,
|
||||
html: htmlContent,
|
||||
text: textContent
|
||||
text: textContent,
|
||||
attachments: []
|
||||
};
|
||||
|
||||
// Add logo as CID attachment if available
|
||||
if (this.resizedLogoBuffer) {
|
||||
mailOptions.attachments.push({
|
||||
filename: 'logo.png',
|
||||
content: this.resizedLogoBuffer,
|
||||
cid: 'logo@serpentrace' // Content-ID for referencing in HTML
|
||||
});
|
||||
}
|
||||
|
||||
const result = await this.transporter.sendMail(mailOptions);
|
||||
logAuth('Email sent successfully', undefined, {
|
||||
messageId: result.messageId,
|
||||
|
||||
Reference in New Issue
Block a user