132 lines
3.5 KiB
JavaScript
132 lines
3.5 KiB
JavaScript
const nodemailer = require('nodemailer');
|
|
const logger = require('../utils/logger');
|
|
const emailTemplates = require('./emailTemplates');
|
|
const config = require('../config');
|
|
|
|
// Create reusable transporter
|
|
let transporter;
|
|
|
|
const initializeEmailService = () => {
|
|
const emailConfig = {
|
|
host: process.env.SMTP_HOST,
|
|
port: parseInt(process.env.SMTP_PORT),
|
|
secure: process.env.SMTP_SECURE === 'true', // true for 465, false for other ports
|
|
auth: {
|
|
user: process.env.SMTP_USER,
|
|
pass: process.env.SMTP_PASS
|
|
}
|
|
};
|
|
|
|
// Additional settings for specific providers
|
|
if (process.env.SMTP_SERVICE) {
|
|
emailConfig.service = process.env.SMTP_SERVICE; // 'gmail' for example
|
|
}
|
|
|
|
// Handle TLS for port 587
|
|
if (emailConfig.port === 587) {
|
|
emailConfig.secure = false;
|
|
emailConfig.requireTLS = true;
|
|
}
|
|
|
|
transporter = nodemailer.createTransport(emailConfig);
|
|
|
|
// Verify connection
|
|
transporter.verify((error, success) => {
|
|
if (error) {
|
|
logger.error('SMTP connection failed:', error);
|
|
} else {
|
|
logger.info('SMTP server ready to send emails');
|
|
}
|
|
});
|
|
};
|
|
|
|
const sendEmail = async ({ to, subject, text, html }) => {
|
|
if (!transporter) {
|
|
throw new Error('Email service not initialized');
|
|
}
|
|
|
|
const mailOptions = {
|
|
from: `${process.env.EMAIL_FROM_NAME} <${process.env.EMAIL_FROM_ADDRESS}>`,
|
|
to,
|
|
subject,
|
|
text,
|
|
html
|
|
};
|
|
|
|
try {
|
|
const info = await transporter.sendMail(mailOptions);
|
|
logger.info(`Email sent: ${info.messageId}`);
|
|
return info;
|
|
} catch (error) {
|
|
logger.error('Failed to send email:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
const sendPasswordRecovery = async (user) => {
|
|
try {
|
|
const baseUrl = config.isProduction ?
|
|
`https://map.${config.domain}` :
|
|
`http://localhost:${config.port}`;
|
|
|
|
const variables = {
|
|
APP_NAME: process.env.APP_NAME || 'CMlite Map',
|
|
USER_NAME: user.Name || user.name || user.Email || user.email,
|
|
USER_EMAIL: user.Email || user.email,
|
|
PASSWORD: user.Password || user.password,
|
|
LOGIN_URL: `${baseUrl}/login.html`,
|
|
TIMESTAMP: new Date().toLocaleString()
|
|
};
|
|
|
|
const { html, text } = await emailTemplates.render('password-recovery', variables);
|
|
|
|
return await sendEmail({
|
|
to: user.Email || user.email,
|
|
subject: `Password Recovery - ${variables.APP_NAME}`,
|
|
text,
|
|
html
|
|
});
|
|
} catch (error) {
|
|
logger.error('Failed to send password recovery email:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
const sendLoginDetails = async (user) => {
|
|
try {
|
|
const baseUrl = config.isProduction ?
|
|
`https://map.${config.domain}` :
|
|
`http://localhost:${config.port}`;
|
|
|
|
const isAdmin = user.admin || user.Admin || false;
|
|
|
|
const variables = {
|
|
APP_NAME: process.env.APP_NAME || 'CMlite Map',
|
|
USER_NAME: user.Name || user.name || user.Email || user.email,
|
|
USER_EMAIL: user.Email || user.email,
|
|
PASSWORD: user.Password || user.password,
|
|
USER_ROLE: isAdmin ? 'Administrator' : 'User',
|
|
LOGIN_URL: `${baseUrl}/login.html`,
|
|
TIMESTAMP: new Date().toLocaleString()
|
|
};
|
|
|
|
const { html, text } = await emailTemplates.render('login-details', variables);
|
|
|
|
return await sendEmail({
|
|
to: user.Email || user.email,
|
|
subject: `Your Login Details - ${variables.APP_NAME}`,
|
|
text,
|
|
html
|
|
});
|
|
} catch (error) {
|
|
logger.error('Failed to send login details email:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
initializeEmailService,
|
|
sendEmail,
|
|
sendPasswordRecovery,
|
|
sendLoginDetails
|
|
}; |