import nodemailer from "nodemailer"; import { config } from "../config/index.js"; /** * Email Service for TurboTrades * Handles sending verification emails, 2FA codes, etc. */ // Create transporter let transporter = null; const initializeTransporter = () => { if (transporter) return transporter; // In development, use Ethereal email (fake SMTP service for testing) if (config.isDevelopment && (!config.email.host || !config.email.user)) { console.log( "āš ļø No email credentials found. Email will be logged to console only." ); return null; } try { transporter = nodemailer.createTransport({ host: config.email.host, port: config.email.port, secure: config.email.port === 465, // true for 465, false for other ports auth: { user: config.email.user, pass: config.email.pass, }, }); console.log("āœ… Email transporter initialized"); return transporter; } catch (error) { console.error("āŒ Failed to initialize email transporter:", error); return null; } }; /** * Send email * @param {Object} options - Email options * @param {string} options.to - Recipient email * @param {string} options.subject - Email subject * @param {string} options.html - HTML content * @param {string} options.text - Plain text content */ export const sendEmail = async ({ to, subject, html, text }) => { const transport = initializeTransporter(); // If no transporter, log to console (development mode) if (!transport) { console.log("\nšŸ“§ ===== EMAIL (Console Mode) ====="); console.log(`To: ${to}`); console.log(`Subject: ${subject}`); console.log(`Text: ${text || "N/A"}`); console.log(`HTML: ${html ? "Yes" : "No"}`); console.log("===================================\n"); return { success: true, mode: "console" }; } try { const info = await transport.sendMail({ from: config.email.from, to, subject, text, html, }); console.log(`āœ… Email sent to ${to}: ${info.messageId}`); return { success: true, messageId: info.messageId }; } catch (error) { console.error(`āŒ Failed to send email to ${to}:`, error); throw error; } }; /** * Send email verification email * @param {string} email - User email * @param {string} username - User username * @param {string} token - Verification token */ export const sendVerificationEmail = async (email, username, token) => { const verificationUrl = `${config.cors.origin}/verify-email/${token}`; const html = `

šŸš€ TurboTrades

Welcome, ${username}!

Thank you for joining TurboTrades. To complete your registration and secure your account, please verify your email address.

Verify Email Address

If the button doesn't work, copy and paste this link into your browser:

${verificationUrl}

This link will expire in 24 hours. If you didn't create an account on TurboTrades, please ignore this email.

`; const text = ` Welcome to TurboTrades, ${username}! Please verify your email address by visiting this link: ${verificationUrl} This link will expire in 24 hours. If you didn't create an account on TurboTrades, please ignore this email. Ā© ${new Date().getFullYear()} TurboTrades `.trim(); return sendEmail({ to: email, subject: "Verify your TurboTrades email address", html, text, }); }; /** * Send 2FA setup email * @param {string} email - User email * @param {string} username - User username * @param {string} revocationCode - Revocation code for 2FA recovery */ export const send2FASetupEmail = async (email, username) => { const html = `

šŸ” Two-Factor Authentication Enabled

Great job, ${username}!

You've successfully enabled Two-Factor Authentication (2FA) on your TurboTrades account. Your account is now more secure.

āš ļø Security Notice

If you did not enable 2FA on your account, please contact support immediately and change your password.

What this means:
• You'll now need your authenticator app code when logging in
• Your account has an extra layer of protection
• Keep your recovery code safe (shown during setup)
• Never share your 2FA codes with anyone

āœ… Your account is now protected by 2FA

`; const text = ` Two-Factor Authentication Enabled Great job, ${username}! You've successfully enabled Two-Factor Authentication (2FA) on your TurboTrades account. āš ļø Security Notice If you did not enable 2FA on your account, please contact support immediately and change your password. What this means: • You'll now need your authenticator app code when logging in • Your account has an extra layer of protection • Keep your recovery code safe (shown during setup) • Never share your 2FA codes with anyone • You can use this code to disable 2FA if you lose your authenticator device Ā© ${new Date().getFullYear()} TurboTrades `.trim(); return sendEmail({ to: email, subject: "šŸ” Two-Factor Authentication Enabled - TurboTrades", html, text, }); }; /** * Send session alert email * @param {string} email - User email * @param {string} username - User username * @param {Object} session - Session details */ export const sendSessionAlertEmail = async (email, username, session) => { const html = `

šŸ”” New Login Detected

Hello, ${username}

We detected a new login to your TurboTrades account.

Time: ${new Date( session.createdAt ).toLocaleString()}
IP Address: ${session.ip || "Unknown"}
Device: ${session.device || "Unknown"}
Location: ${session.location || "Unknown"}

If this was you, you can safely ignore this email. If you don't recognize this login, please secure your account immediately by:

`; const text = ` New Login Detected - TurboTrades Hello, ${username} We detected a new login to your TurboTrades account. Login Details: - Time: ${new Date(session.createdAt).toLocaleString()} - IP Address: ${session.ip || "Unknown"} - Device: ${session.device || "Unknown"} - Location: ${session.location || "Unknown"} If this was you, you can safely ignore this email. If you don't recognize this login, please secure your account immediately by: • Changing your Steam password • Enabling Two-Factor Authentication (2FA) on TurboTrades • Reviewing your active sessions in account settings Ā© ${new Date().getFullYear()} TurboTrades `.trim(); return sendEmail({ to: email, subject: "šŸ”” New Login Detected - TurboTrades", html, text, }); }; export default { sendEmail, sendVerificationEmail, send2FASetupEmail, sendSessionAlertEmail, };