新增支持LoginAuth认证方式适用于IBM、微软等部分邮箱服务 (#2041)

This commit is contained in:
计乐心
2025-06-05 11:31:25 +08:00
committed by GitHub
parent ba63bf2371
commit 174721bc55
7 changed files with 74 additions and 23 deletions

View File

@@ -1,11 +1,12 @@
package config package config
type Email struct { type Email struct {
To string `mapstructure:"to" json:"to" yaml:"to"` // 收件人:多个以英文逗号分隔 例a@qq.com b@qq.com 正式开发中请把此项目作为参数使用 To string `mapstructure:"to" json:"to" yaml:"to"` // 收件人:多个以英文逗号分隔 例a@qq.com b@qq.com 正式开发中请把此项目作为参数使用
From string `mapstructure:"from" json:"from" yaml:"from"` // 发件人 你自己要发邮件的邮箱 From string `mapstructure:"from" json:"from" yaml:"from"` // 发件人 你自己要发邮件的邮箱
Host string `mapstructure:"host" json:"host" yaml:"host"` // 服务器地址 例如 smtp.qq.com 请前往QQ或者你要发邮件的邮箱查看其smtp协议 Host string `mapstructure:"host" json:"host" yaml:"host"` // 服务器地址 例如 smtp.qq.com 请前往QQ或者你要发邮件的邮箱查看其smtp协议
Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` // 密钥 用于登录的密钥 最好不要用邮箱密码 去邮箱smtp申请一个用于登录的密钥 Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` // 密钥 用于登录的密钥 最好不要用邮箱密码 去邮箱smtp申请一个用于登录的密钥
Nickname string `mapstructure:"nickname" json:"nickname" yaml:"nickname"` // 昵称 发件人昵称 通常为自己的邮箱 Nickname string `mapstructure:"nickname" json:"nickname" yaml:"nickname"` // 昵称 发件人昵称 通常为自己的邮箱
Port int `mapstructure:"port" json:"port" yaml:"port"` // 端口 请前往QQ或者你要发邮件的邮箱查看其smtp协议 大多为 465 Port int `mapstructure:"port" json:"port" yaml:"port"` // 端口 请前往QQ或者你要发邮件的邮箱查看其smtp协议 大多为 465
IsSSL bool `mapstructure:"is-ssl" json:"is-ssl" yaml:"is-ssl"` // 是否SSL 是否开启SSL IsSSL bool `mapstructure:"is-ssl" json:"is-ssl" yaml:"is-ssl"` // 是否SSL 是否开启SSL
IsLoginAuth bool `mapstructure:"is-loginauth" json:"is-loginauth" yaml:"is-loginauth"` // 是否LoginAuth 是否使用LoginAuth认证方式适用于IBM、微软邮箱服务器等
} }

View File

@@ -2,6 +2,7 @@ package initialize
import ( import (
"fmt" "fmt"
"github.com/flipped-aurora/gin-vue-admin/server/global" "github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/plugin/email" "github.com/flipped-aurora/gin-vue-admin/server/plugin/email"
"github.com/flipped-aurora/gin-vue-admin/server/utils/plugin" "github.com/flipped-aurora/gin-vue-admin/server/utils/plugin"
@@ -29,6 +30,7 @@ func bizPluginV1(group ...*gin.RouterGroup) {
global.GVA_CONFIG.Email.Nickname, global.GVA_CONFIG.Email.Nickname,
global.GVA_CONFIG.Email.Port, global.GVA_CONFIG.Email.Port,
global.GVA_CONFIG.Email.IsSSL, global.GVA_CONFIG.Email.IsSSL,
global.GVA_CONFIG.Email.IsLoginAuth,
)) ))
holder(public, private) holder(public, private)
} }

View File

