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

React(Vite)结合Express+Nodemailer发邮件遇404错误求助

解决Vite React + Express + Nodemailer 404请求错误

问题核心

  • 基于Vite的React项目中,点击「Realizar Pedido」按钮触发订单邮件发送请求时,返回404错误
  • 已尝试调整请求地址、CORS配置、请求方法,问题仍未解决

前后端示例代码(基于场景还原)

前端React请求代码

const handlePlaceOrder = async () => {
  const orderData = {
    orderSummary: cartItems,
    customerInfo: { name, email, phone }
  };

  try {
    const res = await fetch('http://localhost:3000/api/send-order', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(orderData)
    });

    if (!res.ok) throw new Error('请求失败');
    const data = await res.json();
    alert(data.message);
  } catch (err) {
    console.error(err);
    alert('发送订单失败');
  }
};

后端Express + Nodemailer代码

const express = require('express');
const nodemailer = require('nodemailer');
const cors = require('cors');
const app = express();

// 中间件配置
app.use(express.json());
app.use(cors({ origin: 'http://localhost:5173' }));

// 邮件发送路由
app.post('/api/send-order', async (req, res) => {
  const { orderSummary, customerInfo } = req.body;

  try {
    // 初始化Nodemailer transporter
    const transporter = nodemailer.createTransport({
      host: 'smtp.gmail.com',
      port: 587,
      secure: false,
      auth: {
        user: 'your-email@example.com',
        pass: 'your-app-password'
      }
    });

    // 邮件内容配置
    const mailOptions = {
      from: 'Tu Tienda <your-email@example.com>',
      to: 'admin@your-store.com',
      subject: `Nuevo Pedido - ${customerInfo.name}`,
      html: `
        <h3>Información del Cliente</h3>
        <p>Nombre: ${customerInfo.name}</p>
        <p>Email: ${customerInfo.email}</p>
        <p>Teléfono: ${customerInfo.phone}</p>
        <h3>Resumen del Pedido</h3>
        <ul>
          ${orderSummary.map(item => `<li>${item.quantity}x ${item.name} - $${item.price * item.quantity}</li>`).join('')}
        </ul>
        <p>Total: $${orderSummary.reduce((sum, item) => sum + item.price * item.quantity, 0)}</p>
      `
    };

    await transporter.sendMail(mailOptions);
    res.status(200).json({ message: 'Pedido enviado exitosamente' });
  } catch (error) {
    console.error('邮件发送失败:', error);
    res.status(500).json({ message: 'Error al enviar el pedido' });
  }
});

// 启动服务
const PORT = 3000;
app.listen(PORT, () => console.log(`Servidor corriendo en puerto ${PORT}`));

排查与解决步骤

1. 校验路由路径一致性

  • 确保前端请求的路径与后端路由完全匹配,注意大小写、斜杠结尾、前缀(如/api)是否一致
  • 例:前端请求/api/send-order,后端必须用app.post('/api/send-order', ...),不能写成/send-order或/api/sendOrder

2. 确认CORS配置正确性

  • 明确指定允许的前端源(Vite默认开发端口为5173),避免使用过于宽松的cors()配置(生产环境需严格限制)
  • 若前端配置了Vite代理,CORS可仅允许代理目标地址,或直接依赖代理避免跨域问题

3. 检查请求方法匹配

  • 前端使用POST请求时,后端必须对应使用app.post(),不能混用app.get()或其他方法

4. 验证端口与服务状态

  • 确认Express服务运行的端口与前端请求中的端口一致(例:后端端口3000,前端不能请求3001)
  • 启动后端时打印端口日志,确保服务正常启动

5. 配置Vite代理简化请求(可选)

在vite.config.js中添加代理配置,避免跨域同时简化请求路径:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true
      }
    }
  }
});

配置后前端可直接用fetch('/api/send-order')发起请求

6. 确保解析JSON请求体

  • 后端必须添加app.use(express.json())中间件,否则无法解析前端发送的JSON格式请求体,可能导致路由匹配异常

内容的提问来源于stack exchange,提问作者Teo Gali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 02:20:34