提示:koa发送验证码至邮箱,QQ邮箱发送
前言
koa发送验证码至邮箱,QQ邮箱发送
一、依赖和邮箱设置
npm install nodemailer --save
二、使用步骤
1.vue中Login.vue
代码如下(示例):
<template>
<div class="login_box">
<div class="login_list">
<el-form
:model="user"
status-icon
:rules="rules"
ref="loginForm"
label-width="80px"
class="login_orm"
>
<el-form-item label="邮箱" v-if="loginType='regist'" prop="email" class="login_list_item">
<el-input
v-model="user.email"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item v-if="loginType='regist'" label="邮箱验证码" prop="code" class="login_list_item">
<div class="login_item">
<el-input v-model.number="user.emailCode"></el-input>
<el-button type="primary" :disabled="disabledEmailCode" @click="getEmailCode" round>{{!disabledEmailCode?'获取验证码':countNum+'s'}}</el-button>
</div>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
import { regist,getPhoneCode, getImgCode, getEmailCode } from "@/axios/index";
export default {
name: "Login",
data() {
var validateEmail = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入邮箱"));
} else {
if(value != ""){
if(!this.emailReg.test(value)){
callback(new Error("请输入正确的邮箱"));
return
}
}
callback();
}
};
var validateEmailCode = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入验证码"));
} else {
callback();
}
};
return {
imgUrl: null,
msg: "用户注册",
loginType: "regist",
imgCodeUrl:null,
disabledPhoneCode:false,
disabledEmailCode:false,
countNum:60,
countTimer:null,
emailReg:/^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/,
user: {
email: "",
emailCode:"",
},
rules: {
email: [{required: false},{ validator: validateEmail, trigger: "blur" }],
emailCode: [{required: false},{ validator: validateEmailCode, trigger: "blur" }],
},
};
},
created(){
},
methods: {
getEmailCode(){
if(!this.emailReg.test(this.user.email)&&this.user.email!=''){
this.$message.error();('请输入正确的邮箱');
return
}
getEmailCode({email:this.user.email}).then(()=>{
this.$message.success();('验证码已发送邮箱');
})
},
},
};
</script>
<style scoped lang="scss">
.login_box {
position: relative;
height: 100%;
.login_list {
width: 400px;
position: absolute;
box-sizing: border-box;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
.login_title {
font-size: 16px;
text-align: center;
}
.login_item{
display: flex;
.el-button.is-round{
padding: 0 14px;
margin-left: 30px;
height: 26px;
position: relative;
top: 8px;
}
.login_item_img{
height: 40px;
width: 160px;
margin-left: 30px;
}
}
}
}
</style>
<style>
.login_box .login_list .el-form-item__label{
text-align: justify;
height: 40px;
overflow: hidden;
}
.login_box .login_list .el-form-item__label::after{
content: "";
display: inline-block;
width: 100%;
height: 100%;
}
</style>
2.vue中axios.js
代码如下(示例):
import axios from 'axios';
import { Loading, Message } from 'element-ui';
let urlData = { basicUrl: "http://127.0.0.1:3002" }
let loading;
const instance = axios.create({
baseURL: urlData.basicUrl,
timeout: 1000,
headers: { "X-Requested-With": "XMLHttpRequest" },
withCredentials: false,
});
// 添加请求拦截器
instance.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
loading = Loading.service({
lock: true, // 是否锁屏
text: '正在加载...', // 加载动画的文字
spinner: 'el-icon-loading', // 引入的loading图标
background: 'rgba(0, 0, 0, 0.3)', // 背景颜色
})
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
instance.interceptors.response.use(function (response) {
loading.close();
// 对响应数据做点什么
return response.data;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
export const getImgCode = async () => {
return instance.get('/getImgCode');
}
export default instance;
3.koa中routes.js
代码如下(示例):
import Router from 'koa-router';
import fs, { readFileSync } from 'fs';
import { sendEmail } from './emaiCode.js'
const router = new Router();
const getEmailCode = async ctx => {
let codeStr = ""; //验证码
let codeLen = 6; //验证码长度
for(let i=0;i<codeLen;i++){
codeStr += Math.floor(Math.random()*10);
}
var mail = {
from: `""<xxx@xx.xxx>`, //发件邮箱
subject: "验证码",
to: ctx.request.body.email, //收件邮箱
text: "验证码为:" + codeStr, //发送内容
};
const res = await sendEmail(mail);
ctx.session.emailCode = codeStr;
ctx.session.emailCodeTime = new Date().getTime();
ctx.body = {
code: 200,
data: res.info,
msg: 'success'
}
}
router.post('/getEmailCode ',getEmailCode );
export default router;
4.koa中emailCode.js
代码如下(示例):
import Nodemailer from 'nodemailer'
const config = {
host: "smtp.qq.com",
port: 465,
secureConnection: true,
service: "qq",
auth: {
user: "xxx@xxx.xxx", //发件账号
pass: "xxxxxxxxxx", //发件邮箱授权码
},
};
const transport = Nodemailer.createTransport(config);
export const sendEmail = async (mail) => {
let res = {};
let start_time = new Date().getTime();
return new Promise((resolve,reject)=>{
transport.sendMail(mail, (err, info) => {
res.err = err;
res.info = info;
console.log(new Date().getTime() - start_time,"ms")
resolve(res);
});
})
}
5.koa中app.js
代码如下(示例):
import koa from 'koa';
import cors from 'koa-cors';
import router from './routes/routes.js';
import staticFiles from 'koa-static';
import koaBody from 'koa-body';
import session from 'koa-session'
import path from 'path';
const __dirname = path.resolve();
const app = new koa();
app.use(cors({ // 指定一个或多个可以跨域的域名
origin: function (ctx) { // 设置允许来自指定域名请求
if (ctx.url === '/') {
return "*"; // 允许来自所有域名请求, 这个不管用
}
// return 'http://localhost:8000'; // 这样就能只允许 http://localhost:8000 这个域名的请求了
return '*'; // 这样就能只允许 http://localhost:8000 这个域名的请求了
},
maxAge: 5, // 指定本次预检请求的有效期,单位为秒。
credentials: true, // 是否允许发送Cookie
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], // 设置所允许的HTTP请求方法
allowHeaders: ['Content-Type', 'Authorization', 'Accept'], // 设置服务器支持的所有头信息字段
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'] // 设置获取其他自定义字段
}))
const sessionConfig = {
key: 'koa:sess', // cookie的key,默认koa:sess
maxAge: 1000*5, // 过期时间,毫秒ms
autoCommit: true, // 提交到响应头
overwrite: true, // 重写
httpOnly: true, // 无法获得Cookie信息
signed: true, // 签名
rolling: true, // 每次刷新
renew: false, // 快过期刷新
};
app.keys = ["long long age"]; // signed签名key
app.use(session(sessionConfig, app)); //第二个参数是app ----------------
//解析formdata过来的数据
app.use(koaBody({
multipart: true,
formidable: {
//上传文件存储目录
uploadDir: path.join(__dirname, `/public/uploads/`),
//允许保留后缀名
keepExtensions: true,
multipart: true,
},
jsonLimit:'10mb',
formLimit:'10mb',
textLimit:'10mb'
}));
app.use(router.routes());
app.use(router.allowedMethods());
app.use(staticFiles(__dirname + '/public'));
app.listen('3002');
console.log("项目启动,访问:","localhost:3002");
总结
踩坑路漫漫长@~@