@@ -14,6 +14,7 @@
global.GVA_CONFIG.Email.Nickname, global.GVA_CONFIG.Email.Nickname,
global.GVA_CONFIG.Email.Port, global.GVA_CONFIG.Email.Port,
global.GVA_CONFIG.Email.IsSSL, global.GVA_CONFIG.Email.IsSSL,
global.GVA_CONFIG.Email.IsLoginAuth,
)) ))
同样也可以再传入时写死 同样也可以再传入时写死
@@ -26,6 +27,7 @@
"登录密钥", "登录密钥",
465, 465,
true, true,
true,
)) ))
### 2. 配置说明 ### 2. 配置说明
@@ -34,13 +36,14 @@
//其中 Form 和 Secret 通常来说就是用户名和密码 //其中 Form 和 Secret 通常来说就是用户名和密码
type Email struct { type Email struct {
To string // 收件人:多个以英文逗号分隔 例a@qq.com b@qq.com 正式开发中请把此项目作为参数使用 此处配置主要用于发送错误监控邮件 To string // 收件人:多个以英文逗号分隔 例a@qq.com b@qq.com 正式开发中请把此项目作为参数使用 此处配置主要用于发送错误监控邮件
From string // 发件人 你自己要发邮件的邮箱 From string // 发件人 你自己要发邮件的邮箱
Host string // 服务器地址 例如 smtp.qq.com 请前往QQ或者你要发邮件的邮箱查看其smtp协议 Host string // 服务器地址 例如 smtp.qq.com 请前往QQ或者你要发邮件的邮箱查看其smtp协议
Secret string // 密钥 用于登录的密钥 最好不要用邮箱密码 去邮箱smtp申请一个用于登录的密钥 Secret string // 密钥 用于登录的密钥 最好不要用邮箱密码 去邮箱smtp申请一个用于登录的密钥
Nickname string // 昵称 发件人昵称 自定义即可 可以不填 Nickname string // 昵称 发件人昵称 自定义即可 可以不填
Port int // 端口 请前往QQ或者你要发邮件的邮箱查看其smtp协议 大多为 465 Port int // 端口 请前往QQ或者你要发邮件的邮箱查看其smtp协议 大多为 465
IsSSL bool // 是否SSL 是否开启SSL IsSSL bool // 是否SSL 是否开启SSL
IsLoginAuth bool // 是否LoginAuth 是否使用LoginAuth认证方式适用于IBM、微软邮箱服务器等
} }
#### 2-2 入参结构说明 #### 2-2 入参结构说明
//其中 Form 和 Secret 通常来说就是用户名和密码 //其中 Form 和 Secret 通常来说就是用户名和密码

View File

@@ -1,11 +1,12 @@
package config package config
type Email struct { type Email struct {
To string `mapstructure:"to" json:"to" yaml:"to"` // 收件人:多个以英文逗号分隔 例a@qq.com b@qq.com 正式开发中请把此项目作为参数使用 To string `mapstructure:"to" json:"to" yaml:"to"` // 收件人:多个以英文逗号分隔 例a@qq.com b@qq.com 正式开发中请把此项目作为参数使用
From string `mapstructure:"from" json:"from" yaml:"from"` // 发件人 你自己要发邮件的邮箱 From string `mapstructure:"from" json:"from" yaml:"from"` // 发件人 你自己要发邮件的邮箱
Host string `mapstructure:"host" json:"host" yaml:"host"` // 服务器地址 例如 smtp.qq.com 请前往QQ或者你要发邮件的邮箱查看其smtp协议 Host string `mapstructure:"host" json:"host" yaml:"host"` // 服务器地址 例如 smtp.qq.com 请前往QQ或者你要发邮件的邮箱查看其smtp协议
Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` // 密钥 用于登录的密钥 最好不要用邮箱密码 去邮箱smtp申请一个用于登录的密钥 Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` // 密钥 用于登录的密钥 最好不要用邮箱密码 去邮箱smtp申请一个用于登录的密钥
Nickname string `mapstructure:"nickname" json:"nickname" yaml:"nickname"` // 昵称 发件人昵称 通常为自己的邮箱 Nickname string `mapstructure:"nickname" json:"nickname" yaml:"nickname"` // 昵称 发件人昵称 通常为自己的邮箱
Port int `mapstructure:"port" json:"port" yaml:"port"` // 端口 请前往QQ或者你要发邮件的邮箱查看其smtp协议 大多为 465 Port int `mapstructure:"port" json:"port" yaml:"port"` // 端口 请前往QQ或者你要发邮件的邮箱查看其smtp协议 大多为 465
IsSSL bool `mapstructure:"is-ssl" json:"isSSL" yaml:"is-ssl"` // 是否SSL 是否开启SSL IsSSL bool `mapstructure:"is-ssl" json:"isSSL" yaml:"is-ssl"` // 是否SSL 是否开启SSL
IsLoginAuth bool `mapstructure:"is-loginauth" json:"is-loginauth" yaml:"is-loginauth"` // 是否LoginAuth 是否使用LoginAuth认证
} }

