通过 Node.js 搭配 Nodemailer 实现邮箱验证码发送
目录
一、整体思路
二、环境准备
三、代码详细步骤
1. 引入模块并初始化
2. 配置 Nodemailer 邮件服务
3. 定义发送验证码接口
4. 定义校验验证码接口
5. 启动服务器
四、补充说明
一、整体思路
-
接收邮箱地址请求 →
用户在前端填写邮箱,发送到后端接口(如/send-code
)。 -
后端生成验证码并缓存 →
后端生成随机验证码,存入 Redis 或内存(带过期时间)。 -
使用 Nodemailer 发邮件 →
配置邮箱服务器,用 Nodemailer 发送邮件,将验证码发到用户邮箱。 -
用户提交验证码校验 →
后端验证用户提交的验证码是否正确并且未过期。
二、环境准备
首先,需要安装必要的 Node.js 包:
npm install express nodemailer redis
-
express
:搭建 HTTP 服务器。 -
nodemailer
:发送邮件。 -
redis
:存验证码,设置过期时间。
三、代码详细步骤
1. 引入模块并初始化
const express = require('express');
const nodemailer = require('nodemailer');
const redis = require('redis');
const { promisify } = require('util');const app = express();
app.use(express.json());// 连接 Redis
const redisClient = redis.createClient();
const setAsync = promisify(redisClient.set).bind(redisClient);
const getAsync = promisify(redisClient.get).bind(redisClient);
2. 配置 Nodemailer 邮件服务
可以选择 SMTP 邮件服务器,比如:
-
Gmail
-
QQ邮箱
-
阿里云邮件推送
-
SendGrid
示例(以 QQ 邮箱为例):
const transporter = nodemailer.createTransport({host: 'smtp.qq.com',port: 465,secure: true, // true for 465, false for other portsauth: {user: '你的QQ邮箱@qq.com', // 发送方邮箱pass: '授权码' // 不是密码!是SMTP授权码!}
});
注意:QQ邮箱需要开启 SMTP 服务,并拿到一个授权码,不能用普通密码。
3. 定义发送验证码接口
app.post('/send-code', async (req, res) => {const { email } = req.body;if (!email) {return res.status(400).send({ error: 'Email is required' });}// 生成6位随机验证码const code = Math.floor(100000 + Math.random() * 900000).toString();// 保存到 Redis,设置过期时间5分钟await setAsync(`verify:${email}`, code, 'EX', 300);// 发送邮件const mailOptions = {from: '你的QQ邮箱@qq.com',to: email,subject: '您的验证码',text: `您的验证码是 ${code},有效期5分钟,请勿泄露。`};try {await transporter.sendMail(mailOptions);res.send({ message: '验证码发送成功' });} catch (err) {console.error('发送失败', err);res.status(500).send({ error: '验证码发送失败' });}
});
4. 定义校验验证码接口
app.post('/verify-code', async (req, res) => {const { email, code } = req.body;if (!email || !code) {return res.status(400).send({ error: 'Email and code are required' });}const savedCode = await getAsync(`verify:${email}`);if (!savedCode) {return res.status(400).send({ error: '验证码已过期或不存在' });}if (savedCode === code) {return res.send({ message: '验证成功' });} else {return res.status(400).send({ error: '验证码错误' });}
});
5. 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {console.log(`服务器运行在 http://localhost:${PORT}`);
});
四、补充说明
-
限流控制(防止恶意刷验证码)
-
比如一个邮箱1分钟内只能发送一次。
-
可以在 Redis 里加一层锁或者计数器。
-
-
验证码加密
-
验证码可以使用简单加密(例如哈希存储),提高安全性。
-
-
防止暴力破解
-
连续错误输验证码次数超过3次,锁定一段时间。
-
-
生产环境发送 HTML 格式邮件
-
邮件正文可以用 HTML 格式美化,比如加品牌 Logo、验证码提示等。
-
-
异步处理发送邮件
-
邮件发送可以做成异步,或者通过消息队列(如 RabbitMQ)解耦,提高响应速度。
-