Files
keystone/app/api/contact/route.js
2025-08-14 11:53:40 +05:30

268 lines
9.0 KiB
JavaScript

// app/api/contact/route.js
// ❌ REMOVE "use client" from here - API routes must NOT have this directive
import { NextResponse } from 'next/server';
import nodemailer from 'nodemailer';
// Create transporter with Zoho configuration
const createTransport = () => {
return nodemailer.createTransport({
host: 'smtp.zoho.com',
port: 587,
secure: false,
auth: {
user: process.env.ZOHO_EMAIL,
pass: process.env.ZOHO_PASSWORD,
},
debug: true,
logger: true,
});
};
// Handle Newsletter Subscription
async function handleNewsletter(data) {
console.log('Processing newsletter subscription for:', data.email);
const transporter = createTransport();
const mailOptions = {
from: process.env.ZOHO_EMAIL,
to: process.env.RECIPIENT_EMAIL,
subject: 'New Newsletter Subscription - Keystone Solutions',
html: `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #ff3a2d;">New Newsletter Subscription</h2>
<div style="background: #f5f5f5; padding: 20px; border-radius: 8px;">
<p><strong>Email:</strong> ${data.email}</p>
<p><strong>Subscribed at:</strong> ${new Date().toLocaleString()}</p>
</div>
<hr style="margin: 20px 0;">
<p style="color: #666; font-size: 14px;">
This email was sent from your website's newsletter subscription form.
</p>
</div>
`,
};
const result = await transporter.sendMail(mailOptions);
console.log('Newsletter email sent successfully:', result.messageId);
return result;
}
// Handle Contact Form
async function handleContact(data) {
console.log('Processing contact form for:', data.fullName, data.email);
const transporter = createTransport();
const mailOptions = {
from: process.env.ZOHO_EMAIL,
to: process.env.RECIPIENT_EMAIL,
subject: 'New Contact Form Submission - Keystone Solutions',
html: `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #ff3a2d;">New Contact Form Submission</h2>
<div style="background: #f5f5f5; padding: 20px; border-radius: 8px;">
<p><strong>Full Name:</strong> ${data.fullName}</p>
<p><strong>Email:</strong> ${data.email}</p>
<p><strong>Phone:</strong> ${data.phone || 'Not provided'}</p>
<p><strong>Message:</strong></p>
<div style="background: white; padding: 15px; border-left: 4px solid #ff3a2d; margin: 10px 0;">
${data.message || 'No message provided'}
</div>
<p><strong>Submitted at:</strong> ${new Date().toLocaleString()}</p>
</div>
<hr style="margin: 20px 0;">
<p style="color: #666; font-size: 14px;">
This email was sent from your website's contact form.
</p>
</div>
`,
};
const result = await transporter.sendMail(mailOptions);
console.log('Contact email sent successfully:', result.messageId);
return result;
}
// Handle Career Form
async function handleCareer(data) {
console.log('Processing career form for:', data.fullName, data.email);
const transporter = createTransport();
const attachments = [];
// Handle file attachment if present
if (data.resume) {
console.log('Resume file attached:', data.resume.name);
attachments.push({
filename: data.resume.name,
content: Buffer.from(data.resume.data, 'base64'),
contentType: data.resume.type,
});
}
const mailOptions = {
from: process.env.ZOHO_EMAIL,
to: process.env.RECIPIENT_EMAIL,
subject: 'New Career Application - Keystone Solutions',
html: `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #ff3a2d;">New Career Application</h2>
<div style="background: #f5f5f5; padding: 20px; border-radius: 8px;">
<p><strong>Full Name:</strong> ${data.fullName}</p>
<p><strong>Email:</strong> ${data.email}</p>
<p><strong>Phone:</strong> ${data.phone}</p>
<p><strong>Roles of Interest:</strong> ${data.roles}</p>
<p><strong>Resume:</strong> ${data.resume ? 'Attached' : 'Not provided'}</p>
<p><strong>Applied at:</strong> ${new Date().toLocaleString()}</p>
</div>
<hr style="margin: 20px 0;">
<p style="color: #666; font-size: 14px;">
This email was sent from your website's career application form.
</p>
</div>
`,
attachments: attachments,
};
const result = await transporter.sendMail(mailOptions);
console.log('Career email sent successfully:', result.messageId);
return result;
}
// POST handler for all form submissions
export async function POST(request) {
console.log('\n🚀 === EMAIL API ROUTE STARTED ===');
try {
// Check environment variables first
const requiredEnvVars = {
ZOHO_EMAIL: process.env.ZOHO_EMAIL,
ZOHO_PASSWORD: process.env.ZOHO_PASSWORD,
RECIPIENT_EMAIL: process.env.RECIPIENT_EMAIL,
};
console.log('Environment variables check:');
Object.entries(requiredEnvVars).forEach(([key, value]) => {
console.log(`${key}: ${value ? '✅ Set' : '❌ Missing'}`);
});
console.log(
'Loaded password (first 3 chars):',
process.env.ZOHO_PASSWORD?.slice(0, 3)
);
if (!requiredEnvVars.ZOHO_EMAIL || !requiredEnvVars.ZOHO_PASSWORD || !requiredEnvVars.RECIPIENT_EMAIL) {
console.error('❌ Missing required environment variables');
return NextResponse.json(
{ error: 'Email configuration missing' },
{ status: 500 }
);
}
// Parse request body
let body;
try {
body = await request.json();
console.log('✅ Request body parsed successfully');
} catch (parseError) {
console.error('❌ Failed to parse request body:', parseError);
return NextResponse.json(
{ error: 'Invalid JSON in request body' },
{ status: 400 }
);
}
const { type, ...data } = body;
console.log(`📝 Form type: ${type}`);
console.log(`📋 Form data keys: ${Object.keys(data).join(', ')}`);
if (!type) {
console.error('❌ No form type specified');
return NextResponse.json(
{ error: 'Form type is required' },
{ status: 400 }
);
}
// Route to appropriate handler based on form type
let result;
switch (type) {
case 'newsletter':
if (!data.email) {
console.error('❌ Newsletter: Email is required');
return NextResponse.json({ error: 'Email is required' }, { status: 400 });
}
result = await handleNewsletter(data);
break;
case 'contact':
if (!data.fullName || !data.email) {
console.error('❌ Contact: Full name and email are required');
return NextResponse.json({ error: 'Full name and email are required' }, { status: 400 });
}
result = await handleContact(data);
break;
case 'career':
if (!data.fullName || !data.email || !data.phone) {
console.error('❌ Career: Full name, email, and phone are required');
return NextResponse.json({ error: 'Full name, email, and phone are required' }, { status: 400 });
}
result = await handleCareer(data);
break;
default:
console.error('❌ Invalid form type:', type);
return NextResponse.json({ error: 'Invalid form type' }, { status: 400 });
}
console.log('✅ Email sent successfully!');
console.log('📧 Message ID:', result.messageId);
console.log('🎉 === EMAIL API ROUTE SUCCESS ===\n');
return NextResponse.json(
{
message: 'Email sent successfully',
messageId: result.messageId,
type: type
},
{ status: 200 }
);
} catch (error) {
console.error('\n💥 === EMAIL API ROUTE ERROR ===');
console.error('Error name:', error.name);
console.error('Error message:', error.message);
console.error('Error code:', error.code);
console.error('Error stack:', error.stack);
// Provide more specific error messages
let errorMessage = 'Failed to send email';
let statusCode = 500;
if (error.code === 'EAUTH') {
errorMessage = 'Authentication failed. Please check your Zoho email and app password.';
console.error('🔐 Authentication issue - check ZOHO_EMAIL and ZOHO_PASSWORD');
} else if (error.code === 'ECONNECTION' || error.code === 'ETIMEDOUT') {
errorMessage = 'Connection to email server failed. Please try again.';
console.error('🌐 Network connection issue');
} else if (error.code === 'EMESSAGE') {
errorMessage = 'Invalid email message format.';
statusCode = 400;
console.error('📧 Email format issue');
}
console.error('💥 === END ERROR DETAILS ===\n');
return NextResponse.json(
{
error: errorMessage,
details: error.message,
code: error.code
},
{ status: statusCode }
);
}
}