使用Go實現(xiàn)郵箱驗證碼API功能
前言
本文將帶你了解一個項目如何實現(xiàn)一個郵箱驗證接口,即一個可用的發(fā)送郵箱驗證碼API和驗證驗證碼是否正確功能。
本文靈感來源于我的個人項目中的一個關(guān)于郵箱驗證的小模塊,如果你想學(xué)習(xí)Go以及上線一個簡單的網(wǎng)盤項目,歡迎學(xué)習(xí)或者參與進我的開源項目Go-Cloud-Disk。如果能給我的項目點一個star更好不過,你的鼓勵與點贊會使得我的項目和博客變得更好!
環(huán)境配置
實現(xiàn)一個郵箱驗證接口我們需要使用Redis及一個可以發(fā)送郵件的郵箱本文將以163郵箱為例。
使用到的Go包
email:go常用的發(fā)送郵件的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
如何發(fā)送郵件?
獲取對應(yīng)SMTP密鑰
發(fā)送郵件需要使用到對應(yīng)的SMTP服務(wù)器和郵箱密鑰,下面我會以163郵箱為例演示如何獲取SMTP密鑰。


開啟后會獲得對應(yīng)密鑰,保存即可。
使用go發(fā)送郵件
發(fā)送郵件僅需使用go-email進行對應(yīng)的封裝即可,此處smtp服務(wù)器地址一般都可以猜出,如qq郵箱的smtp服務(wù)器為smtp.qq.com,或者直接百度搜索即可。但是對應(yīng)的端口地址在選擇不同的郵箱時需要注意更換,如163郵箱smtp服務(wù)器可用端口為25,qq郵箱可用端口號為465或587。
package main
import (
"fmt"
"net/smtp"
"github.com/jordan-wright/email"
)
func main() {
targetMailBox := "" // 目標郵箱
smtpServer := "smtp.163.com" // smtp服務(wù)器
emailAddr := "" // 要發(fā)件的郵箱地址
smtpKey := "" // 獲取的smtp密鑰
em := email.NewEmail()
em.From = fmt.Sprintf("Go-Cloud-Disk <%s>", emailAddr) // 發(fā)件人
em.To = []string{targetMailBox} // 目標郵箱
// email title
em.Subject = "Email Confirm Test" // 標題
// build email content
em.Text = []byte("test") // 內(nèi)容
// 調(diào)用接口發(fā)送郵件
// 此處端口號不一定為25使用對應(yīng)郵箱時需要具體更換
em.Send(smtpServer+":25", smtp.PlainAuth("", emailAddr, smtpKey, smtpServer))
}使用go run main.go運行

成功發(fā)送郵件!!!
初始化Redis
此處使用go-Redis對Redis進行操作,此處提供一個初始化Redis的函數(shù)
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密碼,一般建立時不設(shè)置
DB: int(db),
MaxRetries: 1,
})
_, err := client.Ping(context.Background()).Result()
if err != nil {
panic("can't connect redis")
}
RedisClient = client
}實現(xiàn)發(fā)送郵件接口
發(fā)送郵箱驗證碼函數(shù)實現(xiàn)
使用正則表達式,驗證郵箱格式函數(shù)
func VerifyEmailFormat(email string) bool {
pattern := `^[^\s@]+@[^\s@]+\.[^\s@]+$` //match email
reg := regexp.MustCompile(pattern)
return reg.MatchString(email)
}發(fā)送驗證碼函數(shù),此處使用了系統(tǒng)環(huán)境變量配置的郵箱參數(shù),如果想要變更,直接根據(jù)上文進行替換即可
// SendConfirmMessage傳入目標郵箱以及對應(yīng)的Code碼即可發(fā)送驗證碼郵件
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
// 郵件內(nèi)容
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)
// 調(diào)用發(fā)送郵件函數(shù)
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接口函數(shù)實現(xiàn)
定義傳參和返回值
type UserSendConfirmEmailService struct {
UserEmail string `json:"email" form:"email" binding:"required"`
}獲取六位數(shù)隨機驗證碼函數(shù)
func getConfirmCode() string {
var confirmCode int
for i := 0; i < 6; i++ {
confirmCode = confirmCode*10 + (rand.Intn(9) + 1) //隨機函數(shù)獲取值
}
// 轉(zhuǎn)換成字符串
confirmCodeStr := strconv.Itoa(confirmCode)
return confirmCodeStr
}發(fā)送驗證碼函數(shù)
func (service *UserSendConfirmEmailService) SendConfirmEmail() string {
// 檢查是否為正確郵箱
if !VerifyEmailFormat(service.UserEmail) {
return "NotEmail"
}
// 檢查是否在3分鐘內(nèi)發(fā)送過郵件
if RedisClient.Get(context.Background(), "send-email:"+service.UserEmail).Val() != "" {
return "HasSendCode"
}
// 獲取六位數(shù)郵箱驗證碼
code := getConfirmCode()
// 將其存儲至Redis中,由于Redis為KV鍵值對存儲所以需要定義前綴方便使用
RedisClient.Set(context.Background(), "email:"+service.UserEmail, code, time.Minute*30)
// 發(fā)送郵件,此處為方便起見沒有處理返回值
SendConfirmMessage(service.UserEmail, code)
// 設(shè)置每個郵箱發(fā)送郵件的時間 此處設(shè)置為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綁定傳入?yún)?shù)
c.JSON(200, "ParmaErr")
return
}
res := service.SendConfirmEmail()
c.JSON(200, res)
}具體服務(wù)注冊
func main() {
Redis() // 初始化Redis
server := gin.Default()
server.POST("email", ConfirmUserEmail) // 注冊函數(shù)至localhost:3030/email
server.Run(":3030") // 服務(wù)具體運行端口
}使用postman調(diào)用接口

發(fā)送成功!??!

如何校驗驗證碼是否正確?
根據(jù)用戶郵箱,從Redis中直接獲取即可。
此處給出獲取方式
code := cache.RedisClient.Get(context.Background(), "email:"+service.UserEmail).Val()
一些需要注意的地方
驗證3分鐘內(nèi)是否發(fā)送過驗證碼僅需50ms以內(nèi)無需擔心速度
但發(fā)送郵件接口一般需要700ms-2s,可以考慮使用消息隊列進行發(fā)送提高用戶體驗感
發(fā)送郵件驗證碼一般是在注冊時使用,可考慮使用gorm搜索數(shù)據(jù)庫防止重復(fù)郵箱注冊
本文僅僅使用了最簡單的方式處理返回值,如果想了解如何更規(guī)范的處理可以考慮參考我的項目Go-Cloud-Disk如果能給我的項目點個star就再好不過了。
到此這篇關(guān)于使用Go實現(xiàn)郵箱驗證碼API的文章就介紹到這了,更多相關(guān)go郵箱驗證碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用docker構(gòu)建golang線上部署環(huán)境的步驟詳解
這篇文章主要介紹了使用docker構(gòu)建golang線上部署環(huán)境的步驟,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11
go語言編程學(xué)習(xí)實現(xiàn)圖的廣度與深度優(yōu)先搜索
這篇文章主要為大家介紹了go語言編程學(xué)習(xí)實現(xiàn)圖的廣度與深度優(yōu)先搜索示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2021-10-10
gorm FirstOrCreate和受影響的行數(shù)實例
這篇文章主要介紹了gorm FirstOrCreate和受影響的行數(shù)實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12

