Files
goodBaby/drivers/email/accountConfigChecker.go
T
meiandClaude Fable 5 79774070fc feat: 完善后端并新增 Vue3 WebUI
后端:
- 修复登录校验、DB 并发(单例+WAL+纯Go sqlite)、会话密钥持久化等核心缺陷
- 新增 Timer CRUD/签到/手动触发、执行日志、仪表盘、驱动元数据等 API
- 统一驱动接口: 带 context 的执行器、真实错误返回、敏感字段掩码、连通性测试
- 补全钉钉执行器; Timer 触发/提醒去重; 配置支持默认值与环境变量覆盖

前端:
- Vite+Vue3+TS+Pinia+Element Plus, 由驱动元数据动态渲染配置表单
- 登录/仪表盘(倒计时环)/定时器/规则/账号/日志/设置页面, 支持暗色模式
- 主题色 #66ccff, 信号波纹 logo, go:embed 单二进制部署

构建: Dockerfile 增加前端构建阶段; 补充各驱动配置文档

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 22:19:41 +08:00

114 lines
3.7 KiB
Go
Raw 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 email
import (
"context"
"encoding/json"
"fmt"
"net/mail"
"github.com/ssdomei232/goodBaby/internal/meta"
"github.com/ssdomei232/goodBaby/internal/retry"
)
// EmailAccountConfigValidator 邮箱账号配置验证器
type EmailAccountConfigValidator struct{}
func (v *EmailAccountConfigValidator) GetType() string {
return AccountType
}
func (v *EmailAccountConfigValidator) Validate(config string) error {
cfg, err := parseAccountConfig(config)
if err != nil {
return err
}
if cfg.SMTPServer == "" {
return fmt.Errorf("邮箱账号配置中 SMTP 服务器不能为空")
}
if cfg.Port <= 0 || cfg.Port > 65535 {
return fmt.Errorf("邮箱账号配置中 SMTP 端口不合法")
}
if cfg.Username == "" {
return fmt.Errorf("邮箱账号配置中用户名不能为空")
}
if cfg.Password == "" {
return fmt.Errorf("邮箱账号配置中密码不能为空")
}
switch cfg.SecurityOrDefault() {
case SecuritySSL, SecuritySTARTTLS, SecurityNone:
default:
return fmt.Errorf("不支持的加密方式: %s", cfg.Security)
}
if cfg.From != "" {
if _, err := mail.ParseAddress(cfg.From); err != nil {
return fmt.Errorf("发件人地址不合法: %s", cfg.From)
}
}
if cfg.TestDestination != "" {
if _, err := mail.ParseAddress(cfg.TestDestination); err != nil {
return fmt.Errorf("测试收件地址不合法: %s", cfg.TestDestination)
}
}
return nil
}
// Test 连接 SMTP 服务器并完成认证;填写了测试收件地址时会真的发一封测试邮件
func (v *EmailAccountConfigValidator) Test(config string) error {
cfg, err := parseAccountConfig(config)
if err != nil {
return err
}
client, err := newSMTPClient(cfg)
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(context.Background(), retry.TestTimeout)
defer cancel()
if cfg.TestDestination == "" {
if err := client.DialWithContext(ctx); err != nil {
return fmt.Errorf("连接 SMTP 服务器失败: %w", err)
}
return client.Close()
}
message, err := buildMessage(cfg, cfg.TestDestination, "goodBaby 测试邮件", "这是一封来自 goodBaby 的测试邮件,收到即表示邮箱账号配置正确。")
if err != nil {
return err
}
if err := client.DialAndSendWithContext(ctx, message); err != nil {
return fmt.Errorf("发送测试邮件失败: %w", err)
}
return nil
}
func (v *EmailAccountConfigValidator) Meta() meta.AccountMeta {
return meta.AccountMeta{
Type: AccountType,
Label: "邮箱 (SMTP)",
Description: "配置一个用于发信的 SMTP 账号。",
Docs: "docs/email-config.md",
Fields: []meta.Field{
{Key: "smtp_server", Label: "SMTP 服务器", Type: meta.FieldString, Required: true, Placeholder: "smtp.example.com"},
{Key: "port", Label: "端口", Type: meta.FieldNumber, Required: true, Default: 465, Help: "SSL 一般为 465,STARTTLS 一般为 587"},
{Key: "security", Label: "加密方式", Type: meta.FieldString, Required: false, Default: SecuritySSL, Help: "可选 ssl / starttls / none,留空按 ssl 处理"},
{Key: "username", Label: "用户名", Type: meta.FieldString, Required: true, Placeholder: "you@example.com"},
{Key: "password", Label: "密码 / 授权码", Type: meta.FieldPassword, Required: true, Secret: true},
{Key: "from", Label: "发件人地址", Type: meta.FieldString, Help: "留空则使用用户名作为发件人"},
{Key: "test_destination", Label: "测试收件地址", Type: meta.FieldString, Help: "填写后点击“测试”会真的发送一封测试邮件"},
},
}
}
func parseAccountConfig(config string) (*EmailAccountConfig, error) {
var cfg EmailAccountConfig
if err := json.Unmarshal([]byte(config), &cfg); err != nil {
return nil, fmt.Errorf("解析邮箱账号配置失败: %v", err)
}
return &cfg, nil
}