使用Go實(shí)現(xiàn)郵箱驗(yàn)證碼API功能
前言
本文將帶你了解一個(gè)項(xiàng)目如何實(shí)現(xiàn)一個(gè)郵箱驗(yàn)證接口,即一個(gè)可用的發(fā)送郵箱驗(yàn)證碼API和驗(yàn)證驗(yàn)證碼是否正確功能。
本文靈感來源于我的個(gè)人項(xiàng)目中的一個(gè)關(guān)于郵箱驗(yàn)證的小模塊,如果你想學(xué)習(xí)Go以及上線一個(gè)簡單的網(wǎng)盤項(xiàng)目,歡迎學(xué)習(xí)或者參與進(jìn)我的開源項(xiàng)目Go-Cloud-Disk。如果能給我的項(xiàng)目點(diǎn)一個(gè)star更好不過,你的鼓勵(lì)與點(diǎn)贊會(huì)使得我的項(xiàng)目和博客變得更好!
環(huán)境配置
實(shí)現(xiàn)一個(gè)郵箱驗(yàn)證接口我們需要使用Redis及一個(gè)可以發(fā)送郵件的郵箱本文將以163郵箱為例。
使用到的Go包
email:go常用的發(fā)送郵件的api。官方教程
Gin:本文將使用Gin進(jìn)行路由注冊。官方教程
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ù)器和郵箱密鑰,下面我會(huì)以163郵箱為例演示如何獲取SMTP密鑰。
開啟后會(huì)獲得對應(yīng)密鑰,保存即可。
使用go發(fā)送郵件
發(fā)送郵件僅需使用go-email進(jìn)行對應(yīng)的封裝即可,此處smtp服務(wù)器地址一般都可以猜出,如qq郵箱的smtp服務(wù)器為smtp.qq.com,或者直接百度搜索即可。但是對應(yīng)的端口地址在選擇不同的郵箱時(shí)需要注意更換,如163郵箱smtp服務(wù)器可用端口為25,qq郵箱可用端口號(hào)為465或587。
package main import ( "fmt" "net/smtp" "github.com/jordan-wright/email" ) func main() { targetMailBox := "" // 目標(biāo)郵箱 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} // 目標(biāo)郵箱 // email title em.Subject = "Email Confirm Test" // 標(biāo)題 // build email content em.Text = []byte("test") // 內(nèi)容 // 調(diào)用接口發(fā)送郵件 // 此處端口號(hào)不一定為25使用對應(yīng)郵箱時(shí)需要具體更換 em.Send(smtpServer+":25", smtp.PlainAuth("", emailAddr, smtpKey, smtpServer)) }
使用go run main.go運(yùn)行
成功發(fā)送郵件!!!
初始化Redis
此處使用go-Redis對Redis進(jìn)行操作,此處提供一個(gè)初始化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默認(rèn)地址 Password: "", // Redis密碼,一般建立時(shí)不設(shè)置 DB: int(db), MaxRetries: 1, }) _, err := client.Ping(context.Background()).Result() if err != nil { panic("can't connect redis") } RedisClient = client }
實(shí)現(xiàn)發(fā)送郵件接口
發(fā)送郵箱驗(yàn)證碼函數(shù)實(shí)現(xiàn)
使用正則表達(dá)式,驗(yàn)證郵箱格式函數(shù)
func VerifyEmailFormat(email string) bool { pattern := `^[^\s@]+@[^\s@]+\.[^\s@]+$` //match email reg := regexp.MustCompile(pattern) return reg.MatchString(email) }
發(fā)送驗(yàn)證碼函數(shù),此處使用了系統(tǒng)環(huán)境變量配置的郵箱參數(shù),如果想要變更,直接根據(jù)上文進(jìn)行替換即可
// SendConfirmMessage傳入目標(biāo)郵箱以及對應(yīng)的Code碼即可發(fā)送驗(yàn)證碼郵件 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} // 郵箱標(biāo)題 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ù)實(shí)現(xiàn)
定義傳參和返回值
type UserSendConfirmEmailService struct { UserEmail string `json:"email" form:"email" binding:"required"` }
獲取六位數(shù)隨機(jī)驗(yàn)證碼函數(shù)
func getConfirmCode() string { var confirmCode int for i := 0; i < 6; i++ { confirmCode = confirmCode*10 + (rand.Intn(9) + 1) //隨機(jī)函數(shù)獲取值 } // 轉(zhuǎn)換成字符串 confirmCodeStr := strconv.Itoa(confirmCode) return confirmCodeStr }
發(fā)送驗(yàn)證碼函數(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ù)郵箱驗(yàn)證碼 code := getConfirmCode() // 將其存儲(chǔ)至Redis中,由于Redis為KV鍵值對存儲(chǔ)所以需要定義前綴方便使用 RedisClient.Set(context.Background(), "email:"+service.UserEmail, code, time.Minute*30) // 發(fā)送郵件,此處為方便起見沒有處理返回值 SendConfirmMessage(service.UserEmail, code) // 設(shè)置每個(gè)郵箱發(fā)送郵件的時(shí)間 此處設(shè)置為3分鐘,由于Redis為KV鍵值對存儲(chǔ)所以需要定義前綴方便使用 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ù)具體運(yùn)行端口 }
使用postman調(diào)用接口
發(fā)送成功?。?!
如何校驗(yàn)驗(yàn)證碼是否正確?
根據(jù)用戶郵箱,從Redis中直接獲取即可。
此處給出獲取方式
code := cache.RedisClient.Get(context.Background(), "email:"+service.UserEmail).Val()
一些需要注意的地方
驗(yàn)證3分鐘內(nèi)是否發(fā)送過驗(yàn)證碼僅需50ms以內(nèi)無需擔(dān)心速度
但發(fā)送郵件接口一般需要700ms-2s,可以考慮使用消息隊(duì)列進(jìn)行發(fā)送提高用戶體驗(yàn)感
發(fā)送郵件驗(yàn)證碼一般是在注冊時(shí)使用,可考慮使用gorm搜索數(shù)據(jù)庫防止重復(fù)郵箱注冊
本文僅僅使用了最簡單的方式處理返回值,如果想了解如何更規(guī)范的處理可以考慮參考我的項(xiàng)目Go-Cloud-Disk如果能給我的項(xiàng)目點(diǎn)個(gè)star就再好不過了。
到此這篇關(guān)于使用Go實(shí)現(xiàn)郵箱驗(yàn)證碼API的文章就介紹到這了,更多相關(guān)go郵箱驗(yàn)證碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Go中如何進(jìn)行進(jìn)行內(nèi)存優(yōu)化和垃圾收集器管理
這篇文章主要為大家詳細(xì)介紹了Go中如何進(jìn)行進(jìn)行內(nèi)存優(yōu)化和垃圾收集器管理,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解下2023-11-11Golang控制通道實(shí)現(xiàn)協(xié)程等待詳解
這篇文章主要介紹了Golang控制通道實(shí)現(xiàn)協(xié)程等待,通道是Go語言程序的并發(fā)體goroutine是它們之間的通信機(jī)制。一個(gè)通道是一個(gè)通信機(jī)制,它可以讓一個(gè)goroutine通過它給另一個(gè)goroutine發(fā)送值信息。每個(gè)通道都有一個(gè)特殊的類型,也就是channels可發(fā)送數(shù)據(jù)的類型2022-11-11使用Gin框架返回JSON、XML和HTML數(shù)據(jù)
Gin是一個(gè)高性能的Go語言Web框架,它不僅提供了簡潔的API,還支持快速的路由和中間件處理,在Web開發(fā)中,返回JSON、XML和HTML數(shù)據(jù)是非常常見的需求,本文將介紹如何使用Gin框架來返回這三種類型的數(shù)據(jù),需要的朋友可以參考下2024-08-08Golang+Vue輕松構(gòu)建Web應(yīng)用的方法步驟
本文主要介紹了Golang+Vue輕松構(gòu)建Web應(yīng)用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05