gva框架实现邮箱注册功能

本文介绍了如何在GVA框架中使用163邮箱实现注册功能,包括前期准备工作(Go基础、gin和gorm使用)、SMTP配置示例和关键代码片段,强调了163邮箱的易用性。
摘要由CSDN通过智能技术生成

gva框架实现邮箱注册功能

前期准备

需要了解一些go的基础、gin框架以及gorm基本使用。这个功能不涉及到前端编写,所以你不会vue也行。

项目链接: gva源码
邮箱链接: 163邮箱

没对比过其它的邮箱,直接使用的是163,用完之后的主观评价是挺好用的!

邮箱设置

登陆到邮箱的主页面,主页上面的工具栏有一个设置
在这里插入图片描述
点击之后选择pop3/smtp/imap
在这里插入图片描述
然后将imap/smtp服务和pop3/smtp服务开启(我这边已经开启了)

在这里插入图片描述

代码展示

介绍一下前期的一些配置细节
yaml文件

#XXX
email:

    from: [这里填你的邮箱名]@163.com
    host: smtp.163.com
    secret: [你开启邮箱smtp服务的时候会有一串安全码,复制过来粘贴]
    nickname: [what ever you want]
    port: 465
    is-ssl: true
    end-time: "3"

#XXX

config文件夹下面新建一个email.go

package config

type Email struct {
	To       string `mapstructure:"to" json:"to" yaml:"to"`                   // 收件人:多个以英文逗号分隔 例:a@qq.com b@qq.com 正式开发中请把此项目作为参数使用
	From     string `mapstructure:"from" json:"from" yaml:"from"`             // 发件人  你自己要发邮件的邮箱
	Host     string `mapstructure:"host" json:"host" yaml:"host"`             // 服务器地址 例如 smtp.qq.com  请前往QQ或者你要发邮件的邮箱查看其smtp协议
	Secret   string `mapstructure:"secret" json:"secret" yaml:"secret"`       // 密钥    用于登录的密钥 最好不要用邮箱密码 去邮箱smtp申请一个用于登录的密钥
	Nickname string `mapstructure:"nickname" json:"nickname" yaml:"nickname"` // 昵称    发件人昵称 通常为自己的邮箱
	Port     int    `mapstructure:"port" json:"port" yaml:"port"`             // 端口     请前往QQ或者你要发邮件的邮箱查看其smtp协议 大多为 465
	IsSSL    bool   `mapstructure:"is-ssl" json:"is-ssl" yaml:"is-ssl"`       // 是否SSL   是否开启SSL
	EndTime  string `mapstructure:"end-time" json:"end-time" yaml:"end-time"`
}

项目的结构是这样的
在这里插入图片描述

config.go文件中添加上这个email结构体
在这里插入图片描述
只需要在gva项目中添加两个函数即可,其中对应的数据库结构信息,可以根据具体的业务逻辑自行创建

/***
* 参数
* email 前端接收到用户发送过来的json数据
* 返回值
* emailId 
* err 错误码
***/
func (_this *EmailService) SendService(email emailRespone.Email) (emailId string, err error) {
	//生成验证码
	driver := base64Captcha.NewDriverDigit(global.GBQ_CONFIG.Captcha.ImgHeight, global.GBQ_CONFIG.Captcha.ImgWidth, global.GBQ_CONFIG.Captcha.KeyLong, 0.7, 20)
	cp := base64Captcha.NewCaptcha(driver, system2.Store)
	emailId, _, err = cp.Generate()
	if err != nil {
		global.GBQ_LOG.Error("Failed to obtain the verification code. Procedure!", zap.Error(err))
		return
	}
	vcode := system2.Store.Get(emailId, false)
	var user system.SysUser
	var action int
	if email.Subject == "register" {
		err = global.GBQ_DB.Where("email = ?", email.To).First(&user).Error
		if err == nil {
			global.GBQ_LOG.Error("查询email失败", zap.Error(err))
			return
		}
		//TODO 修饰
		email.Body = "your register vcode is:  " + vcode
		action = 0
	} else if email.Subject == "find_pass" {
		email.Body = "your find_pass vcode is:  " + vcode
		action = 2
	}
	fmt.Println("vcode", email.Body)

	currentTime := time.Now()
	var currentEmailSmssystem.SysSms
	err = global.GBQ_DB.Model(&system.SysSms{}).Where("email = ?", email.To).Order("created_at desc").First(&currentEmailSms).Error
	if err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			err = errors.New("Obtaining the verification code is too frequent. Please try again later!")
			
			return "Obtaining the verification code is too frequent. Please try again later!", err
		}
	}

	if utils.IsLessThanThreeMinutes(currentTime, currentEmailSms.CreatedAt) { //距离上次请求验证码的时间小于三分钟
		err = errors.New("Obtaining the verification code is too frequent. Please try again later!")
		
		return "Obtaining the verification code is too frequent. Please try again later!", err
	} else {
		err = ServiceGroupApp.Email(email.To, email.Subject, email.Body)
		if err != nil {
			global.GBQ_LOG.Error("发送失败!", zap.Error(err))
			return
		}

		ssms := &system.SysSms{
			Email:  email.To,
			CodeId: emailId,
			Code:   vcode,
			Action: action,
		}

		err = global.GBQ_DB.Model(ssms).Create(ssms).Error
		if err != nil {
			return "", err
		}

		return emailId, nil
	}

}

