93 lines
3.2 KiB
TypeScript
93 lines
3.2 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import nodemailer from "nodemailer";
|
|
|
|
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
|
|
export async function POST(request: Request) {
|
|
let body: Record<string, unknown>;
|
|
try {
|
|
body = await request.json();
|
|
} catch {
|
|
return NextResponse.json({ error: "Invalid request body." }, { status: 400 });
|
|
}
|
|
|
|
const name = String(body.name ?? "").trim();
|
|
const email = String(body.email ?? "").trim();
|
|
const mailboxes = String(body.mailboxes ?? "").trim();
|
|
const provider = String(body.provider ?? "").trim();
|
|
const message = String(body.message ?? "").trim();
|
|
|
|
const errors: Record<string, string> = {};
|
|
if (!name) {
|
|
errors.name = "Please enter your name.";
|
|
}
|
|
if (!email) {
|
|
errors.email = "Please enter your business email.";
|
|
} else if (!EMAIL_REGEX.test(email)) {
|
|
errors.email = "Email address needs to include an @ symbol.";
|
|
}
|
|
|
|
if (Object.keys(errors).length > 0) {
|
|
return NextResponse.json({ error: "Validation failed.", fields: errors }, { status: 400 });
|
|
}
|
|
|
|
const sesUser = process.env.SES_SMTP_USER;
|
|
const sesPass = process.env.SES_SMTP_PASS;
|
|
const fromEmail = process.env.SES_FROM_EMAIL;
|
|
|
|
if (!sesUser || !sesPass || !fromEmail) {
|
|
return NextResponse.json({ error: "Server configuration error." }, { status: 500 });
|
|
}
|
|
|
|
const transporter = nodemailer.createTransport({
|
|
host: "email-smtp.us-east-2.amazonaws.com",
|
|
port: 587,
|
|
secure: false,
|
|
auth: {
|
|
user: sesUser,
|
|
pass: sesPass,
|
|
},
|
|
});
|
|
|
|
const textBody = [
|
|
`Name: ${name}`,
|
|
`Business Email: ${email}`,
|
|
`Mailboxes: ${mailboxes || "(not provided)"}`,
|
|
`Current Provider: ${provider || "(not selected)"}`,
|
|
`Message: ${message || "(none)"}`,
|
|
].join("\n");
|
|
|
|
const htmlBody = [
|
|
"<table style='font-family:sans-serif;border-collapse:collapse;'>",
|
|
`<tr><td style='padding:6px 12px 6px 0;font-weight:700;white-space:nowrap;'>Name</td><td style='padding:6px 0;'>${escapeHtml(name)}</td></tr>`,
|
|
`<tr><td style='padding:6px 12px 6px 0;font-weight:700;white-space:nowrap;'>Business Email</td><td style='padding:6px 0;'>${escapeHtml(email)}</td></tr>`,
|
|
`<tr><td style='padding:6px 12px 6px 0;font-weight:700;white-space:nowrap;'>Mailboxes</td><td style='padding:6px 0;'>${escapeHtml(mailboxes || "(not provided)")}</td></tr>`,
|
|
`<tr><td style='padding:6px 12px 6px 0;font-weight:700;white-space:nowrap;'>Current Provider</td><td style='padding:6px 0;'>${escapeHtml(provider || "(not selected)")}</td></tr>`,
|
|
`<tr><td style='padding:6px 12px 6px 0;font-weight:700;white-space:nowrap;'>Message</td><td style='padding:6px 0;'>${escapeHtml(message || "(none)")}</td></tr>`,
|
|
"</table>",
|
|
].join("\n");
|
|
|
|
try {
|
|
await transporter.sendMail({
|
|
from: fromEmail,
|
|
to: "support@bayarea-cc.com",
|
|
replyTo: email,
|
|
subject: `New email assessment request — ${name}`,
|
|
text: textBody,
|
|
html: htmlBody,
|
|
});
|
|
} catch {
|
|
return NextResponse.json({ error: "Unable to send your request. Please try again or call us." }, { status: 500 });
|
|
}
|
|
|
|
return NextResponse.json({ ok: true });
|
|
}
|
|
|
|
function escapeHtml(text: string): string {
|
|
return text
|
|
.replace(/&/g, "&")
|
|
.replace(/</g, "<")
|
|
.replace(/>/g, ">")
|
|
.replace(/"/g, """);
|
|
}
|