邮箱正则判断

This commit is contained in:
xmdhs 2023-11-25 16:36:38 +08:00
parent 2e4b8cb673
commit e1517d4243
No known key found for this signature in database
GPG Key ID: E809D6D43DEFCC95
7 changed files with 57 additions and 16 deletions

View File

@ -45,12 +45,14 @@ type EmailConfig struct {
Enable bool `toml:"enable" comment:"注册验证邮件,且允许使用邮箱找回账号"` Enable bool `toml:"enable" comment:"注册验证邮件,且允许使用邮箱找回账号"`
Smtp []SmtpUser `toml:"smtp"` Smtp []SmtpUser `toml:"smtp"`
AllowDomain []string `toml:"allow_domain" comment:"允许用于注册的邮箱域名,留空则允许全部"` AllowDomain []string `toml:"allow_domain" comment:"允许用于注册的邮箱域名,留空则允许全部"`
EmailReg string `toml:"email_reg" comment:"邮箱正则,留空则不处理,如 ^[0-9]+@qq.com$|^[^+\\.A-Z]+@gmail.com$"`
EmailRegMsg string `toml:"email_reg_msg" comment:"不满足要求时的提示信息"`
} }
type SmtpUser struct { type SmtpUser struct {
Host string `toml:"host"` Host string `toml:"host"`
Port int `toml:"port"` Port int `toml:"port"`
SSL bool `toml:"SSL"` SSL bool `toml:"SSL" comment:"启用 ssl"`
Name string `toml:"name"` Name string `toml:"name"`
Pass string `toml:"password"` Pass string `toml:"password"`
} }
@ -82,5 +84,9 @@ func Default() Config {
WebBaseUrl: "", WebBaseUrl: "",
ServerName: "没有设置名字", ServerName: "没有设置名字",
Captcha: Captcha{}, Captcha: Captcha{},
Email: EmailConfig{
Smtp: []SmtpUser{},
AllowDomain: []string{},
},
} }
} }

View File