func (e *EmailService) Email(To, subject string, body string) error {
	to := strings.Split(To, ",")
	return send(to, subject, body)
}

上面的代码放在项目的这个位置
在这里插入图片描述
api这里这样调用即可


func (e *EmailApi) SendEmail(c *gin.Context) {
	var email email_response.Email
	err := c.ShouldBind(&email)
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	realEmailNum := utils.DeEncrypt(email.To)
	fmt.Println(realEmailNum)
	email.To = realEmailNum

	id, err := service.ServiceGroupApp.SendService(email)
	if err != nil || id == "" {
		global.GBQ_LOG.Error("发送失败", zap.Error(err))
		response.FailWithMessage(err.Error(), c)
		return
	}

	response.OkWithMessage("Sent successfully", c)
	
}

这里基本上和源码没什么区别,只增加了几行代码,前端在传输用户邮箱的时候做了个base64加密避免明文传输漏洞
在这里插入图片描述
上面是触发邮箱发送验证码的部分,接下来用户注册的关键逻辑代码

func (b *BaseApi) RegisterByEmail(c *gin.Context) {
	var r systemReq.Register
	err := c.ShouldBind(&r)
	if err != nil {
		global.GBQ_LOG.Error("Failed to obtain registration parameters. Procedure", zap.Error(err))
		response.FailWithMessage("Failed to obtain registration parameters. Procedure", c)
		return
	}

	err = utils.Verify(r, utils.RegisterByEmailVerify)
	if err != nil {
		global.GBQ_LOG.Error("Registration validation failed", zap.Error(err))
		response.FailWithMessage("Registration validation failed", c)
		return
	}
	

	sms := &system.SysSms{}
	err = global.GBQ_DB.Where("code = ? AND email = ?", r.CheckCode, r.Email).First(&sms).Error
	if errors.Is(err, gorm.ErrRecordNotFound) {
		global.GBQ_LOG.Error("Failed to obtain the verification code id. Procedure", zap.Error(err))
		response.FailWithMessage("The verification code is incorrect", c)
		return
	}
	
	//判断验证码时间是否过期
	tsms := sms.CreatedAt
	tnow := time.Now()
	endTime, _ := strconv.ParseFloat(global.GBQ_CONFIG.Email.EndTime, 64)
	if tnow.Sub(tsms).Minutes() > endTime {
		//验证码过期
		global.GBQ_LOG.Info("Verification code expired")
		response.FailWithMessage("Verification code expired", c)
		return
	}

	var authorities []system.SysAuthority
	for _, v := range r.AuthorityIds {
		authorities = append(authorities, system.SysAuthority{
			AuthorityId: v,
		})
	}

	rand.Seed(time.Now().UnixNano())
	kefuId := rand.Intn(2) + 6
	specialId := strconv.Itoa(kefuId) //用户注册随机分配客服


	user := &system.SysUser{Password: r.Password, HeaderImg: r.HeaderImg, Email: r.Email, LockTag: "0",
		AuthorityId: r.AuthorityId,
		Authorities: authorities,
		Enable:      r.Enable,
		UserType:    "01",
		Special:     specialId,
	}
	userReturn, err := userService.Register(user)
	if err != nil {
		global.GBQ_LOG.Error("Registration failure!", zap.Error(err))
		response.FailWithMessage(err.Error(), c)
		return
	}

	userRole := system.SysUserRole{
		UserId: int64(user.ID),
		RoleId: 100,
	}
	err = global.GBQ_DB.Table(global.GBQ_CONFIG.English.EnglishUserRole).Create(&userRole).Error
	if err != nil {
		global.GBQ_LOG.Error("Failed to create user", zap.Error(err))
		response.FailWithMessage("Creation failure", c)
		global.GBQ_DB.Table(global.GBQ_CONFIG.English.EnglishUser).Delete(&user)
		return
	}

	//清除验证码
	Store.Get(r.CaptchaId, true)
	sms.Status = false
	global.GBQ_DB.Save(sms)
	response.OkWithDetailed(systemRes.SysUserResponse{User: userReturn}, "Registered successfully", c)

}

两句总结的话

关于路由注册这部分的代码直接看gva源码即可,这边就不复制粘贴滥竽充数了。
总的来说呢,163邮箱发送验证码是真的丝滑,gva框架也是真的好用!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值