You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 00:29:58