使用Go实现邮箱验证码API功能
作者:陳杪秋
前言
本文将带你了解一个项目如何实现一个邮箱验证接口,即一个可用的发送邮箱验证码API和验证验证码是否正确功能。
本文灵感来源于我的个人项目中的一个关于邮箱验证的小模块,如果你想学习Go以及上线一个简单的网盘项目,欢迎学习或者参与进我的开源项目Go-Cloud-Disk。如果能给我的项目点一个star更好不过,你的鼓励与点赞会使得我的项目和博客变得更好!
环境配置
实现一个邮箱验证接口我们需要使用Redis及一个可以发送邮件的邮箱本文将以163邮箱为例。
使用到的Go包
email:go常用的发送邮件的api。官方教程
Gin:本文将使用Gin进行路由注册。官方教程
Go-Redis: golang流行的Redis操作工具之一。官方教程
一键下载安装
go get github.com/jordan-wright/email go get -u github.com/gin-gonic/gin go get github.com/redis/go-redis/v9
如何发送邮件?
获取对应SMTP密钥
发送邮件需要使用到对应的SMTP服务器和邮箱密钥,下面我会以163邮箱为例演示如何获取SMTP密钥。
开启后会获得对应密钥,保存即可。
使用go发送邮件
发送邮件仅需使用go-email进行对应的封装即可,此处smtp服务器地址一般都可以猜出,如qq邮箱的smtp服务器为smtp.qq.com,或者直接百度搜索即可。但是对应的端口地址在选择不同的邮箱时需要注意更换,如163邮箱smtp服务器可用端口为25,qq邮箱可用端口号为465或587。
package main import ( "fmt" "net/smtp" "github.com/jordan-wright/email" ) func main() { targetMailBox := "" // 目标邮箱 smtpServer := "smtp.163.com" // smtp服务器 emailAddr := "" // 要发件的邮箱地址 smtpKey := "" // 获取的smtp密钥 em := email.NewEmail() em.From = fmt.Sprintf("Go-Cloud-Disk <%s>", emailAddr) // 发件人 em.To = []string{targetMailBox} // 目标邮箱 // email title em.Subject = "Email Confirm Test" // 标题 // build email content em.Text = []byte("test") // 内容 // 调用接口发送邮件 // 此处端口号不一定为25使用对应邮箱时需要具体更换 em.Send(smtpServer+":25", smtp.PlainAuth("", emailAddr, smtpKey, smtpServer)) }
使用go run main.go运行
成功发送邮件!!!
初始化Redis
此处使用go-Redis对Redis进行操作,此处提供一个初始化Redis的函数
package main import ( "context" "os" "strconv" "github.com/redis/go-redis/v9" ) var RedisClient *redis.Client // init redis func Redis() { db, _ := strconv.ParseUint(os.Getenv("REDIS_DB"), 10, 64) //可不填 client := redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6379", // Redis默认地址 Password: "", // Redis密码,一般建立时不设置 DB: int(db), MaxRetries: 1, }) _, err := client.Ping(context.Background()).Result() if err != nil { panic("can't connect redis") } RedisClient = client }
实现发送邮件接口
发送邮箱验证码函数实现
使用正则表达式,验证邮箱格式函数
func VerifyEmailFormat(email string) bool { pattern := `^[^\s@]+@[^\s@]+\.[^\s@]+$` //match email reg := regexp.MustCompile(pattern) return reg.MatchString(email) }
发送验证码函数,此处使用了系统环境变量配置的邮箱参数,如果想要变更,直接根据上文进行替换即可
// SendConfirmMessage传入目标邮箱以及对应的Code码即可发送验证码邮件 func SendConfirmMessage(targetMailBox string, code string) error { em := email.NewEmail() em.From = fmt.Sprintf("Go-Cloud-Disk <%s>", os.Getenv("EMAIL_ADDR")) em.To = []string{targetMailBox} // 邮箱标题 em.Subject = "Email Confirm Code " + code // 邮件内容 emailContentCode := "you confirm code is " + code + ", Your code will expire in 30 minutes" emailContentEmail := "you confirm email is " + targetMailBox emailContent := emailContentCode + "\n" + emailContentEmail em.Text = []byte(emailContent) // 调用发送邮件函数 em.Send(os.Getenv("EMAIL_SMTP_SERVER")+":25", smtp.PlainAuth("", os.Getenv("EMAIL_ADDR"), os.Getenv("EMAIL_SECRET_KEY"), os.Getenv("EMAIL_SMTP_SERVER"))) return nil }
Gin接口函数实现
定义传参和返回值
type UserSendConfirmEmailService struct { UserEmail string `json:"email" form:"email" binding:"required"` }
获取六位数随机验证码函数
func getConfirmCode() string { var confirmCode int for i := 0; i < 6; i++ { confirmCode = confirmCode*10 + (rand.Intn(9) + 1) //随机函数获取值 } // 转换成字符串 confirmCodeStr := strconv.Itoa(confirmCode) return confirmCodeStr }
发送验证码函数
func (service *UserSendConfirmEmailService) SendConfirmEmail() string { // 检查是否为正确邮箱 if !VerifyEmailFormat(service.UserEmail) { return "NotEmail" } // 检查是否在3分钟内发送过邮件 if RedisClient.Get(context.Background(), "send-email:"+service.UserEmail).Val() != "" { return "HasSendCode" } // 获取六位数邮箱验证码 code := getConfirmCode() // 将其存储至Redis中,由于Redis为KV键值对存储所以需要定义前缀方便使用 RedisClient.Set(context.Background(), "email:"+service.UserEmail, code, time.Minute*30) // 发送邮件,此处为方便起见没有处理返回值 SendConfirmMessage(service.UserEmail, code) // 设置每个邮箱发送邮件的时间 此处设置为3分钟,由于Redis为KV键值对存储所以需要定义前缀方便使用 RedisClient.Set(context.Background(), "send-email:"+service.UserEmail, code, time.Minute*3) return "true" }
处理传参
func ConfirmUserEmail(c *gin.Context) { var service UserSendConfirmEmailService if err := c.ShouldBind(&service); err != nil { //使用ShouldBind绑定传入参数 c.JSON(200, "ParmaErr") return } res := service.SendConfirmEmail() c.JSON(200, res) }
具体服务注册
func main() { Redis() // 初始化Redis server := gin.Default() server.POST("email", ConfirmUserEmail) // 注册函数至localhost:3030/email server.Run(":3030") // 服务具体运行端口 }
使用postman调用接口
发送成功!!!
如何校验验证码是否正确?
根据用户邮箱,从Redis中直接获取即可。
此处给出获取方式
code := cache.RedisClient.Get(context.Background(), "email:"+service.UserEmail).Val()
一些需要注意的地方
验证3分钟内是否发送过验证码仅需50ms以内无需担心速度
但发送邮件接口一般需要700ms-2s,可以考虑使用消息队列进行发送提高用户体验感
发送邮件验证码一般是在注册时使用,可考虑使用gorm搜索数据库防止重复邮箱注册
本文仅仅使用了最简单的方式处理返回值,如果想了解如何更规范的处理可以考虑参考我的项目Go-Cloud-Disk如果能给我的项目点个star就再好不过了。
到此这篇关于使用Go实现邮箱验证码API的文章就介绍到这了,更多相关go邮箱验证码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!