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

页面加载时POST请求自动触发,联系表单邮件发送失败

单页网站联系表单邮件发送异常问题

我的单页网站内置邮件联系表单,需求是用户填写提交表单时给我的账号发送邮件,但功能失效:页面加载完成后会立即触发POST请求,导致app.js里的邮件发送函数因参数未定义无法处理请求。

错误截图


相关代码

app.js中的Node.js邮件发送函数

const app = require('express')();
const nodemailer = require('nodemailer');
const path = require('path');
const PORT = process.env.PORT || 3000;
const express = require('express');

async function mainMail(name, email, message) {
    const transporter = await nodemailer.createTransport({
        service: 'gmail',
        auth: {
            user: '*my_email*',
            pass: '*my_password*'
        }
    });

    const mailOption = {
        from: '*my email*',
        to: '*my second email*',
        subject: email,
        html: `You've got message from:
        email: ${email}
        name: ${name}
        message: ${message}`
    };

    try {
        await transporter.sendMail(mailOption);
        return Promise.resolve('Message sent successfully');
    } catch(error) {
        return Promise.reject(error);
    }
}

app.post('/', async(req, res, next) => {
    try {
        await mainMail(req.body.name, req.body.email, req.body.message);
        res.send('Message sent!');
    } catch(error) {
        console.log(error);
        res.send('Message not sent!');
    }
})

app.listen(PORT, () => {
    console.log(`PORT -> ${PORT}`);
});

HTML表单代码

<form method="post" class="contacts-form" id="contacts-form">
            <div class="contacts-upper-inputs">
                <div class="input-container half-input">
                    <label for="name" class="primary-label">Name</label>
                    <input required name="name" id="name" class="primary-input"></input>
                </div>
                <div class="input-container half-input">
                    <label for="email" class="primary-label">Email</label>
                    <input required name="email" id="email" class="primary-input"></input>
                </div>
            </div>
            <div class="input-container">
                <label for="message-text" class="primary-label">Message</label>
                <textarea required name="message" name="" id="message" cols="30" rows="10" class="primary-input"></textarea>
            </div>
            <div style="display: flex; justify-content: center;">
                <button onclick="sendEmail(event)" class="btn-contact">Submit</button>
            </div>
        </form>

index.js中的提交处理函数

function sendEmail(event) {
    event.preventDefault();
    const name = document.getElementById('name').value;
    const email = document.getElementById('email').value;
    const message = document.getElementById('message').value;

    $.post('/', 
        {
            name: name,
            email: email,
            message: message
        },
        function(data, status) {
            console.log('status -> ', status);
        });
}

问题原因及修复方案

核心问题

  1. Express未配置请求体解析中间件:没有添加express.urlencoded()或express.json(),导致req.body无法读取表单提交的数据,触发参数未定义错误。
  2. 表单按钮默认行为冲突:按钮默认类型为submit,即使有onclick事件,仍可能触发表单默认POST提交,导致页面加载时或点击时重复发起请求。
  3. 单页网站静态资源未配置:Express未处理GET请求返回主页,可能导致路由逻辑混乱,触发意外的POST请求。

修复步骤

  1. 添加请求体解析中间件:在app.js的POST路由定义前加入以下代码,让Express能解析表单数据:
app.use(express.urlencoded({ extended: true }));
app.use(express.json()); // 可选,支持JSON格式请求体
  1. 修改按钮类型避免默认提交:将HTML中的按钮明确设置为button类型,彻底阻止表单默认提交行为:
<button type="button" onclick="sendEmail(event)" class="btn-contact">Submit</button>
  1. 配置静态文件服务与GET路由:为单页网站添加静态资源服务,并处理根路径的GET请求返回主页:
// 假设静态文件(HTML/CSS/JS)放在项目根目录的public文件夹下
app.use(express.static(path.join(__dirname, 'public')));

// 处理GET请求返回主页
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 09:05:24