使用Go实现邮箱验证码API功能

 更新时间:2024年06月11日 14:35:45   作者:陳杪秋  
本文将带你了解一个项目如何实现一个邮箱验证接口,即一个可用的发送邮箱验证码API和验证验证码是否正确功能,对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邮箱可用端口号为465587

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邮箱验证码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Goland 生成可执行文件的操作

    Goland 生成可执行文件的操作

    这篇文章主要介绍了Goland 生成可执行文件的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 详解Go中如何进行进行内存优化和垃圾收集器管理

    详解Go中如何进行进行内存优化和垃圾收集器管理

    这篇文章主要为大家详细介绍了Go中如何进行进行内存优化和垃圾收集器管理,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解下
    2023-11-11
  • 深入理解golang中io.Writer接口的使用

    深入理解golang中io.Writer接口的使用

    io 是一个 Golang 标准库包,它为围绕输入和输出的许多操作和用例定义了灵活的接口,这篇文章主要为大家介绍了Go中Writer接口的使用,需要的可以参考下
    2023-10-10
  • Golang控制通道实现协程等待详解

    Golang控制通道实现协程等待详解

    这篇文章主要介绍了Golang控制通道实现协程等待,通道是Go语言程序的并发体goroutine是它们之间的通信机制。一个通道是一个通信机制,它可以让一个goroutine通过它给另一个goroutine发送值信息。每个通道都有一个特殊的类型,也就是channels可发送数据的类型
    2022-11-11
  • golang读取文件的常用方法总结

    golang读取文件的常用方法总结

    今天小编就为大家分享一篇关于golang读取文件的常用方法总结,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • 使用Gin框架返回JSON、XML和HTML数据

    使用Gin框架返回JSON、XML和HTML数据

    Gin是一个高性能的Go语言Web框架,它不仅提供了简洁的API,还支持快速的路由和中间件处理,在Web开发中,返回JSON、XML和HTML数据是非常常见的需求,本文将介绍如何使用Gin框架来返回这三种类型的数据,需要的朋友可以参考下
    2024-08-08
  • Go语言指针访问结构体的方法

    Go语言指针访问结构体的方法

    这篇文章主要介绍了Go语言指针访问结构体的方法,涉及Go语言指针及结构体的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • Go语言里的new函数用法分析

    Go语言里的new函数用法分析

    这篇文章主要介绍了Go语言里的new函数用法,实例分析了new函数的功能及使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • GO语言make和new关键字的区别

    GO语言make和new关键字的区别

    本篇文章来介绍一道非常常见的面试题,到底有多常见呢?可能很多面试的开场白就是由此开始的。那就是 new 和 make 这两个内置函数的区别,希望对大家有所帮助
    2023-04-04
  • Golang+Vue轻松构建Web应用的方法步骤

    Golang+Vue轻松构建Web应用的方法步骤

    本文主要介绍了Golang+Vue轻松构建Web应用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05

最新评论