当前位置: 首页 > news >正文

uni-id-pages配置email

uniapp+unicloud+uni-id-pages 配置邮箱教程

// -- 测试代码// await require('../../lib/utils/verify-code')// .setEmailVerifyCode.call(this, {// email,// code: '123456',// expiresIn: 180,// scene// })// return {// errCode: 'uni-id-invalid-mail-template',// errMsg: `已启动测试模式,直接使用:123456作为邮箱验证码即可。\n如果是正式项目,需自行实现发送邮件的相关功能`// }// -- 测试代码//发送邮件--需自行实现awaitrequire('../../lib/utils/verify-code').setEmailVerifyCode.call(this,{email,code:'',expiresIn:180,scene})return{errCode:0,errMsg:"邮箱验证码已经生成"}// 发送邮件
{"name":"email","dependencies":{"nodemailer":"^8.0.0"},"extensions":{"uni-cloud-jql":{}},"cloudfunction-config":{"runtime":"Nodejs18"}}
// 云对象教程: https://uniapp.dcloud.net.cn/uniCloud/cloud-obj// jsdoc语法提示教程:https://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/129// 导入发送邮件的依赖模块constnodemailer=require('nodemailer');// 谁发送邮件,改为自己的要发送邮件的邮箱constFROM_EMAIL="your_email";// 配置发送类型consttransporter=nodemailer.createTransport({host:"smtp.163.com",//邮箱服务器 这里我用的163邮箱 smtp.qq.com smtp.163.comport:465,//邮箱使用端口secure:true,//是否使用默认的465端口auth:{user:FROM_EMAIL,// 自己的授权密钥,去自己邮箱获取pass:"**********"}});// 编写发送邮件的方法functionsendMail(option){returnnewPromise((resolve,reject)=>{nodemailer.createTestAccount((err)=>{if(err)returnreject("创建失败");transporter.sendMail(option,(error)=>{// console.log("失败的原因:",error);if(error)returnreject("发送失败");resolve({code:200,msg:"发送成功"});});})})}// 获取集合的引用constdb=uniCloud.databaseForJQL();constdbCmd=db.command// 获取 `opendb-verify-codes` 集合的引用constverifyCodeCollection=db.collection('opendb-verify-codes');module.exports={_before:function(){// 通用预处理器// 删除该邮箱的所有验证码记录verifyCodeCollection.where({expired_date:dbCmd.lt(Date.now())}).remove();},/** * sendEmail方法描述 * @param {string} email 邮箱号 * @returns {object} 返回值描述 */asyncsendEmail(email){// 给谁发送邮件(用户邮箱)constTO_EMAIL=email;// 验证码constverifyCode=awaitverifyCodeCollection.where({email,expired_date:dbCmd.gt(Date.now())}).get()// console.warn("verifyCode", verifyCode)if(verifyCode.data.length>0){// 以下发送邮件的信息constemail_HTML={title:`测试邮箱---邮箱验证码`,body:`<h1>您好:</h1> <p style="font-size: 18px;color:#000;"> 您的验证码为: <span style="font-size: 16px;color:#f00;"><b>${verifyCode.data[0].code}</b>,</span> <p>您当前正在测试邮箱账号,验证码告知他人将会导致数据信息被盗,请勿泄露!</p> </p> <p style="font-size: 1.5rem;color:#999;">60秒内有效</p>`}letoption={from:FROM_EMAIL,// 发件人地址to:TO_EMAIL,// 收件人地址,多个收件人可以使用逗号分隔subject:email_HTML.title,// 邮件标题html:email_HTML.body// 邮件内容}// 执行发送邮件的方法returnawaitsendMail(option);}else{returnnewPromise((resolve,reject)=>reject({code:400,msg:"验证码已过期"}))}}}
<!-- 邮箱验证码注册 --> <template> <view class="uni-content"> <match-media :min-width="690"> <view class="login-logo"> <image :src="logo"></image> </view> <!-- 顶部文字 --> <text class="title title-box">邮箱验证码注册</text> </match-media> <uni-forms ref="form" :value="formData" :rules="rules" validate-trigger="submit" err-show-type="toast"> <uni-forms-item name="email" required> <uni-easyinput :inputBorder="false" :focus="focusEmail" @blur="focusEmail = false" class="input-box" placeholder="请输入邮箱" v-model="formData.email" trim="both" /> </uni-forms-item> <uni-forms-item name="nickname"> <uni-easyinput :inputBorder="false" :focus="focusNickname" @blur="focusNickname = false" class="input-box" placeholder="请输入用户昵称" v-model="formData.nickname" trim="both" /> </uni-forms-item> <uni-forms-item name="password" v-model="formData.password" required> <uni-easyinput :inputBorder="false" :focus="focusPassword" @blur="focusPassword = false" class="input-box" maxlength="20" :placeholder="'请输入' + (config.passwordStrength == 'weak'?'6':'8') + '-16位密码'" type="password" v-model="formData.password" trim="both" /> </uni-forms-item> <uni-forms-item name="password2" v-model="formData.password2" required> <uni-easyinput :inputBorder="false" :focus="focusPassword2" @blur="focusPassword2 =false" class="input-box" placeholder="再次输入密码" maxlength="20" type="password" v-model="formData.password2" trim="both" /> </uni-forms-item> <uni-forms-item name="code" > <uni-id-pages-email-form ref="shortCode" :email="formData.email" type="register" :focusCaptchaInput="true" v-model="formData.code" > </uni-id-pages-email-form> </uni-forms-item> <uni-id-pages-agreements scope="register" ref="agreements" ></uni-id-pages-agreements> <button class="uni-btn" type="primary" @click="submit">注册</button> <button @click="navigateBack" class="register-back">返回</button> <match-media :min-width="690"> <view class="link-box"> <text class="link" @click="toLogin">已有账号?点此登录</text> </view> </match-media> </uni-forms> </view> </template> <script> import rules from './validator.js'; import mixin from '@/uni_modules/uni-id-pages/common/login-page.mixin.js'; import config from '@/uni_modules/uni-id-pages/config.js' import passwordMod from '@/uni_modules/uni-id-pages/common/password.js' const uniIdCo = uniCloud.importObject("uni-id-co") export default { mixins: [mixin], data() { return { formData: { email: "", nickname: "", password: "", password2: "", code: "" }, rules: { email: { rules: [{ required: true, errorMessage: '请输入邮箱', },{ format:'email', errorMessage: '邮箱格式不正确', } ] }, nickname: { rules: [{ minLength: 3, maxLength: 32, errorMessage: '昵称长度在 {minLength} 到 {maxLength} 个字符', }, { validateFunction: function(rule, value, data, callback) { // console.log(value); if (/^1\d{10}$/.test(value) || /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/.test(value)) { callback('昵称不能是:手机号或邮箱') }; if (/^\d+$/.test(value)) { callback('昵称不能为纯数字') }; if(/[\u4E00-\u9FA5\uF900-\uFA2D]{1,}/.test(value)){ callback('昵称不能包含中文') } return true } } ], label: "昵称" }, ...passwordMod.getPwdRules(), code: { rules: [{ required: true, errorMessage: '请输入邮箱验证码', }, { pattern: /^.{6}$/, errorMessage: '邮箱验证码不正确', } ] } }, focusEmail:false, focusNickname:false, focusPassword:false, focusPassword2:false, logo: "/static/logo.png" } }, onReady() { this.$refs.form.setRules(this.rules) }, onShow() { // #ifdef H5 document.onkeydown = event => { var e = event || window.event; if (e && e.keyCode == 13) { //回车键的键值为13 this.submit() } }; // #endif }, methods: { /** * 触发表单提交 */ submit() { this.$refs.form.validate().then((res) => { if (this.needAgreements && !this.agree) { return this.$refs.agreements.popup(()=>{ this.submitForm(res) }) } this.submitForm(res) }).catch((errors) => { let key = errors[0].key key = key.replace(key[0], key[0].toUpperCase()) // console.log(key); this['focus'+key] = true }) }, submitForm(params) { uniIdCo.registerUserByEmail(this.formData).then(e => { // console.log(e); uni.navigateTo({ url: '/uni_modules/uni-id-pages/pages/login/login-withpwd', complete: (e) => { // console.log(e); } }) }) .catch(e => { // console.log(e); console.log(e.message); }) }, navigateBack() { uni.navigateBack() }, toLogin() { uni.navigateTo({ url: '/uni_modules/uni-id-pages/pages/login/login-withpwd' }) } } } </script> <style lang="scss"> @import "@/uni_modules/uni-id-pages/common/login-page.scss"; @media screen and (max-width: 690px) { .uni-content{ margin-top: 15px; } } @media screen and (min-width: 690px) { .uni-content{ padding: 30px 40px; max-height: 650px; } .link-box { /* #ifndef APP-NVUE */ display: flex; /* #endif */ flex-direction: row; justify-content: space-between; margin-top: 10px; } .link { font-size: 12px; } } .uni-content ::v-deep .uni-forms-item__label { position: absolute; left: -15px; } button { margin-top: 15px; } </style>
constuniIdCo=uniCloud.importObject("uni-id-co",{customUI:true})// 导出email对象constemail=uniCloud.importObject("email")uniIdCo.sendEmailCode({"email":this.email,"scene":this.type,"captcha":this.captcha}).then(result=>{// 自己修改的代码email.sendEmail(this.email).then(result=>{uni.showToast({title:"邮箱验证码发送成功",icon:'none',duration:3000});}).catch(e=>{uni.showToast({title:"邮箱验证码发送失败",icon:'none',duration:3000});})// 自己修改的代码this.reverseNumber=Number(this.count);this.getCode();}).catch(e=>{if(e.code=="uni-id-invalid-mail-template"){this.modelValue="123456"uni.showToast({title:'已启动测试模式,详情【控制台信息】',icon:'none',duration:3000});console.warn(e.message);}else{this.getImageCaptcha()this.captcha=""uni.showToast({title:'验证码输入错误,请稍后重试!',icon:'none',duration:3000});}})},
<!-- 账号密码登录页 --> <template> <view class="uni-content"> <view class="login-logo"> <image :src="logo"></image> </view> <!-- 顶部文字 --> <text class="title title-box">邮箱登录</text> <uni-forms> <uni-forms-item name="username"> <uni-easyinput :focus="focusUsername" @blur="focusUsername = false" class="input-box" :inputBorder="false" v-model="username" placeholder="邮箱" trim="all" /> </uni-forms-item> <uni-forms-item name="password"> <uni-easyinput :focus="focusPassword" @blur="focusPassword = false" class="input-box" clearable type="password" :inputBorder="false" v-model="password" placeholder="请输入密码" trim="all" /> </uni-forms-item> </uni-forms> <uni-captcha v-if="needCaptcha" focus ref="captcha" scene="login-by-pwd" v-model="captcha" /> <!-- 带选择框的隐私政策协议组件 --> <uni-id-pages-agreements scope="login" ref="agreements"></uni-id-pages-agreements> <button class="uni-btn" type="primary" @click="pwdLogin">登录</button> <!-- 忘记密码 --> <view class="link-box"> <view v-if="!config.isAdmin"> <text class="forget">忘记了?</text> <text class="link" @click="toRetrievePwd">找回密码</text> </view> <text class="link" @click="toRegister">{{config.isAdmin ? '注册管理员账号': '注册账号'}}</text> <!-- <text class="link" @click="toRegister" v-if="!config.isAdmin">注册账号</text> --> </view> <!-- 悬浮登录方式组件 --> <uni-id-pages-fab-login ref="uniFabLogin"></uni-id-pages-fab-login> </view> </template> <script> import mixin from '@/uni_modules/uni-id-pages/common/login-page.mixin.js'; const uniIdCo = uniCloud.importObject("uni-id-co", { errorOptions: { type: 'toast' } }) export default { mixins: [mixin], data() { return { "password": "", "username": "", "captcha": "", "needCaptcha": false, "focusUsername": false, "focusPassword": false, "logo": "/static/logo.png" } }, onShow() { // #ifdef H5 document.onkeydown = event => { var e = event || window.event; if (e && e.keyCode == 13) { //回车键的键值为13 this.pwdLogin() } }; // #endif }, methods: { // 页面跳转,找回密码 toRetrievePwd() { let url = '/uni_modules/uni-id-pages/pages/retrieve/retrieve-by-email' //如果刚好用户名输入框的值为手机号码,就把它传到retrieve页面,根据该手机号找回密码 if (/^1\d{10}$/.test(this.username)) { url += `?phoneNumber=${this.username}` } uni.navigateTo({ url }) }, /** * 密码登录 */ pwdLogin() { if (!this.password.length) { this.focusPassword = true return uni.showToast({ title: '请输入密码', icon: 'none', duration: 3000 }); } if (!this.username.length) { this.focusUsername = true return uni.showToast({ title: '请输入邮箱', icon: 'none', duration: 3000 }); } if (this.needCaptcha && this.captcha.length != 4) { this.$refs.captcha.getImageCaptcha() return uni.showToast({ title: '请输入验证码', icon: 'none', duration: 3000 }); } if (this.needAgreements && !this.agree) { return this.$refs.agreements.popup(this.pwdLogin) } let data = { "password": this.password, "captcha": this.captcha } if (/^1\d{10}$/.test(this.username)) { data.mobile = this.username } else if (/@/.test(this.username)) { data.email = this.username } else { data.username = this.username } uniIdCo.login(data).then(e => { this.loginSuccess(e) }).catch(e => { if (e.errCode == 'uni-id-captcha-required') { this.needCaptcha = true } else if (this.needCaptcha) { //登录失败,自动重新获取验证码 this.$refs.captcha.getImageCaptcha() } }) }, /* 前往注册 */ toRegister() { uni.navigateTo({ url: this.config.isAdmin ? '/uni_modules/uni-id-pages/pages/register/register-admin' : '/uni_modules/uni-id-pages/pages/register/register-by-email', fail(e) { console.error(e); } }) } } } </script> <style lang="scss" scoped> @import "@/uni_modules/uni-id-pages/common/login-page.scss"; @media screen and (min-width: 690px) { .uni-content { height: auto; } } .forget { font-size: 12px; color: #8a8f8b; } .link-box { /* #ifndef APP-NVUE */ display: flex; /* #endif */ flex-direction: row; justify-content: space-between; margin-top: 20px; } .link { font-size: 12px; } .title{ // 居中 text-align: center; } </style>
http://www.jsqmd.com/news/473685/

相关文章:

  • Mesa图形栈实战:从GLSL到NIR的完整编译链接流程解析
  • 【java】Queue(队列)接口详解
  • HTML5游戏革命:Facebook Instant Game如何重塑社交娱乐体验
  • 内存马二:Filter
  • ESP32-C3驱动4*4矩阵键盘与OLED显示屏的交互实现
  • Stable Diffusion Anything V5保姆级教程:从部署到生成第一张二次元图
  • 从生肖款918g大礼袋到新品礼盒装,新年限定零食礼包推荐怎么选更稳 - Top品牌推荐官
  • 龙虾三啖:白话OpenClaw
  • Activiti7进阶(流程定义+流程实例+任务负责人+任务候选人)
  • PGP加密解密原理详解:为什么说它是保护隐私的最后防线?
  • JavaScript 深度学习(五)
  • Kettle实战进阶 第10篇 JavaScript脚本中的高效日志调试技巧
  • 软件架构师工作心得
  • KITTI 3D 数据可视化:从点云到鸟瞰图的实战解析
  • RMBG-2.0智能抠图工具快速部署指南:双击启动,打开浏览器就能用
  • 巧用Kafka报文模拟工具:从零搭建测试环境到精准验证消费逻辑
  • 【实战拆解】从硬实时到软服务:AUTOSAR CP/AP混合架构的落地挑战与选型指南
  • VSCode安装灵毓秀-牧神-造相Z-Turbo开发环境教程
  • Qwen2.5-VL快速入门:Ollama部署教程,图片识别对话一学就会
  • 北京上门回收大活络丸!本草拾光商行高价收,懂行护宝不辜负,时效无忧 - 品牌排行榜单
  • Flink实战:如何用KeyedProcessFunction实现温度异常检测(附完整代码)
  • WSL2网络服务外网访问实战:从局域网到移动端的无缝连接
  • Asian Beauty Z-Image Turbo 本地化部署精讲:OpenClaw社区部署经验与踩坑记录
  • SAR动目标检测系列:【5】多基线联合处理下的三维速度解耦
  • Godot游戏练习01-第9节-游戏轮次
  • ESP32 GPIO底层架构:IO MUX与交换矩阵深度解析
  • GD32VW553驱动TCS34725颜色传感器:I2C通信与RGB/HSL数据采集实战
  • C++中的装饰器模式高级应用
  • javascript零基础入门指南:用快马平台生成你的第一个交互式计算器
  • Ubuntu20.04下拯救者笔记本亮度调节失效?NVIDIA驱动加载顺序问题全解析