使用Go实现验证码发送服务

使用Go实现验证码发送服务

邮箱服务配置

选择一个邮箱,开启该邮箱的SMTP服务,并生成授权码在后续使用。

Go邮件服务支持包配置

在terminal中运行以下命令安装go邮件服务支持包

1
go get github.com/jordan-wright/email

Redis服务配置

在terminal中运行以下命令安装go-redis服务支持包

1
go get github.com/go-redis/redis/v8

安装完毕后,可在项目的init文件中初始化Redis服务

1
2
3
4
5
6
7
8
9
var RDB = InitRedis("localhost:6379")

func InitRedis(addr string) *redis.Client {
return redis.NewClient(&redis.Options{
Addr: addr,
Password: "", // no password set
DB: 0, // use default DB
})
}

接下来打开Redis-Server服务,我们即可通过RDB操作Redis数据库。

Go验证码服务逻辑

我们使用Redis存储邮箱-验证码的键值对,并设置过期时间。

如将过期时间设置为5分钟,那么在一对键值对插入数据库的5分钟后Redis就会将其删除。这样就实现了验证码在一定时间后过期失效的功能。

代码实现

实现邮件转发功能

实现邮件发送函数MailSendCode,其两个参数分别为目标邮箱与验证码,并返回一个错误信息以判断邮件是否成功发送。

e.From的< >前输入发件人名称,< >中输入发送邮件的邮箱地址,在e.Subject中输入邮件标题,在e.HTML中输入邮件内容。

接下来调用SendWithTLS方法发送邮件,该函数有三个参数:

第一个参数输入发信所用邮箱的smtp服务器与端口;

第二个参数smtp.PlainAuth参照代码中配置即可:PlainAuth的第1个参数填写端口,此处可省略;第2个参数填写发送邮件的邮箱地址;第3个参数填写邮箱的SMTP服务授权码;第四个参数填写发信邮箱的smtp服务器;

第三个参数tls.Config填写tls协议的配置:第一个参数InsecureSkipVerify设置为true;第二个参数ServerName设置为发信邮箱的smtp服务器

在调用SendWithTLS后再根据err判断是否邮件是否成功发送。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func MailSendCode(dstMail, code string) error{
e := email.NewEmail()
e.From = "Sender Name <the Email Applied to Send Validation Code>"
e.To = []string{dstMail}

e.Subject = "Validation Code Sending Test"
e.HTML = []byte("<h1>Your Validation Code is "+code+"</h1>")
err := e.SendWithTLS(
"smtp.qq.com:465",
smtp.PlainAuth("", "the Email Applied to Send Validation Code", define.MailPassword, "smtp.qq.com"),
&tls.Config{
InsecureSkipVerify: true,
ServerName: "smtp.qq.com",
})
if err != nil{
return err
}
return nil
}

实现生成验证码功能

在实现发送功能前,我们还需要实现随机生成验证码的函数GenerateRandomCode

1
2
3
4
5
6
7
8
9
10
func GenerateRandomCode() string{
s := "1234567890"
code := ""
// import random seed, or that random code will always be the same one
rand.Seed(time.Now().UnixNano())
for i := 0 ; i < define.CodeLength; i++{
code += string(s[rand.Intn(len(s))])
}
return code
}

实现业务功能

在前端传来的请求中包含接收验证码的邮箱,我们使用req.Email获取邮箱的发送对象。

由于题主实现的该功能与注册功能绑定,故需首先使用xorm包在sql数据库中查询该邮箱是否已经注册。若查询失败则返回数据库查询错误信息;若查询成功且数据库中存在该邮箱的信息,则返回邮箱已注册的错误信息。

若未注册,则生成随机验证码,将邮箱-验证码的键值对存入Redis中,并调用邮件转发函数发送验证码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// check whether the email has been registered
cnt, err := l.svcCtx.Engine.Where("email = ?", req.Email).Count(new(models.UserBasic))
if err != nil {
return
}
if cnt > 0 {
err = errors.New("this Email has registered before")
return
}

// generate random validation code
code := helper.GenerateRandomCode()

// store the email-code kv pair into
l.svcCtx.RDB.Set(l.ctx, req.Email, code, time.Second*time.Duration(define.CodeExpirationTime))

err = helper.MailSendCode(req.Email, code)
return