@ -42,6 +42,8 @@ export interface ApiConfig {
serverName: string serverName: string
NeedEmail: boolean NeedEmail: boolean
AllowDomain: string[] AllowDomain: string[]
EmailReg: string
EmailRegMsg: string
} }
export interface UserInfo { export interface UserInfo {

View File

@ -77,6 +77,11 @@ export default function SendEmail({ title, anyEmail = false, sendService }: { ti
setHelperText("邮箱格式错误") setHelperText("邮箱格式错误")
return return
} }
if (!anyEmail && server.data?.EmailReg && server.data?.EmailReg != ""
&& !new RegExp(server.data?.EmailReg).test(sendEmail)) {
setHelperText(server.data?.EmailRegMsg ?? "邮箱不满足正则要求")
return
}
if (server.data?.captcha.type != "" && captchaToken == "") { if (server.data?.captcha.type != "" && captchaToken == "") {
return return

View File

@ -3,11 +3,15 @@ package handle
import ( import (
"bytes" "bytes"
"context" "context"
"errors"
"fmt" "fmt"
"image/png" "image/png"
"io" "io"
"log/slog" "log/slog"
"net/http" "net/http"
"regexp"
"strings"
"sync"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10" "github.com/go-playground/validator/v10"
@ -25,10 +29,16 @@ type UserHandel struct {
logger *slog.Logger logger *slog.Logger
textureService *service.TextureService textureService *service.TextureService
config config.Config config config.Config
emailReg func() (*regexp.Regexp, error)
} }
func NewUserHandel(handleError *handelerror.HandleError, validate *validator.Validate, func NewUserHandel(handleError *handelerror.HandleError, validate *validator.Validate,
userService *service.UserService, logger *slog.Logger, textureService *service.TextureService, config config.Config) *UserHandel { userService *service.UserService, logger *slog.Logger, textureService *service.TextureService, config config.Config) *UserHandel {
emailReg := sync.OnceValues[*regexp.Regexp, error](func() (*regexp.Regexp, error) {
return regexp.Compile(config.Email.EmailReg)
})
return &UserHandel{ return &UserHandel{
handleError: handleError, handleError: handleError,
validate: validate, validate: validate,
@ -36,6 +46,8 @@ func NewUserHandel(handleError *handelerror.HandleError, validate *validator.Val
logger: logger, logger: logger,
textureService: textureService, textureService: textureService,
config: config, config: config,
emailReg: emailReg,
} }
} }
@ -227,6 +239,8 @@ func (h *UserHandel) NeedEnableEmail(handle http.Handler) http.Handler {
}) })
} }
var ErrNotAllowDomain = errors.New("不在允许域名列表内")
func (h *UserHandel) SendRegEmail() http.HandlerFunc { func (h *UserHandel) SendRegEmail() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context() ctx := r.Context()
@ -235,6 +249,31 @@ func (h *UserHandel) SendRegEmail() http.HandlerFunc {
return return
} }
if len(h.config.Email.AllowDomain) != 0 {
allow := false
for _, v := range h.config.Email.AllowDomain {
if strings.HasSuffix(c.Email, v) {
allow = true
break
}
}
if !allow {
h.handleError.Error(ctx, w, "不在允许邮箱域名内", model.ErrInput, 400, slog.LevelDebug)
return
}
}
if h.config.Email.EmailReg != "" {
r, err := h.emailReg()
if err != nil {
h.handleError.Error(ctx, w, "正则错误", model.ErrUnknown, 500, slog.LevelError)
return
}
if !r.MatchString(c.Email) {
h.handleError.Error(ctx, w, "邮箱不符合正则要求", model.ErrInput, 400, slog.LevelDebug)
return
}
}
err := h.userService.SendRegEmail(ctx, c.Email, c.CaptchaToken, r.Host, ip) err := h.userService.SendRegEmail(ctx, c.Email, c.CaptchaToken, r.Host, ip)
if err != nil { if err != nil {
h.handleError.Service(ctx, w, err) h.handleError.Service(ctx, w, err)

View File

@ -65,6 +65,8 @@ type Config struct {
ServerName string `json:"serverName"` ServerName string `json:"serverName"`
NeedEmail bool NeedEmail bool
AllowDomain []string AllowDomain []string
EmailReg string
EmailRegMsg string
} }
type EditUser struct { type EditUser struct {

View File

@ -238,22 +238,7 @@ func (w *UserService) ChangeName(ctx context.Context, newName string, t *model.T
return nil return nil
} }
var ErrNotAllowDomain = errors.New("不在允许域名列表内")
func (w *UserService) SendRegEmail(ctx context.Context, email, CaptchaToken, host, ip string) error { func (w *UserService) SendRegEmail(ctx context.Context, email, CaptchaToken, host, ip string) error {
if len(w.config.Email.AllowDomain) != 0 {
allow := false
for _, v := range w.config.Email.AllowDomain {
if strings.HasSuffix(email, v) {
allow = true
break
}
}
if !allow {
return fmt.Errorf("SendRegEmail: %w", ErrNotAllowDomain)
}
}
err := w.captchaService.VerifyCaptcha(ctx, CaptchaToken, ip) err := w.captchaService.VerifyCaptcha(ctx, CaptchaToken, ip)
if err != nil { if err != nil {
return fmt.Errorf("SendRegEmail: %w", err) return fmt.Errorf("SendRegEmail: %w", err)

View File

@ -37,5 +37,7 @@ func (w *WebService) GetConfig(ctx context.Context) model.Config {
AllowChangeName: !w.config.OfflineUUID, AllowChangeName: !w.config.OfflineUUID,
NeedEmail: w.config.Email.Enable, NeedEmail: w.config.Email.Enable,
AllowDomain: w.config.Email.AllowDomain, AllowDomain: w.config.Email.AllowDomain,
EmailReg: w.config.Email.EmailReg,
EmailRegMsg: w.config.Email.EmailRegMsg,
} }
} }