swagger jwt email access_log middleware
This commit is contained in:
parent
6459a79c32
commit
fe2f6850f9
@ -31,3 +31,12 @@ JWT:
|
|||||||
Secret: eddycjy
|
Secret: eddycjy
|
||||||
Issuer: blog-service
|
Issuer: blog-service
|
||||||
Expire: 7200
|
Expire: 7200
|
||||||
|
Email:
|
||||||
|
Host: smtp.qq.com
|
||||||
|
Port: 465
|
||||||
|
UserName: xxxx@qq.com
|
||||||
|
Password: xxxxxxxx
|
||||||
|
IsSSL: true
|
||||||
|
From: xxxx@qq.com
|
||||||
|
To:
|
||||||
|
- xxxx@qq.com
|
39
docs/docs.go
39
docs/docs.go
@ -27,18 +27,16 @@ var doc = `{
|
|||||||
"paths": {
|
"paths": {
|
||||||
"/api/v1/tags": {
|
"/api/v1/tags": {
|
||||||
"get": {
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"summary": "获取多个标签",
|
"summary": "获取多个标签",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "token",
|
|
||||||
"name": "token",
|
|
||||||
"in": "query",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"maxLength": 100,
|
"maxLength": 100,
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -94,6 +92,11 @@ var doc = `{
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"post": {
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@ -153,6 +156,11 @@ var doc = `{
|
|||||||
},
|
},
|
||||||
"/api/v1/tags/{id}": {
|
"/api/v1/tags/{id}": {
|
||||||
"put": {
|
"put": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@ -218,6 +226,11 @@ var doc = `{
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"delete": {
|
"delete": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@ -311,6 +324,11 @@ var doc = `{
|
|||||||
},
|
},
|
||||||
"/upload/file": {
|
"/upload/file": {
|
||||||
"post": {
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@ -437,6 +455,13 @@ var doc = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"securityDefinitions": {
|
||||||
|
"ApiKeyAuth": {
|
||||||
|
"type": "apiKey",
|
||||||
|
"name": "Authorization",
|
||||||
|
"in": "header"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}`
|
}`
|
||||||
|
|
||||||
|
@ -10,18 +10,16 @@
|
|||||||
"paths": {
|
"paths": {
|
||||||
"/api/v1/tags": {
|
"/api/v1/tags": {
|
||||||
"get": {
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
"summary": "获取多个标签",
|
"summary": "获取多个标签",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
|
||||||
"type": "string",
|
|
||||||
"description": "token",
|
|
||||||
"name": "token",
|
|
||||||
"in": "query",
|
|
||||||
"required": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"maxLength": 100,
|
"maxLength": 100,
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -77,6 +75,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"post": {
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@ -136,6 +139,11 @@
|
|||||||
},
|
},
|
||||||
"/api/v1/tags/{id}": {
|
"/api/v1/tags/{id}": {
|
||||||
"put": {
|
"put": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@ -201,6 +209,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"delete": {
|
"delete": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@ -294,6 +307,11 @@
|
|||||||
},
|
},
|
||||||
"/upload/file": {
|
"/upload/file": {
|
||||||
"post": {
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"ApiKeyAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
"application/json"
|
"application/json"
|
||||||
],
|
],
|
||||||
@ -420,5 +438,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"securityDefinitions": {
|
||||||
|
"ApiKeyAuth": {
|
||||||
|
"type": "apiKey",
|
||||||
|
"name": "Authorization",
|
||||||
|
"in": "header"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -59,11 +59,6 @@ paths:
|
|||||||
/api/v1/tags:
|
/api/v1/tags:
|
||||||
get:
|
get:
|
||||||
parameters:
|
parameters:
|
||||||
- description: token
|
|
||||||
in: query
|
|
||||||
name: token
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
- description: 标签名称
|
- description: 标签名称
|
||||||
in: query
|
in: query
|
||||||
maxLength: 100
|
maxLength: 100
|
||||||
@ -102,6 +97,8 @@ paths:
|
|||||||
description: 内部错误
|
description: 内部错误
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/errorcode.Error'
|
$ref: '#/definitions/errorcode.Error'
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: [ ]
|
||||||
summary: 获取多个标签
|
summary: 获取多个标签
|
||||||
post:
|
post:
|
||||||
parameters:
|
parameters:
|
||||||
@ -142,6 +139,8 @@ paths:
|
|||||||
description: 内部错误
|
description: 内部错误
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/errorcode.Error'
|
$ref: '#/definitions/errorcode.Error'
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: [ ]
|
||||||
summary: 新增标签
|
summary: 新增标签
|
||||||
/api/v1/tags/{id}:
|
/api/v1/tags/{id}:
|
||||||
delete:
|
delete:
|
||||||
@ -166,6 +165,8 @@ paths:
|
|||||||
description: 内部错误
|
description: 内部错误
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/errorcode.Error'
|
$ref: '#/definitions/errorcode.Error'
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: [ ]
|
||||||
summary: 删除标签
|
summary: 删除标签
|
||||||
put:
|
put:
|
||||||
parameters:
|
parameters:
|
||||||
@ -211,6 +212,8 @@ paths:
|
|||||||
description: 内部错误
|
description: 内部错误
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/errorcode.Error'
|
$ref: '#/definitions/errorcode.Error'
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: [ ]
|
||||||
summary: 更新标签
|
summary: 更新标签
|
||||||
/auth:
|
/auth:
|
||||||
post:
|
post:
|
||||||
@ -278,5 +281,12 @@ paths:
|
|||||||
description: 内部错误
|
description: 内部错误
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/errorcode.Error'
|
$ref: '#/definitions/errorcode.Error'
|
||||||
|
security:
|
||||||
|
- ApiKeyAuth: [ ]
|
||||||
summary: 上传图片
|
summary: 上传图片
|
||||||
|
securityDefinitions:
|
||||||
|
ApiKeyAuth:
|
||||||
|
in: header
|
||||||
|
name: Authorization
|
||||||
|
type: apiKey
|
||||||
swagger: "2.0"
|
swagger: "2.0"
|
||||||
|
@ -11,4 +11,5 @@ var (
|
|||||||
DatabaseSetting *setting.DatabaseSettingS
|
DatabaseSetting *setting.DatabaseSettingS
|
||||||
Logger *logger.Logger
|
Logger *logger.Logger
|
||||||
JWTSetting *setting.JWT
|
JWTSetting *setting.JWT
|
||||||
|
EmailSetting *setting.EmailSettingS
|
||||||
)
|
)
|
||||||
|
2
go.mod
2
go.mod
@ -40,7 +40,9 @@ require (
|
|||||||
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea // indirect
|
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea // indirect
|
||||||
golang.org/x/text v0.3.6 // indirect
|
golang.org/x/text v0.3.6 // indirect
|
||||||
golang.org/x/tools v0.1.2 // indirect
|
golang.org/x/tools v0.1.2 // indirect
|
||||||
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
|
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
|
||||||
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
|
||||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
43
internal/middleware/access_log.go
Normal file
43
internal/middleware/access_log.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"blog/global"
|
||||||
|
"blog/pkg/logger"
|
||||||
|
"bytes"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AccessLogWriter struct {
|
||||||
|
gin.ResponseWriter
|
||||||
|
body *bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w AccessLogWriter) Write(p []byte) (int, error) {
|
||||||
|
if n, err := w.body.Write(p); err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
return w.ResponseWriter.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func AccessLog() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
bodyWriter := &AccessLogWriter{body: bytes.NewBufferString(""), ResponseWriter: c.Writer}
|
||||||
|
c.Writer = bodyWriter
|
||||||
|
|
||||||
|
beginTime := time.Now().Unix()
|
||||||
|
c.Next()
|
||||||
|
endTime := time.Now().Unix()
|
||||||
|
|
||||||
|
fields := logger.Fields{
|
||||||
|
"request": c.Request.PostForm.Encode(),
|
||||||
|
"response": bodyWriter.body.String(),
|
||||||
|
}
|
||||||
|
global.Logger.WithFields(fields).Infof("access log: method: %s, status_code: %d, begin_time: %d, end_time: %d",
|
||||||
|
c.Request.Method,
|
||||||
|
bodyWriter.Status(),
|
||||||
|
beginTime,
|
||||||
|
endTime,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
11
internal/middleware/app_info.go
Normal file
11
internal/middleware/app_info.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import "github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
func AppInfo() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
c.Set("app_name", "blog-service")
|
||||||
|
c.Set("app_version", "1.0.0")
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
}
|
@ -13,10 +13,10 @@ func JWT() gin.HandlerFunc {
|
|||||||
token string
|
token string
|
||||||
ecode = errorcode.Success
|
ecode = errorcode.Success
|
||||||
)
|
)
|
||||||
if s, exist := c.GetQuery("token"); exist {
|
if s, exist := c.GetQuery("Authorization"); exist {
|
||||||
token = s
|
token = s
|
||||||
} else {
|
} else {
|
||||||
token = c.GetHeader("token")
|
token = c.GetHeader("Authorization")
|
||||||
}
|
}
|
||||||
if token == "" {
|
if token == "" {
|
||||||
ecode = errorcode.InvalidParams
|
ecode = errorcode.InvalidParams
|
||||||
|
42
internal/middleware/recovery.go
Normal file
42
internal/middleware/recovery.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"blog/global"
|
||||||
|
"blog/pkg/app"
|
||||||
|
"blog/pkg/email"
|
||||||
|
"blog/pkg/errorcode"
|
||||||
|
"fmt"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Recovery() gin.HandlerFunc {
|
||||||
|
defailtMailer := email.NewEmail(&email.SMTPInfo{
|
||||||
|
Host: global.EmailSetting.Host,
|
||||||
|
Port: global.EmailSetting.Port,
|
||||||
|
IsSSL: global.EmailSetting.IsSSL,
|
||||||
|
UserName: global.EmailSetting.UserName,
|
||||||
|
Password: global.EmailSetting.Password,
|
||||||
|
From: global.EmailSetting.From,
|
||||||
|
})
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
global.Logger.WithCallersFrames().Errorf("panic recover err: %v", err)
|
||||||
|
|
||||||
|
err := defailtMailer.SendMail(
|
||||||
|
global.EmailSetting.To,
|
||||||
|
fmt.Sprintf("异常抛出,发生时间: %d", time.Now().Unix()),
|
||||||
|
fmt.Sprintf("错误信息: %v", err),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
global.Logger.Panicf("mail.SendMail err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
app.NewResponse(c).ToErrorResponse(errorcode.ServerError)
|
||||||
|
c.Abort()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
}
|
@ -33,8 +33,10 @@ func ReadFile(c *gin.Context) {
|
|||||||
c.File(fileName)
|
c.File(fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UploadFile
|
||||||
// @Summary 上传图片
|
// @Summary 上传图片
|
||||||
// @Produce json
|
// @Produce json
|
||||||
|
// @Security ApiKeyAuth
|
||||||
// @Param type formData int true "文件类型1图片" required Enums(1,2,3)
|
// @Param type formData int true "文件类型1图片" required Enums(1,2,3)
|
||||||
// @Param file formData file true "文件"
|
// @Param file formData file true "文件"
|
||||||
// @Success 200 {object} service.FileInfo "成功"
|
// @Success 200 {object} service.FileInfo "成功"
|
||||||
|
@ -18,9 +18,10 @@ func NewTag() Tag {
|
|||||||
|
|
||||||
func (t Tag) Get(c *gin.Context) {}
|
func (t Tag) Get(c *gin.Context) {}
|
||||||
|
|
||||||
|
// List
|
||||||
// @Summary 获取多个标签
|
// @Summary 获取多个标签
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param token query string true "token"
|
// @Security ApiKeyAuth
|
||||||
// @Param name query string false "标签名称" maxlength(100)
|
// @Param name query string false "标签名称" maxlength(100)
|
||||||
// @Param state query int false "状态" Enums(0, 1) default(1)
|
// @Param state query int false "状态" Enums(0, 1) default(1)
|
||||||
// @Param page query int false "页码" default(1)
|
// @Param page query int false "页码" default(1)
|
||||||
@ -60,6 +61,7 @@ func (t Tag) List(c *gin.Context) {
|
|||||||
|
|
||||||
// @Summary 新增标签
|
// @Summary 新增标签
|
||||||
// @Produce json
|
// @Produce json
|
||||||
|
// @Security ApiKeyAuth
|
||||||
// @Param name formData string true "标签名称" minlength(3) maxlength(100)
|
// @Param name formData string true "标签名称" minlength(3) maxlength(100)
|
||||||
// @Param state formData int false "状态" Enums(0, 1) default(1)
|
// @Param state formData int false "状态" Enums(0, 1) default(1)
|
||||||
// @Param created_by formData string true "创建者" minlength(3) maxlength(100)
|
// @Param created_by formData string true "创建者" minlength(3) maxlength(100)
|
||||||
@ -91,6 +93,7 @@ func (t Tag) Create(c *gin.Context) {
|
|||||||
|
|
||||||
// @Summary 更新标签
|
// @Summary 更新标签
|
||||||
// @Produce json
|
// @Produce json
|
||||||
|
// @Security ApiKeyAuth
|
||||||
// @Param id path int true "标签 ID"
|
// @Param id path int true "标签 ID"
|
||||||
// @Param name formData string false "标签名称" minlength(3),maxlength(100)
|
// @Param name formData string false "标签名称" minlength(3),maxlength(100)
|
||||||
// @Param state formData int false "状态" Enums(0, 1) default(1)
|
// @Param state formData int false "状态" Enums(0, 1) default(1)
|
||||||
@ -121,6 +124,7 @@ func (t Tag) Update(c *gin.Context) {
|
|||||||
|
|
||||||
// @Summary 删除标签
|
// @Summary 删除标签
|
||||||
// @Produce json
|
// @Produce json
|
||||||
|
// @Security ApiKeyAuth
|
||||||
// @Param id path int true "标签 ID"
|
// @Param id path int true "标签 ID"
|
||||||
// @Success 200 {string} string "成功"
|
// @Success 200 {string} string "成功"
|
||||||
// @Failure 400 {object} errorcode.Error "请求错误"
|
// @Failure 400 {object} errorcode.Error "请求错误"
|
||||||
|
@ -17,15 +17,18 @@ func NewRouter() *gin.Engine {
|
|||||||
r.Use(gin.Logger())
|
r.Use(gin.Logger())
|
||||||
r.Use(gin.Recovery())
|
r.Use(gin.Recovery())
|
||||||
r.Use(middleware.Translations())
|
r.Use(middleware.Translations())
|
||||||
|
r.Use(middleware.Recovery())
|
||||||
|
r.Use(middleware.AccessLog())
|
||||||
article := v1.NewArticle()
|
article := v1.NewArticle()
|
||||||
tag := v1.NewTag()
|
tag := v1.NewTag()
|
||||||
upload := api.NewUpload()
|
upload := api.NewUpload()
|
||||||
r.POST("/upload/file", upload.UploadFile)
|
|
||||||
|
r.POST("/upload/file", middleware.JWT(), upload.UploadFile)
|
||||||
r.StaticFS("/static", http.Dir(global.AppSetting.UploadSavePath))
|
r.StaticFS("/static", http.Dir(global.AppSetting.UploadSavePath))
|
||||||
//r.GET("/static/*any",api.ReadFile)
|
//r.GET("/static/*any",api.ReadFile)
|
||||||
r.GET("/doc/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
r.GET("/doc/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||||
r.POST("/auth", api.GetAuth)
|
r.POST("/auth", api.GetAuth)
|
||||||
|
|
||||||
apiv1 := r.Group("/api/v1")
|
apiv1 := r.Group("/api/v1")
|
||||||
apiv1.Use(middleware.JWT())
|
apiv1.Use(middleware.JWT())
|
||||||
{
|
{
|
||||||
|
8
main.go
8
main.go
@ -68,7 +68,10 @@ func setupSetting() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = newSetting.ReadSection("Email", &global.EmailSetting)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
global.JWTSetting.Expire *= time.Second
|
global.JWTSetting.Expire *= time.Second
|
||||||
global.ServerSetting.ReadTimeout *= time.Second
|
global.ServerSetting.ReadTimeout *= time.Second
|
||||||
global.ServerSetting.WriteTimeout *= time.Second
|
global.ServerSetting.WriteTimeout *= time.Second
|
||||||
@ -79,6 +82,9 @@ func setupSetting() error {
|
|||||||
// @version 1.0
|
// @version 1.0
|
||||||
// @description Go 语言编程之旅:一起用 Go 做项目
|
// @description Go 语言编程之旅:一起用 Go 做项目
|
||||||
// @termsOfService https://github.com/go-programming-tour-book
|
// @termsOfService https://github.com/go-programming-tour-book
|
||||||
|
// @securityDefinitions.apikey ApiKeyAuth
|
||||||
|
// @in header
|
||||||
|
// @name Authorization
|
||||||
func main() {
|
func main() {
|
||||||
gin.SetMode(global.ServerSetting.RunMode)
|
gin.SetMode(global.ServerSetting.RunMode)
|
||||||
|
|
||||||
|
35
pkg/email/email.go
Normal file
35
pkg/email/email.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package email
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"gopkg.in/gomail.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Email struct {
|
||||||
|
*SMTPInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type SMTPInfo struct {
|
||||||
|
Host string
|
||||||
|
Port int
|
||||||
|
IsSSL bool
|
||||||
|
UserName string
|
||||||
|
Password string
|
||||||
|
From string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewEmail(info *SMTPInfo) *Email {
|
||||||
|
return &Email{SMTPInfo: info}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Email) SendMail(to []string, subject, body string) error {
|
||||||
|
m := gomail.NewMessage()
|
||||||
|
m.SetHeader("From", e.From)
|
||||||
|
m.SetHeader("To", to...)
|
||||||
|
m.SetHeader("Subject", subject)
|
||||||
|
m.SetBody("text/html", body)
|
||||||
|
|
||||||
|
dialer := gomail.NewDialer(e.Host, e.Port, e.UserName, e.Password)
|
||||||
|
dialer.TLSConfig = &tls.Config{InsecureSkipVerify: e.IsSSL}
|
||||||
|
return dialer.DialAndSend(m)
|
||||||
|
}
|
@ -163,3 +163,8 @@ func (l *Logger) Error(v ...interface{}) {
|
|||||||
func (l *Logger) Errorf(format string, v ...interface{}) {
|
func (l *Logger) Errorf(format string, v ...interface{}) {
|
||||||
l.Output(LevelError, fmt.Sprintf(format, v...))
|
l.Output(LevelError, fmt.Sprintf(format, v...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Panicf(format string, v ...interface{}) {
|
||||||
|
l.Output(LevelPanic, fmt.Sprintf(format, v...))
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -48,3 +48,13 @@ func (s *Setting) ReadSection(k string, v interface{}) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EmailSettingS struct {
|
||||||
|
Host string
|
||||||
|
Port int
|
||||||
|
UserName string
|
||||||
|
Password string
|
||||||
|
IsSSL bool
|
||||||
|
From string
|
||||||
|
To []string
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user