使用SendGrid模块实现联系表单发邮件时遭遇404错误求助
问题:SendGrid邮件发送出现404错误
点击联系表单的「发送」按钮后,控制台抛出404错误,邮件未发送:
POST http://localhost:3000/send-email 404 (Not Found) Card.tsx:58 Error: Request failed with status code 404 at createError (createError.js:16:1) at settle (settle.js:17:1) at XMLHttpRequest.onloadend (xhr.js:66:1)
相关代码
客户端Card.tsx(联系表单)
import React, { useState, useEffect, useRef } from "react"; import cardcss from "./Card.module.css"; import axios from "axios"; interface CardProps { imageUrl: string; title: string; body: string; } function Card(props: CardProps) { // State and ref initialization useEffect(() => { // Focus and selection logic }, []); const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => { // Handle focus event }; const submitHandler = (event: React.FormEvent<HTMLFormElement>) => { event.preventDefault(); // Form data retrieval and preparation axios .post("http://localhost:3000/send-email", contactData) .then((response) => { console.log("Received email request"); // Handle success response }) .catch((error) => { console.error(error); // Handle error response }); }; return ( // JSX code for the contact form ); } export default Card;
服务端server.js(处理邮件发送)
const express = require("express"); const sgMail = require("@sendgrid/mail"); const { resolve } = require("path-browserify"); // Set up SendGrid API key sgMail.setApiKey("*****"); // Create Express app const app = express(); // Middleware to parse JSON requests app.use(express.json()); app.get("/", (req, res) => { res.send("Hello, server!"); }); // Route to handle sending emails app.post("/send-email", (req, res) => { // Extract form data const msg = { to: "****@gmail.com", from: "*****@gmail.com", subject: "Example Subject", text: `Name: ${Name}\nEmail: ${Email}\nMessage: ${Message}\nSubmit Button: ${submitbutton}`, html: `<p>Name: ${Name}</p><p>Email: ${Email}</p><p>Message: ${Message}</p><p>Submit Button: ${submitbutton}</p>`, }; sgMail .send(msg) .then(() => { res.status(200).json({ message: "Email sent successfully" }); }) .catch((error) => { console.error(error.toString()); res.status(500).json({ error: "Failed to send email" }); }); }); // Set up fallback for path module resolve.fallback = { path: require.resolve("path-browserify") }; // Start the server app.listen(3000, () => { console.log("Server started on port 3000"); });
联系页面Contact.tsx
import React, { useRef } from "react"; import contactcss from "./Contact.module.css"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import Card from "../../components/ui/Card"; import { faInstagram, faFacebook, faLinkedin, faDiscord, } from "@fortawesome/free-brands-svg-icons"; import emaillogo from "../../resources/email-logo.png"; const Contact: React.FC = () => { return ( <div> <div> <div className={contactcss.background}> <img className={contactcss.emaillogo} src={emaillogo} alt="Contact Us" /> <div className={contactcss.contact}>Contact Us</div> </div> </div> <Card title="We're keen to hear from you!" imageUrl="https://images.app.goo.gl/D6m6hHMnP1gjsKKV7" body="" /* onSubmitForm={submitFormHandler} */ // Placeholder comment /> <div className={contactcss.whitebackground}> <div className={contactcss.socials}> <h1>Follow Our Socials</h1> <p className={contactcss.socialmedia}> Stay connected with GDSC USYD by following us on our social media channels: </p> <div> <a href="https://www.instagram.com/gdscusyd/"> <FontAwesomeIcon className={contactcss.instagram} icon={faInstagram} /> </a> <a href="https://www.facebook.com/gdsc.usyd"> <FontAwesomeIcon className={contactcss.facebook} icon={faFacebook} /> </a> <a href="https://discord.com/channels/872033047652990986/872033047652990989"> <FontAwesomeIcon className={contactcss.discord} icon={faDiscord} /> </a> <a href="*****")> <FontAwesomeIcon className={contactcss.linkedin} icon={faLinkedin} /> </a> </div> </div> </div> </div> ); }; export default Contact;
补充信息
- SendGrid API密钥配置正确
- 客户端与服务端均在本地运行
- 服务端监听3000端口,客户端请求地址为
http://localhost:3000/send-email
已尝试操作
- 确认服务端
/send-email路由定义正确 - 验证服务端正常运行并监听3000端口
- 确认表单数据在发送前已正确获取
排查方向与解决方案
1. 修复服务端代码错误
服务端代码中resolve.fallback = { path: require.resolve("path-browserify") };存在逻辑错误:resolve是从path-browserify导入的函数,并非可修改属性的对象,这行代码会抛出运行时错误,导致后续的/send-email路由无法被注册。
解决方法:直接删除该行代码。如果需要配置Webpack的路径fallback,应在Webpack配置文件中设置,而非Express服务代码内。
2. 检查端口占用情况
即使服务端日志显示监听3000端口,仍可能存在端口被其他进程占用的情况,导致服务未真正启动。可通过以下命令检查:
# Windows系统 netstat -ano | findstr :3000 # macOS/Linux系统 lsof -i :3000
若发现占用进程,杀掉后重启服务即可。
3. 处理跨域问题
如果客户端实际运行在非3000端口(比如React项目默认占用3000时会自动切换到其他端口),需在服务端添加CORS中间件:
const cors = require('cors'); app.use(cors());
同时执行npm install cors安装依赖包。
4. 验证路由一致性
确认客户端请求的路径/send-email与服务端定义的路由完全一致,检查是否存在大小写、斜杠拼写等细节错误。
内容的提问来源于stack exchange,提问作者user22081405
相关产品推荐
相关产品推荐

