diff --git a/server/api/v1/sys_email.go b/server/api/v1/sys_email.go new file mode 100644 index 0000000000000000000000000000000000000000..264ae340a513f5d34b32c97ab1a483c0029af960 --- /dev/null +++ b/server/api/v1/sys_email.go @@ -0,0 +1,23 @@ +package v1 + +import ( + "fmt" + "gin-vue-admin/global/response" + "gin-vue-admin/service" + "github.com/gin-gonic/gin" +) + +// @Tags system +// @Summary 发送测试邮件 +// @Security ApiKeyAuth +// @Produce application/json +// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}" +// @Router /email/emailTest [post] +func EmailTest(c *gin.Context) { + err := service.EmailTest() + if err != nil { + response.FailWithMessage(fmt.Sprintf("发送失败,%v", err), c) + } else { + response.OkWithData("发送成功", c) + } +} diff --git a/server/config.yaml b/server/config.yaml index 037c17f9b8c6f9fe761bd02d0f4ebe636d2c662d..c03b1eab03030c370a6588655a5a18101fc441a5 100644 --- a/server/config.yaml +++ b/server/config.yaml @@ -11,7 +11,7 @@ jwt: # mysql connect configuration mysql: username: root - password: 'Aa@6447985' + password: 'root' path: '127.0.0.1:3306' db-name: 'qmPlus' config: 'charset=utf8mb4&parseTime=True&loc=Local' @@ -80,4 +80,13 @@ zap: # LowercaseLevelEncoder:小写, LowercaseColorLevelEncoder:小写带颜色,CapitalLevelEncoder: 大写, CapitalColorLevelEncoder: 大写带颜色, encode_level: 'LowercaseColorLevelEncoder' stacktrace_key: 'stacktrace' - log_in_console: true \ No newline at end of file + log_in_console: true + +email: + email_from: 'xxx@163.com' + email_nick_name: 'test' + email_secret: 'xxx' + email_to: 'xxx@qq.com' + email_host: 'smtp.163.com' + email_port: 465 + email_isSSL: true \ No newline at end of file diff --git a/server/config/config.go b/server/config/config.go index 9a1197acf3c98f697c96af4f109e648c7cd373e2..3aee6358288c7054f0e91a083c3a6727554400ac 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -11,6 +11,7 @@ type Server struct { Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"` Zap Zap `mapstructure:"zap" json:"zap" yaml:"zap"` LocalUpload LocalUpload `mapstructure:"localUpload" json:"localUpload" yaml:"localUpload"` + Email Email `mapstructure:"email" json:"email" yaml:"email"` } type System struct { @@ -84,3 +85,13 @@ type Zap struct { StacktraceKey string `mapstructure:"stacktrace_key" json:"stacktraceKey" yaml:"stacktrace_key"` LogInConsole bool `mapstructure:"log_in_console" json:"logInConsole" yaml:"log_in_console"` } + +type Email struct { + EmailFrom string `mapstructure:"email_from" json:"emailFrom" yaml:"email_from"` + EmailNickName string `mapstructure:"email_nick_name" json:"emailNickName" yaml:"email_nick_name"` + EmailSecret string `mapstructure:"email_secret" json:"emailSecret" yaml:"email_secret"` + EmailTo string `mapstructure:"email_to" json:"emailTo" yaml:"email_to"` + EmailHost string `mapstructure:"email_host" json:"emailHost" yaml:"email_host"` + EmailPort int `mapstructure:"email_port" json:"emailPort" yaml:"email_port"` + EmailIsSSL bool `mapstructure:"email_isSSL" json:"emailIsSSL" yaml:"email_isSSL"` +} diff --git a/server/go.mod b/server/go.mod index 6ac4777f9a36989a42846a72086fffe87f57d3f7..d3084fc8dea70f3b53bc1bd8522fdd5ecd8adecd 100644 --- a/server/go.mod +++ b/server/go.mod @@ -19,6 +19,7 @@ require ( github.com/go-sql-driver/mysql v1.5.0 github.com/golang/protobuf v1.4.2 // indirect github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect + github.com/jordan-wright/email v0.0.0-20200824153738-3f5bafa1cd84 github.com/json-iterator/go v1.1.10 // indirect github.com/lestrrat-go/file-rotatelogs v2.3.0+incompatible github.com/lestrrat-go/strftime v1.0.3 // indirect diff --git a/server/initialize/router.go b/server/initialize/router.go index 14ebefbc416e7499d3af2ca09bc178957c70cff6..977035549dea1e2f277c528d9bd560c63107f532 100644 --- a/server/initialize/router.go +++ b/server/initialize/router.go @@ -43,6 +43,7 @@ func Routers() *gin.Engine { router.InitSysDictionaryDetailRouter(ApiGroup) // 字典详情管理 router.InitSysDictionaryRouter(ApiGroup) // 字典管理 router.InitSysOperationRecordRouter(ApiGroup) // 操作记录 + router.InitEmailRouter(ApiGroup) // 邮件相关路由 global.GVA_LOG.Info("router register success") return Router diff --git a/server/router/sys_email.go b/server/router/sys_email.go new file mode 100644 index 0000000000000000000000000000000000000000..6d201cf05261e75bcfb082abc3289c9ca1374d2e --- /dev/null +++ b/server/router/sys_email.go @@ -0,0 +1,14 @@ +package router + +import ( + "gin-vue-admin/api/v1" + "gin-vue-admin/middleware" + "github.com/gin-gonic/gin" +) + +func InitEmailRouter(Router *gin.RouterGroup) { + UserRouter := Router.Group("email").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler()) + { + UserRouter.POST("emailTest", v1.EmailTest) // 发送测试邮件 + } +} diff --git a/server/service/sys_email.go b/server/service/sys_email.go new file mode 100644 index 0000000000000000000000000000000000000000..0db1416f9c852f8c4da90b47ba61828207dffa9d --- /dev/null +++ b/server/service/sys_email.go @@ -0,0 +1,17 @@ +package service + +import ( + "gin-vue-admin/utils" +) + +// @title EmailTest +// @description 发送邮件测试 +// @auth (2020/09/08 13:58 +// @return err error + +func EmailTest() (err error) { + subject := "test" + body := "test" + err = utils.EmailTest(subject, body) + return err +} diff --git a/server/utils/email.go b/server/utils/email.go new file mode 100644 index 0000000000000000000000000000000000000000..7e87383a3d75b612544ee0f7e3615755aa14ee8d --- /dev/null +++ b/server/utils/email.go @@ -0,0 +1,50 @@ +package utils + +import ( + "fmt" + "strings" + "net/smtp" + "crypto/tls" + + "gin-vue-admin/global" + + "github.com/jordan-wright/email" +) + +func Email(subject string, body string) error { + to := strings.Split(global.GVA_CONFIG.Email.EmailTo, ",") + return send(to, subject, body) +} + +func EmailTest(subject string, body string) error { + to := []string{global.GVA_CONFIG.Email.EmailFrom} + return send(to, subject, body) +} + +func send(to []string, subject string, body string) error { + from := global.GVA_CONFIG.Email.EmailFrom + nickName := global.GVA_CONFIG.Email.EmailNickName + secret := global.GVA_CONFIG.Email.EmailSecret + host := global.GVA_CONFIG.Email.EmailHost + port := global.GVA_CONFIG.Email.EmailPort + isSSL := global.GVA_CONFIG.Email.EmailIsSSL + + auth := smtp.PlainAuth("", from, secret, host) + e := email.NewEmail() + if nickName == "" { + e.From = fmt.Sprintf("%s <%s>", nickName, from) + }else{ + e.From = from + } + e.To = to + e.Subject = subject + e.HTML = []byte(body) + var err error + hostAddr := fmt.Sprintf("%s:%d", host, port) + if isSSL { + err = e.SendWithTLS(hostAddr, auth, &tls.Config{ServerName: host}) + }else{ + err = e.Send(hostAddr, auth) + } + return err +} \ No newline at end of file diff --git a/web/src/api/email.js b/web/src/api/email.js new file mode 100644 index 0000000000000000000000000000000000000000..2502353334a4d0d47e9a615aadccbd5b700f77bb --- /dev/null +++ b/web/src/api/email.js @@ -0,0 +1,15 @@ +import service from '@/utils/request' + +// @Tags email +// @Summary 发送测试邮件 +// @Security ApiKeyAuth +// @Produce application/json +// @Success 200 {string} string "{"success":true,"data":{},"msg":"返回成功"}" +// @Router /email/emailTest [post] +export const emailTest = (data) => { + return service({ + url: "/email/emailTest", + method: 'post', + data + }) +} \ No newline at end of file diff --git a/web/src/view/systemTools/system/system.vue b/web/src/view/systemTools/system/system.vue index 4ec3aa4df6302fa7b1f1070ee34d29a717a572eb..5d2e791b7bf97860669369d8f66bcdb5e3f9777d 100644 --- a/web/src/view/systemTools/system/system.vue +++ b/web/src/view/systemTools/system/system.vue @@ -105,6 +105,31 @@ +

邮箱配置

+ + + + + + + + + + + + + + + + + + + + + + + 测试邮件 + 立即更新 重启服务(开发中) @@ -115,6 +140,7 @@