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

Next.js API路由实现邮件发送时重复发信该如何解决?

问题根因

你遇到的发两封邮件的问题和是否抽离发信函数没有关系,核心原因是代码中存在多余的全局调用:你在定义完contactUsEmail函数后,直接写了一行contactUsEmail().catch(console.error);,这行代码会在Next.js加载该API路由文件时直接执行,没有传入任何参数,所以第一封参数全为undefined的邮件就是这行代码触发的。第二封参数正确的邮件才是用户请求接口时,控制器逻辑正常调用生成的。

修复方案
  • 第一步:直接删除文件中contactUsEmail().catch(console.error);这行多余的调用代码,即可解决重复发信的问题。
  • 第二步:优化异步调用逻辑,你当前在控制器中调用contactUsEmail时没有加await,会导致邮件还没发送完成就提前给前端返回响应,若发信过程出现报错前端也无法感知,建议补充await,同时增加异常捕获逻辑,避免服务端报错无处理。
  • 第三步:关于发信函数是否抽离:如果后续其他业务逻辑也需要用到发信能力,建议将contactUsEmail这类通用工具函数抽离到/lib或者/utils目录下统一维护,减少重复代码;如果只有当前这一个API路由用到发信功能,保留在当前文件中也完全没问题。
修复后的完整代码示例
const nodemailer = require("nodemailer");
import { validEmail } from '../../services';

const contactUsEmail = async (from, subject, tel, text, email) => {
  // 使用默认SMTP传输创建可复用的传输器对象
  const transporter = nodemailer.createTransport({
    host: 'smtp.ethereal.email',
    port: 587,
    auth: {
      user: 'myuser@example.com',
      pass: 'xxxxxxxxxxxx'
    }
  });

  // 使用已定义的传输器对象发送邮件
  let info = await transporter.sendMail({
    from: `${email}`, // 发件人邮箱地址
    to: "deven.medhurst@ethereal.email", // 收件人列表
    subject: `${subject}`, // 邮件主题
    text: `From: ${from}\nEmail: ${email}\nTel: ${tel}\n\n${text}`, // 纯文本正文
  });

  console.log("Message sent: %s", info.messageId);
  // 仅通过Ethereal账号发送邮件时可查看预览
  console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
  return info;
};

export default async function sendEmailToUs (req, res) {
  if(req.method !== 'POST'){
    res.status(400).send('Bad request');
    return
  }

  const email = req.body.email;  

  if(!validEmail(email)){
    res.status(400).send('Errors');
    return
  }
  
  try {
    const from = req.body.from;
    const tel = req.body.tel === '' ? '0' : req.body.tel;
    const subject = req.body.subject;
    const text = req.body.text;

    await contactUsEmail(from, subject, tel, text, email);
    res.status(200).send('Sended');
  } catch (err) {
    console.error('发信失败:', err);
    res.status(500).send('邮件发送失败');
  }
}

注:Next.js原生API路由不需要传入next参数,上述代码已移除该无用参数,同时删除了else块内重复声明的email变量。

内容的提问来源于stack exchange,提问作者Antonio De Luca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 10:45:04