Cypress登录测试:如何从关联邮箱提取OTP完成登录
登录测试中邮箱OTP提取实现方案
项目文件夹结构
login-test-otp/ ├── config/ │ └── Config.js # 全局配置文件 ├── utils/ │ └── emailHandler.js # 邮件操作核心逻辑 ├── tests/ │ └── login.test.js # 登录测试用例 ├── package.json └── package-lock.json
Config.js 配置
集中管理邮箱服务、账号和OTP匹配规则,方便后续调整:
module.exports = { email: { user: 'your-test-email@example.com', // 接收OTP的测试邮箱账号 password: 'your-email-app-password', // 邮箱应用专用密码(优先用这个,别用主密码) host: 'imap.example.com', // IMAP服务器地址,比如Gmail是imap.gmail.com port: 993, // IMAP加密端口,常规是993 tls: true, markSeen: false // 是否标记邮件为已读,测试阶段建议设为false }, otp: { regex: /Your OTP code is: (\d{6})/, // 匹配6位数字OTP的正则,根据实际邮件内容修改 timeout: 30000 // 等待邮件的超时时间(毫秒) } };
邮件操作核心代码(utils/emailHandler.js)
用imap库连接邮箱,mailparser解析邮件内容,实现最新OTP提取逻辑:
const Imap = require('imap'); const { simpleParser } = require('mailparser'); const config = require('../config/Config'); // 初始化IMAP客户端 const imap = new Imap(config.email); // 连接邮箱并提取最新OTP async function getLatestOtp() { return new Promise((resolve, reject) => { let otp = null; imap.once('ready', () => { imap.openBox('INBOX', false, (err, box) => { if (err) return reject(err); // 按主题+未读筛选邮件,精准定位OTP邮件 const searchCriteria = ['UNSEEN', ['SUBJECT', 'Login Verification OTP']]; const fetchOptions = { bodies: ['TEXT'], markSeen: config.email.markSeen }; imap.search(searchCriteria, (err, results) => { if (err) return reject(err); if (results.length === 0) { return reject(new Error('未找到OTP邮件')); } // 获取最新的一封匹配邮件 const fetch = imap.fetch(results[results.length - 1], fetchOptions); fetch.on('message', (msg) => { msg.on('body', (stream) => { simpleParser(stream, async (err, parsed) => { if (err) return reject(err); // 从邮件正文匹配OTP const match = parsed.text.match(config.otp.regex); if (match) { otp = match[1]; imap.end(); resolve(otp); } else { reject(new Error('邮件中未找到OTP')); } }); }); }); fetch.once('error', (err) => reject(err)); fetch.once('end', () => { if (!otp) reject(new Error('OTP提取失败')); imap.end(); }); }); }); }); imap.once('error', (err) => reject(err)); imap.once('end', () => console.log('IMAP连接已关闭')); imap.connect(); }); } // 带超时限制的OTP获取函数 async function getOtpWithTimeout() { const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error('OTP获取超时')), config.otp.timeout); }); return Promise.race([getLatestOtp(), timeoutPromise]); } module.exports = { getOtpWithTimeout };
登录测试用例示例(tests/login.test.js)
在测试流程中调用邮件工具获取OTP,完成登录验证:
const { getOtpWithTimeout } = require('../utils/emailHandler'); // 这里以Jest测试框架为例,替换成你实际使用的测试工具 test('使用OTP完成登录', async () => { // 1. 触发登录请求,触发OTP发送 await triggerLoginRequest('test-user@example.com'); // 你的登录触发逻辑 // 2. 从邮箱获取OTP const otp = await getOtpWithTimeout(); expect(otp).toHaveLength(6); // 验证OTP格式 // 3. 提交OTP完成登录 const loginResult = await submitLoginWithOtp('test-user@example.com', otp); expect(loginResult.success).toBe(true); });
依赖安装
需要安装两个核心依赖:
npm install imap mailparser --save-dev
注意事项
- 如果用Gmail,需要开启IMAP访问权限并生成应用专用密码(开启两步验证后才能生成)
- 正则表达式要根据实际邮件里的OTP展示格式调整,比如OTP是4位就改成
\d{4} - 测试用邮箱建议用专门的测试账号,避免干扰个人邮件
内容的提问来源于stack exchange,提问作者Shayentan
相关产品推荐
相关产品推荐

