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

React调用react-email API遇CORS及res.setHeader错误求助

问题分析与解决方案

核心问题

  1. CORS拦截:React应用(44411端口)与react-email服务(3000端口)属于不同域,浏览器同源策略会拦截跨域请求;Postman不受浏览器同源策略限制,因此能正常请求。
  2. res.setHeader is not a function报错:你大概率在Next.js App Router的route.ts中使用了Express生态的cors中间件——Next.js App Router的Response对象遵循Web标准,没有Express的setHeader方法,导致中间件调用失败。

解决方案

方案1:手动设置CORS响应头(推荐,无需额外依赖)

直接在route.ts中添加CORS头,并处理OPTIONS预检请求:

import { NextResponse } from 'next/server';
import { Resend } from 'resend';
// 导入你的React Email组件
import YourEmailTemplate from '@/emails/YourEmailTemplate';

const resend = new Resend(process.env.RESEND_API_KEY);

export async function POST(request: Request) {
  // 配置CORS头,允许你的React应用域名
  const corsHeaders = new Headers({
    'Access-Control-Allow-Origin': 'http://localhost:44411',
    'Access-Control-Allow-Methods': 'POST, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type',
  });

  // 处理浏览器OPTIONS预检请求
  if (request.method === 'OPTIONS') {
    return new NextResponse(null, { headers: corsHeaders });
  }

  try {
    const payload = await request.json();
    const { data, error } = await resend.emails.send({
      from: 'Your App <onboarding@resend.dev>',
      to: [payload.toEmail],
      subject: payload.subject,
      react: YourEmailTemplate({ content: payload.content }),
    });

    if (error) {
      return new NextResponse(JSON.stringify({ error }), {
        status: 400,
        headers: corsHeaders,
      });
    }

    return new NextResponse(JSON.stringify(data), { headers: corsHeaders });
  } catch (err) {
    return new NextResponse(JSON.stringify({ error: err }), {
      status: 500,
      headers: corsHeaders,
    });
  }
}

方案2:使用适配Next.js的CORS工具

如果不想手动写头,可以用next-cors包(专门适配Next.js的CORS处理工具):

  1. 安装依赖
npm install next-cors
  1. 修改route.ts
import { NextResponse } from 'next/server';
import { Resend } from 'resend';
import nextCors from 'next-cors';
import YourEmailTemplate from '@/emails/YourEmailTemplate';

const resend = new Resend(process.env.RESEND_API_KEY);

export async function POST(request: Request) {
  // 配置CORS规则
  await nextCors(request, NextResponse, {
    origin: 'http://localhost:44411',
    methods: ['POST', 'OPTIONS'],
    allowedHeaders: ['Content-Type'],
  });

  try {
    const payload = await request.json();
    const { data, error } = await resend.emails.send({
      from: 'Your App <onboarding@resend.dev>',
      to: [payload.toEmail],
      subject: payload.subject,
      react: YourEmailTemplate({ content: payload.content }),
    });

    if (error) return NextResponse.json({ error }, { status: 400 });
    return NextResponse.json(data);
  } catch (err) {
    return NextResponse.json({ error: err }, { status: 500 });
  }
}

注意事项

  • 生产环境不要硬编码http://localhost:44411,改用环境变量动态配置允许的域名,比如:
    'Access-Control-Allow-Origin': process.env.NEXT_PUBLIC_REACT_APP_URL || 'http://localhost:44411',
    
  • 确认React应用中的API请求地址正确,比如:
    // React的handleSubmit代码示例
    async function handleSubmit(formData) {
      try {
        const response = await fetch('http://localhost:3000/api/email', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(formData),
        });
        const data = await response.json();
        // 处理响应
      } catch (err) {
        console.error('请求失败:', err);
      }
    }
    
  • 如果你用的是Next.js Pages Router的API路由(pages/api/xxx.ts),可以直接使用Express的cors中间件,因为Pages Router的API基于Express,Response对象兼容setHeader方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 00:39:51