79 lines
3.4 KiB
TypeScript
79 lines
3.4 KiB
TypeScript
import { NextResponse } from 'next/server';
|
|
import { Resend } from 'resend';
|
|
|
|
const resend = new Resend(process.env.RESEND_API_KEY);
|
|
|
|
function escapeHtml(str: string): string {
|
|
return str
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"');
|
|
}
|
|
|
|
export async function POST(request: Request) {
|
|
try {
|
|
const body = await request.json();
|
|
const { name, email, message } = body;
|
|
|
|
if (!name || typeof name !== 'string' || name.trim().length === 0) {
|
|
return NextResponse.json({ error: 'Name is required' }, { status: 400 });
|
|
}
|
|
if (!email || typeof email !== 'string' || !email.includes('@') || !email.includes('.')) {
|
|
return NextResponse.json({ error: 'Valid email is required' }, { status: 400 });
|
|
}
|
|
if (!message || typeof message !== 'string' || message.trim().length === 0) {
|
|
return NextResponse.json({ error: 'Message is required' }, { status: 400 });
|
|
}
|
|
|
|
const safeName = escapeHtml(name.trim());
|
|
const safeEmail = escapeHtml(email.trim());
|
|
const safeMessage = escapeHtml(message.trim());
|
|
|
|
const { error } = await resend.emails.send({
|
|
from: 'XHIVA Art <noreply@jeffemmett.com>',
|
|
to: 'xhivart@gmail.com',
|
|
replyTo: email.trim(),
|
|
subject: `New message from ${name.trim()} — XHIVA Art`,
|
|
html: `
|
|
<div style="font-family: Georgia, serif; max-width: 600px; margin: 0 auto; padding: 40px 20px;">
|
|
<div style="border-bottom: 2px solid #c9a962; padding-bottom: 20px; margin-bottom: 30px;">
|
|
<h1 style="font-size: 24px; font-weight: 300; letter-spacing: 0.1em; color: #2d2d2d; margin: 0;">
|
|
New Message from XHIVA Art
|
|
</h1>
|
|
</div>
|
|
<div style="margin-bottom: 24px;">
|
|
<p style="font-family: Montserrat, sans-serif; font-size: 11px; letter-spacing: 0.15em; text-transform: uppercase; color: #6b6b6b; margin: 0 0 4px 0;">NAME</p>
|
|
<p style="font-size: 16px; color: #2d2d2d; margin: 0;">${safeName}</p>
|
|
</div>
|
|
<div style="margin-bottom: 24px;">
|
|
<p style="font-family: Montserrat, sans-serif; font-size: 11px; letter-spacing: 0.15em; text-transform: uppercase; color: #6b6b6b; margin: 0 0 4px 0;">EMAIL</p>
|
|
<p style="font-size: 16px; color: #2d2d2d; margin: 0;">
|
|
<a href="mailto:${safeEmail}" style="color: #c9a962;">${safeEmail}</a>
|
|
</p>
|
|
</div>
|
|
<div style="margin-bottom: 24px;">
|
|
<p style="font-family: Montserrat, sans-serif; font-size: 11px; letter-spacing: 0.15em; text-transform: uppercase; color: #6b6b6b; margin: 0 0 4px 0;">MESSAGE</p>
|
|
<p style="font-size: 16px; color: #2d2d2d; margin: 0; white-space: pre-wrap;">${safeMessage}</p>
|
|
</div>
|
|
<div style="border-top: 1px solid #e5e5e5; padding-top: 20px; margin-top: 30px;">
|
|
<p style="font-family: Montserrat, sans-serif; font-size: 10px; letter-spacing: 0.1em; color: #6b6b6b; margin: 0;">
|
|
Sent from xhivart.jeffemmett.com contact form
|
|
</p>
|
|
</div>
|
|
</div>
|
|
`,
|
|
});
|
|
|
|
if (error) {
|
|
console.error('Resend error:', error);
|
|
return NextResponse.json({ error: 'Failed to send message' }, { status: 500 });
|
|
}
|
|
|
|
return NextResponse.json({ success: true });
|
|
} catch (err) {
|
|
console.error('Contact API error:', err);
|
|
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
|
|
}
|
|
}
|