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

如何用Nodemailer实现表单提交后先后发送管理员与用户邮件?

实现步骤

一、后端Node.js服务改造

将原有GET接口改为POST接口以接收React表单数据,通过async/await实现邮件顺序发送(先管理员通知,成功后再发用户确认邮件),避免回调嵌套的混乱。

改造后的后端代码

const express = require('express')
const nodeMailer = require('nodemailer')
const cors = require('cors') // 解决跨域问题,需先安装:npm install cors
const app = express()

// 配置跨域和JSON解析
app.use(cors())
app.use(express.json())

// 初始化邮件传输器(保持原配置)
let mailTransport = nodeMailer.createTransport({
  service: 'gmail',
  auth: {
    user: 'xuser@gmail.com',
    pass: 'dplcflaj21jcdtspsv22' // 生产环境建议用环境变量存储,比如process.env.EMAIL_PASS
  }
})

// 发送管理员通知邮件
async function sendAdminAlert(userInfo) {
  const adminMailOpts = {
    from: 'xuser@gmail.com',
    to: 'testadmin@gmail.com',
    subject: `新用户提交:${userInfo.name}`,
    html: `
      <h3>新增用户信息</h3>
      <p><strong>姓名:</strong>${userInfo.name}</p>
      <p><strong>邮箱:</strong>${userInfo.email}</p>
      <p><strong>地址:</strong>${userInfo.address}</p>
    `
  }
  await mailTransport.sendMail(adminMailOpts)
}

// 发送用户确认邮件
async function sendUserConfirm(userInfo) {
  const userMailOpts = {
    from: 'xuser@gmail.com',
    to: userInfo.email,
    subject: `感谢您的提交,${userInfo.name}`,
    html: `
      <h3>提交成功!</h3>
      <p>您好 ${userInfo.name},我们已收到您的信息:</p>
      <p><strong>地址:</strong>${userInfo.address}</p>
      <p>我们会尽快与您取得联系。</p>
    `
  }
  await mailTransport.sendMail(userMailOpts)
}

// 表单提交处理接口
app.post('/submit-form', async (req, res) => {
  try {
    const userData = req.body
    // 1. 优先发送管理员通知邮件
    await sendAdminAlert(userData)
    console.log('管理员邮件发送成功')
    
    // 2. 管理员邮件成功后,发送用户确认邮件
    await sendUserConfirm(userData)
    console.log('用户确认邮件发送成功')
    
    res.status(200).json({ success: true, msg: '邮件发送完成' })
  } catch (err) {
    console.error('邮件发送失败:', err)
    // 任意一步出错,返回错误信息给前端
    res.status(500).json({ success: false, msg: '邮件发送失败,请稍后重试' })
  }
})

app.listen(3000, () => {
  console.log('服务运行在端口3000')
})

关键说明

  • 顺序执行保证:用async/await确保只有管理员邮件成功后,才会触发用户确认邮件的发送,避免逻辑混乱。
  • 代码可维护性:将两类邮件的发送逻辑拆分为独立函数,便于后续修改内容或扩展。
  • 安全提示:生产环境务必将邮箱密码等敏感信息存入环境变量,禁止硬编码;Gmail用户若开启两步验证,需使用应用专用密码替代普通密码。

二、前端React表单实现

创建表单组件收集用户信息,提交到后端接口并处理提交状态反馈。

React表单组件示例

import { useState } from 'react'

function UserInfoForm() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    address: ''
  })
  const [submitMsg, setSubmitMsg] = useState('')

  const handleInputChange = (e) => {
    const { name, value } = e.target
    setFormData(prev => ({ ...prev, [name]: value }))
  }

  const handleSubmit = async (e) => {
    e.preventDefault()
    setSubmitMsg('提交中...')
    
    try {
      const res = await fetch('http://localhost:3000/submit-form', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(formData)
      })
      
      const result = await res.json()
      if (result.success) {
        setSubmitMsg('提交成功!确认邮件已发送至您的邮箱')
        // 重置表单
        setFormData({ name: '', email: '', address: '' })
      } else {
        setSubmitMsg('提交失败,请稍后重试')
      }
    } catch (err) {
      setSubmitMsg('网络错误,请检查连接')
      console.error('提交异常:', err)
    }
  }

  return (
    <form onSubmit={handleSubmit} style={{ maxWidth: '450px', margin: '2rem auto', padding: '1rem' }}>
      <div style={{ marginBottom: '1rem' }}>
        <label>姓名:</label>
        <input
          type="text"
          name="name"
          value={formData.name}
          onChange={handleInputChange}
          required
          style={{ width: '100%', padding: '0.5rem', marginTop: '0.25rem' }}
        />
      </div>
      <div style={{ marginBottom: '1rem' }}>
        <label>邮箱:</label>
        <input
          type="email"
          name="email"
          value={formData.email}
          onChange={handleInputChange}
          required
          style={{ width: '100%', padding: '0.5rem', marginTop: '0.25rem' }}
        />
      </div>
      <div style={{ marginBottom: '1rem' }}>
        <label>地址:</label>
        <textarea
          name="address"
          value={formData.address}
          onChange={handleInputChange}
          required
          rows="4"
          style={{ width: '100%', padding: '0.5rem', marginTop: '0.25rem' }}
        />
      </div>
      <button type="submit" style={{ padding: '0.5rem 1.5rem', cursor: 'pointer' }}>
        提交信息
      </button>
      {submitMsg && (
        <p style={{ marginTop: '1rem', color: submitMsg.includes('成功') ? 'green' : 'red' }}>
          {submitMsg}
        </p>
      )}
    </form>
  )
}

export default UserInfoForm

关键说明

  • 状态反馈:通过submitMsg给用户展示提交中、成功、失败等状态,提升体验。
  • 跨域处理:后端已配置cors中间件,避免React应用与后端端口不同导致的跨域错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:33:28