const express = require('express'); const bodyParser = require('body-parser'); const cors = require('cors'); const nodemailer = require('nodemailer'); const dotenv = require('dotenv'); // 加载环境变量 dotenv.config(); const app = express(); const port = process.env.PORT || 3001; // 中间件 app.use(cors({ origin: '*', // 允许所有来源访问 methods: ['GET', 'POST', 'OPTIONS'], // 允许的HTTP方法 allowedHeaders: ['Content-Type', 'Authorization'], // 允许的请求头 credentials: true // 允许发送凭证 })); app.use(bodyParser.json()); // 处理OPTIONS预检请求 app.options('*', (req, res) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization'); res.header('Access-Control-Max-Age', '86400'); // 24小时 res.sendStatus(204); }); // 创建Nodemailer传输器 const transporter = nodemailer.createTransport({ service: process.env.EMAIL_SERVICE || 'smtp', // 邮件服务商,例如:'gmail', 'qq', '163'等 host: process.env.EMAIL_HOST || 'smtp.163.com', // SMTP服务器 port: parseInt(process.env.EMAIL_PORT || '587'), secure: process.env.EMAIL_SECURE === 'true', // true for 465, false for other ports auth: { user: process.env.EMAIL_USER || '', // 发送方邮箱 pass: process.env.EMAIL_PASS || '', // 授权码或密码 }, // 增加连接超时设置 connectionTimeout: 10000, // 10秒连接超时 greetingTimeout: 10000, // 10秒问候超时 socketTimeout: 15000, // 15秒socket超时 // 增加重试选项 pool: true, // 使用连接池 maxConnections: 5, // 最大连接数 maxMessages: 100, // 每个连接最大消息数 // 调试选项 debug: true, // 启用调试日志 }); // 验证传输器连接 transporter.verify(function(error, success) { if (error) { console.error('SMTP连接验证失败:', error); } else { console.log('SMTP服务器连接成功,准备发送邮件'); } }); // 存储IP地址最后发送邮件的时间 const lastEmailSentTime = new Map(); // 速率限制中间件 - 60秒内只能发送一封邮件 const rateLimitMiddleware = (req, res, next) => { const ip = req.ip || req.connection.remoteAddress; const currentTime = Date.now(); const lastTime = lastEmailSentTime.get(ip) || 0; const timeDiff = currentTime - lastTime; // 如果距离上次发送不足60秒,则拒绝请求 if (lastTime && timeDiff < 60000) { const remainingTime = Math.ceil((60000 - timeDiff) / 1000); return res.status(429).json({ error: `请求过于频繁,请在${remainingTime}秒后再试`, remainingTime }); } // 更新最后发送时间并继续处理请求 lastEmailSentTime.set(ip, currentTime); next(); }; // 邮件发送接口 app.post('/api/send-email', rateLimitMiddleware, async (req, res) => { const { name, email, subject, message } = req.body; if (!name || !email || !message) { return res.status(400).json({ error: '请填写所有必填字段' }); } // 邮件选项 const mailOptions = { from: `"个人网站联系表单" <${process.env.EMAIL_USER}>`, to: process.env.EMAIL_RECIPIENT || process.env.EMAIL_USER, // 接收方邮箱 subject: subject ? `新的联系表单消息: ${subject}` : '新的联系表单消息', html: `
姓名: ${name}
邮箱: ${email}
主题: ${subject || '无'}
消息:
${message.replace(/\n/g, '
')}