package controllers import ( "encoding/json" "fmt" "io" "strconv" "strings" "server/models" "server/pkg/jwtutil" "server/services" beego "github.com/beego/beego/v2/server/web" ) // PlatformEmailController 系统邮箱配置(yz_system_email) type PlatformEmailController struct { beego.Controller } func (c *PlatformEmailController) platformClaims() (*jwtutil.Claims, error) { auth := c.Ctx.Request.Header.Get("Authorization") if auth == "" { return nil, fmt.Errorf("未登录") } parts := strings.SplitN(auth, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { return nil, fmt.Errorf("认证信息格式错误") } claims, err := jwtutil.ParseToken(parts[1]) if err != nil { return nil, fmt.Errorf("无效的token") } if claims.UserType != "platform" { return nil, fmt.Errorf("无权访问") } return claims, nil } func (c *PlatformEmailController) jsonErr(httpStatus, bizCode int, msg string) { c.Ctx.Output.SetStatus(httpStatus) c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg} _ = c.ServeJSON() } func emailRowToMap(m models.SystemEmail) map[string]interface{} { out := map[string]interface{}{ "id": m.ID, "from_address": m.FromAddress, "host": m.Host, "port": m.Port, "password": m.Password, "encryption": m.Encryption, "timeout": m.Timeout, "status": m.Status, "create_time": m.CreateTime.Format("2006-01-02 15:04:05"), "update_time": m.UpdateTime.Format("2006-01-02 15:04:05"), } if m.FromName != nil { out["from_name"] = *m.FromName } else { out["from_name"] = "" } if m.Remark != nil { out["remark"] = *m.Remark } else { out["remark"] = "" } return out } // GetInfo GET /platform/email/info func (c *PlatformEmailController) GetInfo() { if _, err := c.platformClaims(); err != nil { c.jsonErr(401, 401, err.Error()) return } rows, err := services.ListSystemEmails() if err != nil { c.jsonErr(500, 500, "获取邮箱配置失败: "+err.Error()) return } list := make([]map[string]interface{}, 0, len(rows)) for i := range rows { list = append(list, emailRowToMap(rows[i])) } c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": list} _ = c.ServeJSON() } type emailFormPayload struct { FromAddress string `json:"fromAddress"` FromName string `json:"fromName"` Host string `json:"host"` Port interface{} `json:"port"` Password string `json:"password"` Encryption string `json:"encryption"` Timeout interface{} `json:"timeout"` } type testEmailPayload struct { emailFormPayload TestEmail string `json:"testEmail"` } func parseUintFlexible(v interface{}) uint { if v == nil { return 0 } switch x := v.(type) { case float64: if x < 0 { return 0 } return uint(x) case string: n, err := parseUintString(x) if err != nil { return 0 } return n default: return 0 } } func parseUintString(s string) (uint, error) { s = strings.TrimSpace(s) if s == "" { return 0, fmt.Errorf("empty") } n, err := strconv.ParseUint(s, 10, 32) if err != nil { return 0, err } return uint(n), nil } func normalizeEncryption(s string) string { s = strings.ToLower(strings.TrimSpace(s)) switch s { case "ssl", "tls", "none": return s default: return "ssl" } } // EditInfo POST /platform/email/editinfo func (c *PlatformEmailController) EditInfo() { if _, err := c.platformClaims(); err != nil { c.jsonErr(401, 401, err.Error()) return } raw, err := io.ReadAll(c.Ctx.Request.Body) if err != nil { c.jsonErr(400, 400, "参数错误") return } var p emailFormPayload if uerr := json.Unmarshal(raw, &p); uerr != nil { c.jsonErr(400, 400, "参数错误") return } from := strings.TrimSpace(p.FromAddress) host := strings.TrimSpace(p.Host) if from == "" || host == "" { c.jsonErr(400, 400, "发件人邮箱与 SMTP 主机不能为空") return } port := parseUintFlexible(p.Port) if port == 0 { port = 465 } timeout := parseUintFlexible(p.Timeout) if timeout == 0 { timeout = 30 } enc := normalizeEncryption(p.Encryption) cnt, cerr := models.Orm.QueryTable(new(models.SystemEmail)).Count() if cerr != nil { c.jsonErr(500, 500, "读取邮箱配置失败: "+cerr.Error()) return } if strings.TrimSpace(p.Password) == "" && cnt == 0 { c.jsonErr(400, 400, "授权码/密码不能为空") return } var fn *string if strings.TrimSpace(p.FromName) != "" { s := strings.TrimSpace(p.FromName) fn = &s } err = services.UpsertFirstSystemEmail(from, fn, host, port, strings.TrimSpace(p.Password), enc, timeout, 1, nil) if err != nil { c.jsonErr(500, 500, "保存邮箱配置失败: "+err.Error()) return } c.Data["json"] = map[string]interface{}{"code": 200, "msg": "保存成功"} _ = c.ServeJSON() } // SendTestEmail POST /platform/email/sendtestemail func (c *PlatformEmailController) SendTestEmail() { if _, err := c.platformClaims(); err != nil { c.jsonErr(401, 401, err.Error()) return } raw, err := io.ReadAll(c.Ctx.Request.Body) if err != nil { c.jsonErr(400, 400, "参数错误") return } var p testEmailPayload if uerr := json.Unmarshal(raw, &p); uerr != nil { c.jsonErr(400, 400, "参数错误") return } to := strings.TrimSpace(p.TestEmail) if to == "" { c.jsonErr(400, 400, "测试收件邮箱不能为空") return } from := strings.TrimSpace(p.FromAddress) host := strings.TrimSpace(p.Host) if from == "" || host == "" { c.jsonErr(400, 400, "发件人邮箱与 SMTP 主机不能为空") return } port := parseUintFlexible(p.Port) if port == 0 { port = 465 } timeout := parseUintFlexible(p.Timeout) if timeout == 0 { timeout = 30 } enc := normalizeEncryption(p.Encryption) pass := strings.TrimSpace(p.Password) if pass == "" { rows, lerr := services.ListSystemEmails() if lerr == nil && len(rows) > 0 { pass = rows[0].Password } } if pass == "" { c.jsonErr(400, 400, "授权码/密码不能为空(请填写或先保存配置)") return } cfg := services.SMTPConfig{ FromAddress: from, FromName: strings.TrimSpace(p.FromName), Host: host, Port: port, Password: pass, Encryption: enc, Timeout: timeout, } if err := services.SendTestEmailSMTP(cfg, to); err != nil { c.jsonErr(500, 500, "发送失败: "+err.Error()) return } c.Data["json"] = map[string]interface{}{"code": 200, "msg": "发送成功"} _ = c.ServeJSON() }