go-platform/controllers/platform_email.go
2026-04-01 15:15:21 +08:00

266 lines
6.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()
}