feat: 实现联系表单提交与邮件通知功能
添加联系表单提交接口和邮件通知功能,支持从环境变量读取 SMTP 配置 重构 SEO 配置到 site.json,新增 robots.txt 和 sitemap.xml 生成 更新公司电话并添加 PM2 生产运行配置
This commit is contained in:
79
app/api/contact/route.ts
Normal file
79
app/api/contact/route.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { NextResponse } from "next/server"
|
||||
import { ZodError } from "zod"
|
||||
import { contactFormSchema } from "@/lib/contact-form"
|
||||
import { sendContactNotification } from "@/lib/contact-mailer"
|
||||
import { ContactMailerConfigError, loadContactMailerConfig } from "@/lib/contact-mailer-config"
|
||||
|
||||
export const runtime = "nodejs"
|
||||
|
||||
function getClientIp(request: Request) {
|
||||
const forwardedFor = request.headers.get("x-forwarded-for")
|
||||
|
||||
if (forwardedFor) {
|
||||
return forwardedFor.split(",")[0]?.trim() || "unknown"
|
||||
}
|
||||
|
||||
return request.headers.get("x-real-ip") ?? "unknown"
|
||||
}
|
||||
|
||||
function formatSubmittedAt() {
|
||||
return new Intl.DateTimeFormat("zh-CN", {
|
||||
timeZone: "Asia/Shanghai",
|
||||
dateStyle: "full",
|
||||
timeStyle: "long",
|
||||
}).format(new Date())
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
let requestBody: unknown
|
||||
|
||||
try {
|
||||
requestBody = await request.json()
|
||||
} catch {
|
||||
return NextResponse.json(
|
||||
{ error: "请求格式不正确,请刷新后重试。" },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
try {
|
||||
const payload = contactFormSchema.parse(requestBody)
|
||||
const config = await loadContactMailerConfig()
|
||||
|
||||
await sendContactNotification({
|
||||
config,
|
||||
payload,
|
||||
meta: {
|
||||
submittedAt: formatSubmittedAt(),
|
||||
sourceUrl: request.headers.get("referer") ?? request.headers.get("origin") ?? new URL(request.url).origin,
|
||||
ipAddress: getClientIp(request),
|
||||
userAgent: request.headers.get("user-agent") ?? "unknown",
|
||||
},
|
||||
})
|
||||
|
||||
return NextResponse.json({ ok: true })
|
||||
} catch (error) {
|
||||
if (error instanceof ZodError) {
|
||||
return NextResponse.json(
|
||||
{ error: error.issues[0]?.message ?? "提交信息不完整,请检查后重试。" },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
if (error instanceof ContactMailerConfigError) {
|
||||
console.error(error.message)
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: "邮件通知配置不完整,请联系管理员检查 SMTP 设置。" },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
|
||||
console.error("Failed to send contact notification", error)
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: "提交失败,邮件通知未发送成功,请稍后重试。" },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user