View File

@@ -8,7 +8,7 @@ import (
type emailPlugin struct{} type emailPlugin struct{}
func CreateEmailPlug(To, From, Host, Secret, Nickname string, Port int, IsSSL bool) *emailPlugin { func CreateEmailPlug(To, From, Host, Secret, Nickname string, Port int, IsSSL bool, IsLoginAuth bool) *emailPlugin {
global.GlobalConfig.To = To global.GlobalConfig.To = To
global.GlobalConfig.From = From global.GlobalConfig.From = From
global.GlobalConfig.Host = Host global.GlobalConfig.Host = Host
@@ -16,6 +16,7 @@ func CreateEmailPlug(To, From, Host, Secret, Nickname string, Port int, IsSSL bo
global.GlobalConfig.Nickname = Nickname global.GlobalConfig.Nickname = Nickname
global.GlobalConfig.Port = Port global.GlobalConfig.Port = Port
global.GlobalConfig.IsSSL = IsSSL global.GlobalConfig.IsSSL = IsSSL
global.GlobalConfig.IsLoginAuth = IsLoginAuth
return &emailPlugin{} return &emailPlugin{}
} }

View File

@@ -60,8 +60,14 @@ func send(to []string, subject string, body string) error {
host := global.GlobalConfig.Host host := global.GlobalConfig.Host
port := global.GlobalConfig.Port port := global.GlobalConfig.Port
isSSL := global.GlobalConfig.IsSSL isSSL := global.GlobalConfig.IsSSL
isLoginAuth := global.GlobalConfig.IsLoginAuth
auth := smtp.PlainAuth("", from, secret, host) var auth smtp.Auth
if isLoginAuth {
auth = LoginAuth(from, secret)
} else {
auth = smtp.PlainAuth("", from, secret, host)
}
e := email.NewEmail() e := email.NewEmail()
if nickname != "" { if nickname != "" {
e.From = fmt.Sprintf("%s <%s>", nickname, from) e.From = fmt.Sprintf("%s <%s>", nickname, from)
@@ -80,3 +86,37 @@ func send(to []string, subject string, body string) error {
} }
return err return err
} }
// LoginAuth 用于IBM、微软邮箱服务器的LOGIN认证方式
type loginAuth struct {
username, password string
}
func LoginAuth(username, password string) smtp.Auth {
return &loginAuth{username, password}
}
func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
return "LOGIN", []byte{}, nil
}
func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
if more {
switch string(fromServer) {
case "Username:":
return []byte(a.username), nil
case "Password:":
return []byte(a.password), nil
default:
// 邮箱服务器可能发送的其他提示信息
prompt := strings.ToLower(string(fromServer))
if strings.Contains(prompt, "username") || strings.Contains(prompt, "user") {
return []byte(a.username), nil
}
if strings.Contains(prompt, "password") || strings.Contains(prompt, "pass") {
return []byte(a.password), nil
}
}
}
return nil, nil
}

View File

@@ -202,6 +202,9 @@
<el-form-item label="是否为ssl"> <el-form-item label="是否为ssl">
<el-switch v-model="config.email['is-ssl']" /> <el-switch v-model="config.email['is-ssl']" />
</el-form-item> </el-form-item>
<el-form-item label="是否LoginAuth认证">
<el-switch v-model="config.email['is-loginauth']" />
</el-form-item>
<el-form-item label="secret"> <el-form-item label="secret">
<el-input <el-input
v-model.trim="config.email.secret" v-model.trim="config.email.secret"