使用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)無需擔(dān)心速度
但發(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)文章
詳解Go中如何進行進行內(nèi)存優(yōu)化和垃圾收集器管理
這篇文章主要為大家詳細介紹了Go中如何進行進行內(nèi)存優(yōu)化和垃圾收集器管理,文中的示例代碼講解詳細,具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以了解下2023-11-11使用Gin框架返回JSON、XML和HTML數(shù)據(jù)
Gin是一個高性能的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)用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05