This commit is contained in:
2025-02-27 17:10:33 +08:00
parent d3a3e1918c
commit d61028a104
20 changed files with 4274 additions and 96 deletions

87
api/README.md Normal file
View File

@@ -0,0 +1,87 @@
# 邮件发送API
这是一个简单的Express后端服务用于处理联系表单的邮件发送功能。
## 安装
```bash
cd api
npm install
```
## 配置
编辑 `.env` 文件,填入您的邮箱配置:
```
# 服务器配置
PORT=3001
# 邮件配置
EMAIL_SERVICE=163 # 邮件服务提供商
EMAIL_HOST=smtp.163.com # SMTP服务器地址
EMAIL_PORT=465 # SMTP端口
EMAIL_SECURE=true # 是否使用SSL/TLS
EMAIL_USER=your-email@163.com # 发送邮件的邮箱地址
EMAIL_PASS=your-password-or-app-password # 邮箱密码或授权码
EMAIL_RECIPIENT=recipient@example.com # 接收邮件的邮箱地址(可选默认与EMAIL_USER相同)
```
对于大部分邮箱服务商,您需要生成专门的"应用密码"或"授权码",而不是使用登录密码。例如:
- 对于163邮箱您需要在邮箱设置中开启SMTP服务并获取授权码
- 对于Gmail您需要开启两步验证并生成应用专用密码
## 运行
```bash
# 开发模式(自动重启)
npm run dev
# 生产模式
npm start
```
服务器将在 http://localhost:3001 上运行。
## API端点
### 发送邮件
```
POST /api/send-email
```
请求体示例:
```json
{
"name": "张三",
"email": "zhangsan@example.com",
"subject": "合作咨询",
"message": "我对您的项目很感兴趣,希望能进一步了解。"
}
```
成功响应:
```json
{
"success": true,
"message": "邮件已成功发送"
}
```
### 测试API
```
GET /api/test
```
响应示例:
```json
{
"message": "API服务器运行正常"
}
```

1152
api/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

20
api/package.json Normal file
View File

@@ -0,0 +1,20 @@
{
"name": "email-api",
"version": "1.0.0",
"description": "邮件发送API",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
},
"dependencies": {
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"nodemailer": "^6.9.7"
},
"devDependencies": {
"nodemon": "^3.0.1"
}
}

97
api/server.js Normal file
View File

@@ -0,0 +1,97 @@
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());
app.use(bodyParser.json());
// 创建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 || '', // 授权码或密码
},
});
// 存储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: '请填写所有必填字段' });
}
try {
// 邮件选项
const mailOptions = {
from: `"个人网站联系表单" <${process.env.EMAIL_USER}>`,
to: process.env.EMAIL_RECIPIENT || process.env.EMAIL_USER, // 接收方邮箱
subject: subject ? `新的联系表单消息: ${subject}` : '新的联系表单消息',
html: `
<h3>您有一条新的联系表单消息</h3>
<p><strong>姓名:</strong> ${name}</p>
<p><strong>邮箱:</strong> ${email}</p>
<p><strong>主题:</strong> ${subject || '无'}</p>
<p><strong>消息:</strong></p>
<p>${message.replace(/\n/g, '<br>')}</p>
`,
// 回复选项,回复时会发送到表单提交者的邮箱
replyTo: email
};
// 发送邮件
await transporter.sendMail(mailOptions);
return res.status(200).json({ success: true, message: '邮件已成功发送' });
} catch (error) {
console.error('发送邮件时出错:', error);
return res.status(500).json({ error: '发送邮件失败,请稍后再试' });
}
});
// 测试路由
app.get('/api/test', (req, res) => {
res.json({ message: 'API服务器运行正常' });
});
// 启动服务器
app.listen(port, () => {
console.log(`邮件服务API正在端口 ${port} 上运行`);
});