import express from 'express'; import multer from 'multer'; import { saveLead, getLeads } from '../db.js'; import { sendContactEmail, sendCareersEmail, sendStrategyEmail } from '../services/mailService.js'; const router = express.Router(); const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 10 * 1024 * 1024 } }); async function verifyTurnstile(token, remoteip) { const secretKey = process.env.TURNSTILE_SECRET_KEY || '1x000000000000000000000000000000AA'; if (!token) return { success: false, 'error-codes': ['missing-input-response'] }; try { const formData = new URLSearchParams(); formData.append('secret', secretKey); formData.append('response', token); if (remoteip) formData.append('remoteip', remoteip); const res = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', { method: 'POST', body: formData }); return await res.json(); } catch (err) { console.error('Turnstile verification exception:', err); return { success: true }; } } // POST /api/contact - Handle Contact, Careers, and Strategy Call form submissions via SMTP router.post('/', upload.single('resume'), async (req, res) => { try { const { name, email, phone, mobile, subject, message, interests, type, designation, dateTime, resumeName, turnstileToken } = req.body; const contactName = name?.trim(); const contactEmail = email?.trim(); const contactPhone = (phone || mobile || '').trim(); const contactSubject = (subject || interests || type || 'General Inquiry').trim(); const contactMessage = (message || req.body.comments || '').trim(); if (!contactName || !contactEmail) { return res.status(400).json({ error: 'Name and Email are required.' }); } // Verify Cloudflare Turnstile Token if (turnstileToken) { const turnstileRes = await verifyTurnstile(turnstileToken, req.ip); if (!turnstileRes.success) { return res.status(400).json({ error: 'Cloudflare Turnstile security verification failed. Please try again.' }); } } // Save lead record in database const lead = saveLead({ name: contactName, email: contactEmail, phone: contactPhone, subject: contactSubject, message: contactMessage, designation, dateTime, resumeName, type: type || 'contact' }); // Attempt sending email via SMTP service based on form type let mailResult = { success: false }; if (type === 'careers') { mailResult = await sendCareersEmail({ name: contactName, email: contactEmail, phone: contactPhone, resumeName: req.file ? req.file.originalname : (resumeName || 'Resume Uploaded'), message: contactMessage, file: req.file }); } else if (type === 'strategy') { mailResult = await sendStrategyEmail({ name: contactName, email: contactEmail, phone: contactPhone, designation: designation || 'N/A', dateTime: dateTime || 'N/A', interests: interests || 'General Strategy Consultation', message: contactMessage }); } else { mailResult = await sendContactEmail({ name: contactName, email: contactEmail, phone: contactPhone, subject: contactSubject, message: contactMessage }); } if (!mailResult.success) { // If SMTP is not yet configured or fails, return 200 with lead saved & warning return res.status(200).json({ success: true, saved: true, leadId: lead.id, smtpError: mailResult.error, message: 'Your request was saved successfully. Note: SMTP email dispatch requires SMTP credentials in .env.' }); } return res.status(200).json({ success: true, saved: true, leadId: lead.id, messageId: mailResult.messageId, message: 'Request sent successfully via SMTP!' }); } catch (error) { console.error('[Contact Route Error]', error); return res.status(500).json({ error: error.message || 'Internal Server Error' }); } }); // GET /api/contact/leads - Retrieve saved contact leads router.get('/leads', (_req, res) => { try { const leads = getLeads(); return res.json({ success: true, leads }); } catch (error) { return res.status(500).json({ error: error.message }); } }); export default router;