ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

uni-id-pages 邮箱验证码配置实战:SMTP、授权码与避坑指南

uni-id-pages 邮箱验证码配置实战:SMTP、授权码与避坑指南 uni-id-pages 配置 email 这件事我前阵子在新项目里又完整走了一遍。说实话uni-id-pages 这套用户体系已经很成熟了但邮件验证码这块的配置一直比较分散官方文档有、插件市场示例也有可真到自己上手时还是会遇到“配置了但发不出去”“验证码一直提示错误”“测试邮箱收不到邮件”这种问题。这篇文章把我这次的实操过程、配置细节、以及踩过的坑完整记录下来给准备在 uni-id-pages 里接邮箱验证码登录/注册/找回密码的朋友做一个可以直接抄的参考。1. uni-id-pages 里邮箱验证码到底用在哪先说清楚 uni-id-pages 是什么。它是 uni-app 生态里的一个用户登录/注册/找回密码的页面插件配合 uniCloud 云服务端的 uni-id-co 云对象使用提供账号密码、短信验证码、邮箱验证码、微信一键登录、Apple 登录等能力。它不是一个简单的页面而是一整套用户认证身份方案的前端部分后端逻辑在 uni-id-co 云对象里。1.1 这套东西的运行逻辑我在项目里用 uni-id-pages最核心的一个原因就是它把前端页面、云对象、uni-id 公共模块这三层全打通了。前端页面负责收集用户输入、调起验证码发送和登录请求uni-id-co 负责真正执行发邮件、校验验证码、创建账号、返回 tokenuni-id 公共模块则负责通用的用户表结构和权限校验。所以配置 email 不只是在前端改改页面还需要把云端的配置、公共模块的参数一起改到位。整个邮箱验证码的调用链路是这样的用户在 uni-id-pages 的登录页选择邮箱验证码登录输入邮箱后点击“获取验证码”前端调用云对象 uni-id-co 的 sendEmailCode 方法云对象校验邮箱格式后使用配置好的 SMTP 服务把邮件发出去邮件里带上随机验证码用户收到验证码后在表单里输入前端再调云对象的 login 方法场景里是 email 登录云对象核对验证码和邮箱是否匹配匹配则创建或登录账号返回 token 给前端存起来。这套链路本身不复杂但每一环都可能出问题。SMTP 配置错了邮件发不出验证码发送频率限制没配好用户会抱怨收不到前端登录类型没开启页面上连邮箱登录入口都没有。所以配置 email 前最好先完整理解这套链路不然出问题了会像无头苍蝇一样乱试。1.2 为什么邮件验证码比短信更适合某些场景我在多个项目里做过对比。短信验证码适合面向 C 端大众用户的移动端产品用户手机号是天然的账号体系但短信通道是要按条付费的而且国内短信签名、模板审核都比较麻烦个人开发者很难快速接入。邮件验证码的优势在于成本低、接入快。只要有一个能发 SMTP 的邮箱个人开发者就能立刻用起来不需要申请签名、不需要等审核而且邮件内容可以做得更丰富附上品牌信息、用户协议链接看起来比短信正式很多。缺点也很明显邮件有延迟、可能进垃圾箱、手机端查看不如短信方便。所以我的判断是如果你的产品是开发者工具、SaaS 后台、B 端服务或者做的是海外用户email 登录是首选如果是面向国内 C 端的娱乐类 App短信仍然更直接。uni-id-pages 的好处是两种方式可以并存配置 email 不影响短信、微信等其他登录方式这也是我选择用它而不是自己写用户系统的原因。2. 先把邮件服务商和外发参数选好很多朋友一上来就直接在配置里填邮箱和密码这是最常见的错误。uni-id-co 发邮件走的是 SMTP 协议你需要的是一个支持 SMTP 外发的邮箱或邮件服务而不是简单的邮箱地址和登录密码。服务商选不对后面全是坑。2.1 各家 SMTP 服务对比我把常用的几类邮件服务商放在一起对比过实际体验差别很大服务商SMTP 地址端口获取密钥方式适合场景成本QQ 邮箱smtp.qq.com465/587开启 SMTP 服务后生成授权码个人项目、测试免费163 邮箱smtp.163.com465/994开启 SMTP 后设置授权码个人项目、测试免费阿里云邮件推送smtp.qiye.aliyun.com 等465/80控制台配置发信域名正式业务、大量发送按量计费Resendsmtp.resend.com465/587API Key 或 SMTP 密码海外用户、开发者工具免费额度SendGridsmtp.sendgrid.net465/587API Key海外用户、大量发送免费额度如果你是个人开发者、只是想快速把邮箱验证码跑通我用 QQ 邮箱或者 163 邮箱就够了流程最短不涉及域名备案和 DNS 解析。但如果项目要上线、面向真实用户我不建议用个人免费邮箱去发验证码会有几个问题单日发信数量限制、邮件容易被判垃圾邮件、发信域名和产品域名不一致导致 SPF/DKIM 认证过不了。这时候应该用阿里云邮件推送或者 Resend 这类专门的服务配置发信域名和 DNS 记录送达率会高很多。我这次项目里因为要对接国内外用户国内环境我用的是 QQ 邮箱 SMTP 做快速验证验证通过后把发信能力切到了 Resend两者在 uni-id-co 里的配置格式基本一致切换成本很低。2.2 授权码不是密码这步错了全白搭QQ 邮箱和 163 邮箱的坑在同一个地方SMTP 认证需要的不是你的邮箱登录密码而是“授权码”。授权码是你在邮箱设置里开启 SMTP 服务后平台生成的一串十六位左右的长字符串。如果你在 uni-id-co 的配置里填了登录密码SMTP 服务器会返回认证失败邮件绝对发不出去。以 QQ 邮箱为例获取授权码的路径是网页版 QQ 邮箱 → 设置 → 账号与安全 → 安全设置 → 开启 SMTP 服务开启后会引导你发送一条短信验证验证通过后就会生成授权码。这个授权码只在开启时看到一次建议立刻复制保存到自己的密码管理器里。163 邮箱的路径类似网页版 163 邮箱 → 设置 → POP3/SMTP/IMAP → 开启 SMTP 服务 → 设置授权码。需要注意授权码和登录密码是两回事即使你知道邮箱密码没有授权码也无法走 SMTP。另外有些邮箱服务商在你异地登录、更换设备后会重置授权码如果你昨天配置还好的、今天突然发不出邮件先去检查授权码是否失效。3. 服务端 uni-id-co 的邮箱配置实操配置分两层云对象 uni-id-co 的配置文件以及 uniCloud 环境变量/公共模块的配置。这里我把关键操作一步步写清楚。3.1 找到配置文件在 uniCloud 项目里uni-id-co 云对象的核心配置实际上在配套的 uni-id 公共模块中。目录结构大致是这样uniCloud-aliyun/cloudfunctions/ uni-id-co/ index.js config.json package.json common/ uni-id/ config.json --- 这里存放 uni-id 的配置 package.json如果你的项目是从插件市场直接导入 uni-id-pages 的通常会自动带上 uni-id-co 云对象和 uni-id 公共模块。如果还没有需要在插件市场搜索并添加这两个依赖执行上传部署后才能生效。我把 uni-id 公共模块里的 config.json 视为整个用户体系的核心配置邮件、短信、token 过期时间、密码规则、验证码规则都在这里控制。3.2 核心配置项拆解我这次用的 uni-id 配置文件里邮件相关的部分如下{ email: { smtp: { host: smtp.qq.com, port: 465, secure: true, user: your_emailqq.com, pass: your_authorization_code }, sendCode: { scene: { login: { template: 您的登录验证码为 ${code}请在 ${expiresIn} 分钟内填写。 }, register: { template: 您的注册验证码为 ${code}请在 ${expiresIn} 分钟内填写。 }, reset-password: { template: 您正在重置密码验证码为 ${code}请在 ${expiresIn} 分钟内填写。 }, bind: { template: 您正在绑定邮箱验证码为 ${code}请在 ${expiresIn} 分钟内填写。 }, unbind: { template: 您正在解绑邮箱验证码为 ${code}请在 ${expiresIn} 分钟内填写。 } }, codeExpiresIn: 600, sendInterval: 60 } } }这里每个配置项都有意义smtp.host和smtp.port对应你选择的邮件服务商的 SMTP 地址和端口。QQ 邮箱是 smtp.qq.com:465Resend 是 smtp.resend.com:465。端口用 465 是 SSL 加密连接587 是 STARTTLS两者都能用但 465 在 uni-id-co 里表现更稳我在项目里用的就是 465。smtp.securetrue 表示使用 SSL 加密连接和 465 端口是一对。如果端口写成 587建议 secure 用 false 或者看服务商要求。这个参数写错了会连接失败报错信息通常是 TLS 握手失败。smtp.user和smtp.passuser 是完整邮箱地址pass 是授权码/API Key。这里不是密码再次强调。sendCode.scene不同业务场景下的邮件模板模板里的${code}和${expiresIn}会被 uni-id-co 自动替换成真实验证码和有效分钟数。你可以调整文案以适应产品的语气。codeExpiresIn验证码有效期单位秒。我设的是 600也就是 10 分钟。太短用户来不及收邮件太长有安全风险。sendInterval发送间隔单位秒。60 表示同一个邮箱 60 秒内只能发一次验证码防止用户手抖反复点击、也防止接口被刷。3.3 部署与日志观察配置文件改好后记住一件事一定要把 uni-id 公共模块重新上传部署到云服务空间uni-id-co 也要同步上传否则配置不生效。这个坑我踩过本地改了配置但忘了在 HBuilderX 里右键上传公共模块结果线上还是旧配置白白排查了一晚上。部署完成后建议先在 HBuilderX 运行到浏览器打开 uni-id-pages 的登录页切换到邮箱验证码登录输入你的测试邮箱点击发送验证码。这时候打开 uniCloud 控制台的云函数日志搜索 uni-id-co 的调用记录能看到 sendEmailCode 的执行结果。如果配置正确返回码是 0日志里会有一条类似 “发送邮件成功” 的记录如果配置错误日志里会有返回码 500 或者 SMTP 的错误信息。云函数日志是排查邮件问题的第一现场。很多问题在页面上看不到细节但在日志里会直白地告诉你认证失败、连接超时还是端口不通。我每次配置完都会习惯性看一轮日志确认 SMTP 连接成功后才继续往下走。4. 前端 uni-id-pages 开启邮箱登录入口服务端配好了前端的入口也得打开。uni-id-pages 默认可能只显示账号密码登录需要手动把 email 登录类型加进去。4.1 登录类型配置uni-id-pages 插件在项目里会有一个配置文件通常是uni-id-pages/config.js或uni-id-pages.config.js位置可能是页面目录下的 config.js也可能在项目的 config 目录里。我这次项目里的配置大致长这样// uni-id-pages/config.js export default { loginTypes: [email, password], // ... }loginTypes数组控制显示哪些登录方式可选项包括password、sms、email、univerify、apple等。把email加进去后登录页就会出现邮箱验证码登录的标签或图标。注意email登录和password登录是两套逻辑前者只靠验证码登录不需要用户设置密码后者是账号密码登录。如果你的项目还需要用户能在后台绑定邮箱记得把邮箱验证码场景里的bind和unbind也配置上否则绑定邮箱功能会报“验证码场景不存在”一类的错误。4.2 页面表单与验证码按钮uni-id-pages 内置的页面已经实现了邮箱输入框和“获取验证码”按钮的逻辑不需要你重新写。它会自动从配置里读取邮箱场景点击“获取验证码”后调 uni-id-co 的 sendEmailCode并按照sendInterval做倒计时。有一点要留意uni-id-pages 页面上显示的登录方式优先级和你loginTypes数组的顺序一致。如果你把email放第一个默认展示的就是邮箱登录表单。我建议产品上如果主推邮箱就把 email 放最前密码登录放第二个这样对新用户更友好。如果项目不是直接用 uni-id-pages 的完整页面而是自己写的自定义登录表单也可以直接掉云对象方法核心调用是这样const uniIdCo uniCloud.importObject(uni-id-co) // 发送验证码 await uniIdCo.sendEmailCode({ email: userexample.com, scene: login }) // 邮箱验证码登录 const res await uniIdCo.login({ email: userexample.com, code: 123456, scene: login })这个方法调用方式在任何自定义页面上都可以用所以哪怕你不用 uni-id-pages 自带的页面只参考它的工程结构也能自由扩展。5. 用 moakt 临时邮箱把整套链路测通测试邮箱验证码最怕什么一收不到、二收不到还找不到原因。以前我测试时用的是自己的 QQ 邮箱问题是每次测试都要切到邮箱客户端去收信验证码时效 10 分钟来回折腾效率很低。这次我用了临时邮箱工具 moakt整个过程顺畅了很多。5.1 为什么要用临时邮箱moaktmoakt.com是一个临时邮箱服务打开网站会自动生成一个随机邮箱地址比如abc123moakt.com你不需要注册、不需要密码页面会实时显示收到的邮件。这个地址可以直接当测试收件邮箱使用。用它来测 uni-id-pages 的邮箱验证码有几个好处一是即开即用输入邮箱地址后直接就能在页面上等邮件不用切换 App二是不需要自己真的有一个邮箱来收信尤其适合团队里需要多人联调时每个人都开一个临时地址互不干扰三是临时邮箱收到邮件后可以直接复制验证码效率高很多。注意moakt 这类临时邮箱只适合开发测试千万不能给真实用户用。生产环境的用户收信一定要用真正可长期访问的邮箱服务否则验证码发出去用户根本收不到账号也登不进去。5.2 本地测试的完整过程我在本地完整的测试流程是打开 moakt.com页面会自动分配一个临时邮箱地址我复制下来一般是xxxmoakt.com这种格式。在 HBuilderX 里运行 uni-app 项目到浏览器打开 uni-id-pages 登录页切换到“邮箱验证码登录”把刚才的临时邮箱粘贴进去。点击“获取验证码”等 1-3 秒。正常情况下按钮进入倒计时表示请求已经发出。回到 moakt.com 页面如果配置正确收件箱里很快会出现一封来自你配置发件邮箱的邮件主题一般是“验证码”或你自定义的主题。点开邮件能看到验证码数字。把验证码填回登录表单点击登录正常情况下会跳回首页uni-id 的用户表里也会新增一条用户记录。我实际测试时QQ 邮箱的 SMTP 发到 moakt 的邮箱大概需要 2-5 秒偶尔会等十几秒这是正常的。如果超过 1 分钟还没收到基本可以判断是配置问题或者邮件被服务商拦截了直接去云函数日志里看有没有报错。测试完以后我建议把 moakt.com 这种临时邮箱彻底从生产环境的代码和文档里清理掉不然哪天不小心把服务配置成发往临时邮箱用户验证码全部丢失那就是事故了。6. 高频问题排查实录配置过程里我踩了不少坑也帮朋友排查过类似问题把最容易被卡住的点整理成一个速查表按优先级排列。6.1 收不到验证码这是遇到最多的场景现象是前端提示“发送成功”但邮箱里就是没有邮件。这分两种可能可能原因判断方法解决办法SMTP 认证失败云函数日志里有 SMTP 535 或 Authentication 错误检查smtp.pass是否填了授权码而不是登录密码邮件进垃圾箱看垃圾邮件文件夹邮件内容避免诱导性词汇配置发信域名 SPF/DKIM服务商延迟等待 1 分钟以上检查发信日志部分服务商高峰期有延迟邮箱写错用户在输入框里多打了空格在业务层做邮箱格式和去空格处理如果是“发送成功”但收不到我建议第一时间看云函数日志确认 SMTP 是否真的连接成功。日志里显示“发送邮件成功”但邮件没到大概率是垃圾箱或者延迟日志里显示错误就按错误信息去修。6.2 SMTP 连接失败 / 端口不通连接失败常见的报错有connect ETIMEDOUT、socket hang up、TLS handshake failed。这类问题大多出在端口和加密方式上。QQ 邮箱的 465 端口在 uniCloud 阿里云环境里是可以通的但有些邮件服务商的 465 端口对境外服务器不一定开放。如果你用的是阿里云邮件推送建议直接按服务商文档里的端口和加密方式配置不要照搬 QQ 邮箱的参数。ETIMEDOUT通常是网络不通先确认服务商的防火墙策略TLS handshake failed通常是secure参数不对465 对应 true,587 对应 false 或 STARTTLS 模式。把端口和 secure 的搭配关系对照一下就能解决大部分连接问题。6.3 验证码校验报错另外一种情况,验证码收到了,但登录时报“验证码错误”或者“验证码已过期”。我排查下来常见原因有两个。第一个原因是场景不一致。发送验证码时用的 scene 是register登录时调用的 scene 是loginuni-id-co 对验证码是按邮箱场景时间戳组合校验的场景对不上会直接判无效。前端页面一般不会自己搞混但如果你在自定义表单里先后调 sendEmailCode 和 login务必保证两个 scene 一致。第二个原因是验证码有效期太短。codeExpiresIn如果设成 1202分钟用户还没收到邮件验证码就过期了。建议至少设 300 秒我用 600 秒是比较从容的。还有一个小坑有些邮件服务商或者客户端会解析邮件里的数字后被格式化用户复制验证码时可能带进空格或换行。前端提交前最好做一次trim()或者校验时忽略空白字符。我在自建表单时遇到过用户从邮件里复制验证码多了个空格结果一直报错去掉空格就成功了。6.4 邮件进垃圾箱即使技术配置全对邮件进垃圾箱也是可能发生的这直接决定用户体验。个人邮箱发验证码本来就很容易被判垃圾邮件因为你的发信 IP、域名信誉、邮件内容都会影响算法的判断。几个改变送达率的有效做法一是邮件模板里不要出现“免费”“中奖”“点击链接”这类高风险的词验证码邮件文案保持简洁、正式二是发件人名称和邮箱域名尽量和产品品牌一致不要整封邮件都是乱码或者英文夹杂拼音三是在正式环境用专业邮件服务并配置 SPF、DKIM 记录这会显著提高送达率四是邮件里把用户的完整邮箱写进正文例如“这封邮件发送给 userexample.com”很多垃圾邮件过滤规则会识别这种为正常邮件。我测试期间用 QQ 邮箱发到 moakt 临时邮箱大多数情况能正常收到但偶尔也会进垃圾箱这属于测试链路可以接受的范围内。真要上线我会优先用专业发送服务而不是纠结于免费邮箱的送达率。6.5 配置已改但页面无变化还有一类问题不在邮件本身而是配置改了之后不起作用。现象是 uni-id-pages 登录页还是老样子或者验证码发送行为没有任何变化。这一般是缓存问题。uni-id-pages 是前端页面插件部分配置会被编译进前端代码需要重新运行项目才能生效云端的 uni-id-co 配置则必须重新上传部署公共模块。我每次改完配置都会做三个动作重新运行前端、重新上传 uni-id-co、在云函数测试里手动执行一次 sendEmailCode 验证配置确保改动真正生效。如果项目里有自建的数据库表结构还要确认 uni-id 的用户表已经初始化过。新服务空间首次使用 uni-id-pages 时如果没跑初始化脚本用户表不存在登录会报错。这个表结构初始化通常在 uniCloud 控制台的云数据库里通过执行 uni-id 配套的 db_init.json 或迁移脚本来完成不同的项目版本初始化的方式略有区别但官方文档和插件说明里都有照着做一遍就不容易出错。7. 上线前我还想再说几个细节这一路配置完、测试通过并不代表就完事了。有几个细节我在多个项目里反复验证过建议上线前一定过一遍验证码发送必须有频率限制不能只依赖前端倒计时。sendInterval这个参数就是服务端的硬限制一定要保留默认值不要为了测试方便改成 0否则接口很容易被脚本刷单日发信额度也会很快耗尽。邮件模板要支持多语言。uni-id-pages 面向的可能是海外用户默认中文模板在国际化场景里不够用。可以在 uni-id 公共模块里维护不同语言版本的模板或者在调用 sendEmailCode 时传入语言参数让云对象动态选择模板。我这次项目的用户以中文为主但我也预留了英文模板避免以后接入海外版本时又要大改。要关注发信失败率的监控。邮件的送达率不会永远是 100%尤其用免费邮箱服务时可能某天发信额度耗尽、服务商临时限流用户那边就收不到验证码了。建议在云函数日志里建立一个简单的告警比如发信失败连续超过一定数量就提醒。uniCloud 的日志服务和告警功能可以做到这一点成本很低但对用户体验的提升很明显。还要在代码里处理好异常分支。比如验证码发送成功但用户长时间没收到邮件页面应该给出“没收到重新发送”的按钮同时提示检查垃圾箱。不要只弹一个冷冰冰的“发送成功”提示就结束要给用户操作空间。uni-id-pages 内置页面有些交互已经处理了但自定义页面就需要自己补。最后说一下我个人的实际体会。uni-id-pages 配置 email 的事单纯从技术实现上难度不高它真正的价值在于让你在很短的时间内获得一套完整的、有前后端和数据库支撑的用户邮箱验证码体系。相比从零手写邮件发送、验证码存储、用户表设计用这套现成方案可以省下不少重复工作把精力集中在业务逻辑和用户体验上。但“省事”的前提是你得理解它的配置层次前端页面开入口、服务端云对象管逻辑、公共模块存配置。三层各改各的缺一层都会出问题。不要一上来就盲目改配置先搞清楚每一层分别管什么再动手排查问题时也会更快定位到环节。如果你正准备在自己的 uni-app 项目里接入邮箱验证码照着这篇文章的步骤走一遍大概率能在一小时内跑通。卡住了就去看云函数日志日志不会说谎。祝顺利。
返回列表