docs(README): 更新文档为中文并完善API参考

- 将README从英文翻译为中文
- 添加详细的API参考文档,包括所有管理接口和枚举值说明
- 补充安装、快速开始、认证方式等使用指南

refactor(client): 优化客户端代码结构并添加详细注释

- 为所有API方法添加中文注释和使用说明
- 改进Client结构体和Option配置的设计
- 统一错误处理和响应结构的文档说明
This commit is contained in:
shiran
2026-04-18 15:54:19 +08:00
parent fe19922eff
commit fe43b9bdce
15 changed files with 1013 additions and 291 deletions
+247 -145
View File
@@ -2,7 +2,14 @@ package emailcli
import "time"
// PaginationResult is the generic paginated response wrapper.
// PaginationResult 是分页接口的统一返回结构。
//
// {
// "list": [...], // 当前页数据
// "total": 123, // 总记录数
// "page": 1,
// "page_size": 20
// }
type PaginationResult[T any] struct {
List []T `json:"list"`
Total int64 `json:"total"`
@@ -10,13 +17,17 @@ type PaginationResult[T any] struct {
PageSize int `json:"page_size"`
}
// PaginationQuery 是所有列表接口的分页参数基类,
// 业务 Query 结构体可通过嵌入来复用。
// - Page: 页码,从 1 开始;省略时后端默认 1
// - PageSize: 每页大小,省略时后端默认 20,最大 100
type PaginationQuery struct {
Page int `json:"page,omitempty"`
PageSize int `json:"page_size,omitempty"`
}
// --- GormModel fields ---
// GormModel 对应后端 gorm.Model。注意后端该部分没有自定义 json tag,
// 因此字段使用 PascalCase 序列化(与数据库模型保持一致)。
type GormModel struct {
ID uint `json:"ID"`
CreatedAt time.Time `json:"CreatedAt"`
@@ -24,84 +35,104 @@ type GormModel struct {
DeletedAt *time.Time `json:"DeletedAt"`
}
// --- Account ---
// ============================================================
// Account 邮件账号
// ============================================================
// Account 表示一个邮件发送账号。
// AppKey 用于发件认证;AppSecret 只在创建或重置时返回一次,
// 入库时以 bcrypt 保存,SDK 不会回传。
type Account struct {
GormModel
UserID int `json:"user_id"`
Name string `json:"name"`
AppKey string `json:"app_key"`
Status int8 `json:"status"`
AuditMode int8 `json:"audit_mode"`
RateLimit int `json:"rate_limit"`
AllowedChannels string `json:"allowed_channels"`
DefaultSignatureID *uint `json:"default_signature_id"`
Remark string `json:"remark"`
UserID int `json:"user_id"` // 关联主平台用户 ID
Name string `json:"name"` // 账号名称
AppKey string `json:"app_key"` // 发件公钥
Status int8 `json:"status"` // 账号状态: 0=禁用 1=启用
AuditMode int8 `json:"audit_mode"` // 审核模式: 0=免审核 1=自动 2=人工
RateLimit int `json:"rate_limit"` // 频率限制(封/分钟),0 表示不限
DefaultChannelID *uint `json:"default_channel_id"` // 默认发件通道 ID
AllowedChannels string `json:"allowed_channels"` // 允许的通道 ID 列表 JSON 字符串,如 "[1,2]";空串=不限
DefaultSignatureID *uint `json:"default_signature_id"` // 默认签名 ID
Remark string `json:"remark"` // 备注
}
// CreateAccountReq 是创建账号的请求体。
type CreateAccountReq struct {
UserID int `json:"user_id"`
Name string `json:"name"`
AuditMode *int8 `json:"audit_mode,omitempty"`
RateLimit *int `json:"rate_limit,omitempty"`
Remark string `json:"remark,omitempty"`
UserID int `json:"user_id"` // 必填,关联用户 ID
Name string `json:"name"` // 必填,账号名称,≤100
AuditMode *int8 `json:"audit_mode,omitempty"` // 可选,默认 0 免审核
RateLimit *int `json:"rate_limit,omitempty"` // 可选,0=不限
DefaultChannelID *uint `json:"default_channel_id,omitempty"` // 可选,默认发件通道 ID
AllowedChannels string `json:"allowed_channels,omitempty"` // 可选,允许通道 ID 列表的 JSON 字符串
Remark string `json:"remark,omitempty"` // 可选,备注
}
// CreateAccountResp 是创建账号后的返回,AppSecret 仅此一次明文展示。
type CreateAccountResp struct {
ID uint `json:"id"`
AppKey string `json:"app_key"`
AppSecret string `json:"app_secret"`
AppSecret string `json:"app_secret"` // 明文密钥,务必妥善保存
Name string `json:"name"`
}
// UpdateAccountReq 所有字段均为可选;只对传入字段做局部更新。
type UpdateAccountReq struct {
Name *string `json:"name,omitempty"`
Status *int8 `json:"status,omitempty"`
AuditMode *int8 `json:"audit_mode,omitempty"`
RateLimit *int `json:"rate_limit,omitempty"`
AllowedChannels *string `json:"allowed_channels,omitempty"`
DefaultSignatureID *uint `json:"default_signature_id,omitempty"`
Status *int8 `json:"status,omitempty"` // 0=禁用 1=启用
AuditMode *int8 `json:"audit_mode,omitempty"` // 0=免审核 1=自动 2=人工
RateLimit *int `json:"rate_limit,omitempty"` // 封/分钟,0=不限
DefaultChannelID *uint `json:"default_channel_id,omitempty"` // 默认发件通道 ID
AllowedChannels *string `json:"allowed_channels,omitempty"` // 允许通道 ID 列表 JSON
DefaultSignatureID *uint `json:"default_signature_id,omitempty"` // 默认签名 ID
Remark *string `json:"remark,omitempty"`
}
// AccountListQuery 是账号列表过滤参数。
type AccountListQuery struct {
PaginationQuery
UserID *int `json:"user_id,omitempty"`
Status *int8 `json:"status,omitempty"`
Keyword string `json:"keyword,omitempty"`
UserID *int `json:"user_id,omitempty"` // 按用户过滤
Status *int8 `json:"status,omitempty"` // 0=禁用 1=启用
Keyword string `json:"keyword,omitempty"` // 模糊匹配 name / remark
}
// ResetSecretResp 是重置密钥后的返回。
type ResetSecretResp struct {
AppSecret string `json:"app_secret"`
AppSecret string `json:"app_secret"` // 新生成的明文密钥
}
// --- Signature ---
// ============================================================
// Signature 签名
// ============================================================
// Signature 表示一个邮件签名。
// EnglishName 会作为 From 地址的 local 部分组装发件人(签名@域名)。
type Signature struct {
GormModel
UserID int `json:"user_id"`
AccountID *uint `json:"account_id"`
Title string `json:"title"`
EnglishName string `json:"english_name"`
Content string `json:"content"`
Applicant string `json:"applicant"`
ApplicantInfo string `json:"applicant_info"`
Status int8 `json:"status"`
AccountID *uint `json:"account_id"` // 为空表示用户全局签名
Title string `json:"title"` // 中文抬头
EnglishName string `json:"english_name"` // 英文标识(用于拼 From 地址)
Content string `json:"content"` // HTML 签名正文
Applicant string `json:"applicant"` // 申请人
ApplicantInfo string `json:"applicant_info"` // 申请说明
Status int8 `json:"status"` // 0=待审核 1=已通过 2=已驳回
RejectReason string `json:"reject_reason"`
Auditor string `json:"auditor"`
AuditedAt *time.Time `json:"audited_at"`
}
// CreateSignatureReq 是创建签名的请求体。新建签名默认 Status=0(待审核)。
type CreateSignatureReq struct {
UserID int `json:"user_id"`
AccountID *uint `json:"account_id,omitempty"`
Title string `json:"title"`
EnglishName string `json:"english_name"`
Content string `json:"content,omitempty"`
Applicant string `json:"applicant,omitempty"`
ApplicantInfo string `json:"applicant_info,omitempty"`
UserID int `json:"user_id"` // 必填
AccountID *uint `json:"account_id,omitempty"` // 可选,绑定账号
Title string `json:"title"` // 必填,中文抬头
EnglishName string `json:"english_name"` // 必填,英文标识
Content string `json:"content,omitempty"` // HTML 签名内容
Applicant string `json:"applicant,omitempty"` // 申请人
ApplicantInfo string `json:"applicant_info,omitempty"` // 申请说明
}
// UpdateSignatureReq 局部更新签名字段。
type UpdateSignatureReq struct {
Title *string `json:"title,omitempty"`
EnglishName *string `json:"english_name,omitempty"`
@@ -110,64 +141,79 @@ type UpdateSignatureReq struct {
ApplicantInfo *string `json:"applicant_info,omitempty"`
}
// AuditSignatureReq 是审核签名的请求体。
type AuditSignatureReq struct {
Status int8 `json:"status"`
RejectReason string `json:"reject_reason,omitempty"`
Status int8 `json:"status"` // 1=通过 2=驳回
RejectReason string `json:"reject_reason,omitempty"` // 驳回时填写
}
// SignatureListQuery 是签名列表过滤参数。
type SignatureListQuery struct {
PaginationQuery
AccountID *uint `json:"account_id,omitempty"`
Status *int8 `json:"status,omitempty"`
Status *int8 `json:"status,omitempty"` // 0=待审核 1=已通过 2=已驳回
UserID *int `json:"user_id,omitempty"`
Keyword string `json:"keyword,omitempty"`
Keyword string `json:"keyword,omitempty"` // 模糊匹配 title / english_name
}
// --- Mail ---
// ============================================================
// Mail 发送邮件
// ============================================================
// SendMailReq 是 POST /api/v1/mail/send 的请求体。
//
// Channel 为空时,后端按以下顺序自动选择:
// 1. Account.DefaultChannelID 对应的已启用通道;
// 2. Account.AllowedChannels 列表中的首个已启用通道。
type SendMailReq struct {
To []string `json:"to"`
Cc []string `json:"cc,omitempty"`
Bcc []string `json:"bcc,omitempty"`
Subject string `json:"subject"`
Body string `json:"body"`
ContentType string `json:"content_type,omitempty"`
Channel string `json:"channel"`
SignatureID *uint `json:"signature_id,omitempty"`
SignatureTitle string `json:"signature_title,omitempty"`
Attachments []AttachmentItem `json:"attachments,omitempty"`
To []string `json:"to"` // 必填,收件人列表(至少 1 个)
Cc []string `json:"cc,omitempty"` // 抄送
Bcc []string `json:"bcc,omitempty"` // 密送
Subject string `json:"subject"` // 必填,主题
Body string `json:"body"` // 必填,正文
ContentType string `json:"content_type,omitempty"` // text/plain 或 text/html,默认 text/html
Channel string `json:"channel,omitempty"` // 通道 code;留空走默认/允许通道
SignatureID *uint `json:"signature_id,omitempty"` // 指定签名 ID(优先级低于 title)
SignatureTitle string `json:"signature_title,omitempty"` // 按 title + user_id 查找已审核签名
Attachments []AttachmentItem `json:"attachments,omitempty"` // 附件
}
// AttachmentItem 附件项,Content 为 base64 编码字符串。
type AttachmentItem struct {
Filename string `json:"filename"`
Content string `json:"content"`
Filename string `json:"filename"` // 文件名(含扩展名)
Content string `json:"content"` // base64 编码的文件内容
}
// SendMailResp 是发送邮件的返回结果。
type SendMailResp struct {
MailLogID uint `json:"mail_log_id"`
Status string `json:"status"`
MailLogID uint `json:"mail_log_id"` // 创建的邮件日志 ID
Status string `json:"status"` // queued / pending_audit / rejected
}
// --- Mail Log ---
// ============================================================
// MailLog 邮件日志
// ============================================================
// MailLog 邮件日志记录。
// Status 枚举:0=待审核 1=排队中 2=发送中 3=成功 4=失败 5=放弃 6=驳回
type MailLog struct {
GormModel
UserID int `json:"user_id"`
AccountID uint `json:"account_id"`
QuotaID *uint `json:"quota_id"`
ChannelID *uint `json:"channel_id"`
SenderAccountID *uint `json:"sender_account_id"`
QuotaID *uint `json:"quota_id"` // 扣减的配额记录 ID
ChannelID *uint `json:"channel_id"` // 使用的发件通道 ID
SenderAccountID *uint `json:"sender_account_id"` // 实际使用的发信账号 ID
SignatureID *uint `json:"signature_id"`
MessageID string `json:"message_id"`
FromAddress string `json:"from_address"`
ToAddresses string `json:"to_addresses"`
CcAddresses string `json:"cc_addresses"`
BccAddresses string `json:"bcc_addresses"`
MessageID string `json:"message_id"` // SMTP 返回的 Message-ID
FromAddress string `json:"from_address"` // 实际 From 地址
ToAddresses string `json:"to_addresses"` // JSON 字符串数组
CcAddresses string `json:"cc_addresses"` // JSON 字符串数组
BccAddresses string `json:"bcc_addresses"` // JSON 字符串数组
Subject string `json:"subject"`
ContentType string `json:"content_type"`
HasAttachment bool `json:"has_attachment"`
SourceIP string `json:"source_ip"`
SourceType string `json:"source_type"`
SourceIP string `json:"source_ip"` // 请求来源 IP
SourceType string `json:"source_type"` // http / smtp
Status int8 `json:"status"`
RetryCount int `json:"retry_count"`
MaxRetry int `json:"max_retry"`
@@ -175,51 +221,61 @@ type MailLog struct {
SentAt *time.Time `json:"sent_at"`
}
// MailLogListQuery 是邮件日志列表过滤参数。
type MailLogListQuery struct {
PaginationQuery
UserID *int `json:"user_id,omitempty"`
AccountID *uint `json:"account_id,omitempty"`
Status *int8 `json:"status,omitempty"`
StartDate string `json:"start_date,omitempty"`
EndDate string `json:"end_date,omitempty"`
To string `json:"to,omitempty"`
Keyword string `json:"keyword,omitempty"`
Status *int8 `json:"status,omitempty"` // 见 MailLog.Status 枚举
StartDate string `json:"start_date,omitempty"` // 格式 YYYY-MM-DD
EndDate string `json:"end_date,omitempty"` // 格式 YYYY-MM-DD
To string `json:"to,omitempty"` // 精确匹配收件人
Keyword string `json:"keyword,omitempty"` // 模糊匹配主题/收件人
}
// MailLogDetail 邮件日志详情,包含完整正文。
type MailLogDetail struct {
Log MailLog `json:"log"`
Body string `json:"body"`
Body string `json:"body"` // 邮件正文
}
// MailStatItem 按状态分组的邮件计数,用于概览统计。
type MailStatItem struct {
Status int8 `json:"status"`
Count int64 `json:"count"`
}
// --- Quota ---
// ============================================================
// Quota 配额
// ============================================================
// MailQuota 配额记录。
// - QuotaType=1 总量:Total 为生命周期内的总配额
// - QuotaType=2 周期:每个 CycleUnit 周期重置 Used
type MailQuota struct {
GormModel
UserID int `json:"user_id"`
AccountID uint `json:"account_id"`
QuotaType int8 `json:"quota_type"`
QuotaType int8 `json:"quota_type"` // 1=总量 2=周期
Total int `json:"total"`
Used int `json:"used"`
ExpireAt *time.Time `json:"expire_at"`
CycleUnit string `json:"cycle_unit"`
CycleResetAt *time.Time `json:"cycle_reset_at"`
Status int8 `json:"status"`
ExpireAt *time.Time `json:"expire_at"` // 到期时间,仅总量配额有意义
CycleUnit string `json:"cycle_unit"` // day/week/month/year
CycleResetAt *time.Time `json:"cycle_reset_at"` // 周期起始时间
Status int8 `json:"status"` // 0=禁用 1=启用
}
// CreateQuotaReq 创建配额。
type CreateQuotaReq struct {
AccountID uint `json:"account_id"`
QuotaType int8 `json:"quota_type"`
Total int `json:"total"`
ExpireAt string `json:"expire_at,omitempty"`
CycleUnit string `json:"cycle_unit,omitempty"`
CycleResetAt string `json:"cycle_reset_at,omitempty"`
AccountID uint `json:"account_id"` // 必填
QuotaType int8 `json:"quota_type"` // 必填,1=总量 2=周期
Total int `json:"total"` // 必填,配额上限
ExpireAt string `json:"expire_at,omitempty"` // YYYY-MM-DD HH:mm:ss
CycleUnit string `json:"cycle_unit,omitempty"` // day/week/month/year
CycleResetAt string `json:"cycle_reset_at,omitempty"` // 周期起点
}
// UpdateQuotaReq 局部更新配额。
type UpdateQuotaReq struct {
Total *int `json:"total,omitempty"`
Status *int8 `json:"status,omitempty"`
@@ -228,6 +284,7 @@ type UpdateQuotaReq struct {
CycleResetAt *string `json:"cycle_reset_at,omitempty"`
}
// QuotaListQuery 配额列表过滤参数。
type QuotaListQuery struct {
PaginationQuery
AccountID *uint `json:"account_id,omitempty"`
@@ -235,32 +292,38 @@ type QuotaListQuery struct {
Status *int8 `json:"status,omitempty"`
}
// QuotaSummary 指定账号的配额汇总信息。
type QuotaSummary struct {
AccountID uint `json:"account_id"`
TotalQuota int `json:"total_quota"`
TotalUsed int `json:"total_used"`
TotalRemaining int `json:"total_remaining"`
Details []MailQuota `json:"details"`
TotalQuota int `json:"total_quota"` // 所有配额累加总量
TotalUsed int `json:"total_used"` // 已用
TotalRemaining int `json:"total_remaining"` // 剩余
Details []MailQuota `json:"details"` // 每条配额明细
}
// --- Channel ---
// ============================================================
// Channel 通道
// ============================================================
// Channel 发件通道,一个通道下可挂多个 SenderAccount,由 Strategy 决定分发逻辑。
type Channel struct {
GormModel
Name string `json:"name"`
Code string `json:"code"`
Code string `json:"code"` // 唯一标识,发件请求中 channel 字段填这个
Description string `json:"description"`
Strategy string `json:"strategy"`
Status int8 `json:"status"`
Strategy string `json:"strategy"` // round_robin / weight / least_used
Status int8 `json:"status"` // 0=禁用 1=启用
}
// CreateChannelReq 创建通道。
type CreateChannelReq struct {
Name string `json:"name"`
Code string `json:"code"`
Name string `json:"name"` // 必填
Code string `json:"code"` // 必填,唯一
Description string `json:"description,omitempty"`
Strategy string `json:"strategy,omitempty"`
Strategy string `json:"strategy,omitempty"` // 默认 round_robin
}
// UpdateChannelReq 局部更新通道。
type UpdateChannelReq struct {
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
@@ -268,14 +331,18 @@ type UpdateChannelReq struct {
Status *int8 `json:"status,omitempty"`
}
// ChannelListQuery 通道列表过滤参数。
type ChannelListQuery struct {
PaginationQuery
Status *int8 `json:"status,omitempty"`
Keyword string `json:"keyword,omitempty"`
Keyword string `json:"keyword,omitempty"` // 模糊匹配 name / code
}
// --- Sender Account ---
// ============================================================
// SenderAccount 发信账号(SMTP
// ============================================================
// SenderAccount 挂在某个 Channel 下的 SMTP 发信账号。
type SenderAccount struct {
GormModel
ChannelID uint `json:"channel_id"`
@@ -286,27 +353,29 @@ type SenderAccount struct {
SmtpSSL bool `json:"smtp_ssl"`
FromName string `json:"from_name"`
FromAddress string `json:"from_address"`
DailyLimit int `json:"daily_limit"`
DailySent int `json:"daily_sent"`
Weight int `json:"weight"`
Status int8 `json:"status"`
DailyLimit int `json:"daily_limit"` // 每日发送上限,0=不限
DailySent int `json:"daily_sent"` // 当日已发送数
Weight int `json:"weight"` // Strategy=weight 时使用
Status int8 `json:"status"` // 0=禁用 1=启用
LastCheckAt *time.Time `json:"last_check_at"`
LastCheckResult string `json:"last_check_result"`
}
// CreateSenderReq 创建发信账号。Password 只存密文,不会回显。
type CreateSenderReq struct {
Name string `json:"name"`
SmtpHost string `json:"smtp_host"`
SmtpPort int `json:"smtp_port"`
SmtpUser string `json:"smtp_user"`
SmtpPassword string `json:"smtp_password"`
Name string `json:"name"` // 必填
SmtpHost string `json:"smtp_host"` // 必填
SmtpPort int `json:"smtp_port"` // 必填
SmtpUser string `json:"smtp_user"` // 必填
SmtpPassword string `json:"smtp_password"` // 必填
SmtpSSL *bool `json:"smtp_ssl,omitempty"`
FromName string `json:"from_name,omitempty"`
FromAddress string `json:"from_address"`
FromAddress string `json:"from_address"` // 必填
DailyLimit *int `json:"daily_limit,omitempty"`
Weight *int `json:"weight,omitempty"`
}
// UpdateSenderReq 局部更新发信账号。
type UpdateSenderReq struct {
Name *string `json:"name,omitempty"`
SmtpHost *string `json:"smtp_host,omitempty"`
@@ -321,91 +390,108 @@ type UpdateSenderReq struct {
Status *int8 `json:"status,omitempty"`
}
// SenderListQuery 发信账号列表过滤参数。
type SenderListQuery struct {
PaginationQuery
Status *int8 `json:"status,omitempty"`
Keyword string `json:"keyword,omitempty"`
}
// --- Audit ---
// ============================================================
// Audit 审核
// ============================================================
// MailAudit 邮件审核记录。
type MailAudit struct {
GormModel
MailLogID uint `json:"mail_log_id"`
UserID int `json:"user_id"`
AccountID uint `json:"account_id"`
AuditType int8 `json:"audit_type"`
Action int8 `json:"action"`
AuditType int8 `json:"audit_type"` // 1=自动 2=人工
Action int8 `json:"action"` // 1=通过 2=驳回
RejectReason string `json:"reject_reason"`
HitRules string `json:"hit_rules"`
HitRules string `json:"hit_rules"` // 命中规则列表 JSON
Auditor string `json:"auditor"`
AuditedAt time.Time `json:"audited_at"`
}
// AuditPendingQuery 待审核列表过滤参数。
type AuditPendingQuery struct {
PaginationQuery
UserID *int `json:"user_id,omitempty"`
AccountID *uint `json:"account_id,omitempty"`
Keyword string `json:"keyword,omitempty"`
Keyword string `json:"keyword,omitempty"` // 模糊匹配主题/收件人
}
// AuditLogQuery 审核记录列表过滤参数。
type AuditLogQuery struct {
PaginationQuery
AuditType *int8 `json:"audit_type,omitempty"`
Action *int8 `json:"action,omitempty"`
AuditType *int8 `json:"audit_type,omitempty"` // 1=自动 2=人工
Action *int8 `json:"action,omitempty"` // 1=通过 2=驳回
UserID *int `json:"user_id,omitempty"`
StartDate string `json:"start_date,omitempty"`
EndDate string `json:"end_date,omitempty"`
StartDate string `json:"start_date,omitempty"` // YYYY-MM-DD
EndDate string `json:"end_date,omitempty"` // YYYY-MM-DD
}
// AuditRejectReq 驳回审核请求体。
type AuditRejectReq struct {
RejectReason string `json:"reject_reason"`
RejectReason string `json:"reject_reason"` // 建议填写驳回原因
}
// BatchAuditApproveReq 批量通过请求体。
type BatchAuditApproveReq struct {
MailLogIDs []uint `json:"mail_log_ids"`
}
// BatchAuditRejectReq 批量驳回请求体。
type BatchAuditRejectReq struct {
MailLogIDs []uint `json:"mail_log_ids"`
RejectReason string `json:"reject_reason"`
}
// AuditStats 审核概览统计(用于仪表盘)。
type AuditStats struct {
PendingCount int64 `json:"pending_count"`
TodayDetails []AuditDetailCount `json:"today_details"`
PendingCount int64 `json:"pending_count"` // 待审核数量
TodayDetails []AuditDetailCount `json:"today_details"` // 今日按 type/action 分组
}
// AuditDetailCount 按 AuditType+Action 分组的计数。
type AuditDetailCount struct {
AuditType int8 `json:"audit_type"`
Action int8 `json:"action"`
Count int64 `json:"count"`
}
// --- Audit Rule ---
// ============================================================
// AuditRule 审核规则
// ============================================================
// AuditRule 审核规则。自动审核会按 Priority 从高到低依次评估,
// 命中即返回 Action。
type AuditRule struct {
GormModel
Name string `json:"name"`
RuleType string `json:"rule_type"`
Target string `json:"target"`
Condition string `json:"condition"`
Action int8 `json:"action"`
Priority int `json:"priority"`
Status int8 `json:"status"`
RuleType string `json:"rule_type"` // keyword/regex/domain
Target string `json:"target"` // subject/body/to/from
Condition string `json:"condition"` // 关键词或正则
Action int8 `json:"action"` // 1=自动通过 2=自动驳回 3=转人工
Priority int `json:"priority"` // 数字越大优先级越高
Status int8 `json:"status"` // 0=禁用 1=启用
Remark string `json:"remark"`
}
// CreateAuditRuleReq 创建规则。
type CreateAuditRuleReq struct {
Name string `json:"name"`
RuleType string `json:"rule_type"`
Target string `json:"target"`
Condition string `json:"condition"`
Action int8 `json:"action"`
Name string `json:"name"` // 必填
RuleType string `json:"rule_type"` // 必填,keyword/regex/domain
Target string `json:"target"` // 必填,subject/body/to/from
Condition string `json:"condition"` // 必填
Action int8 `json:"action"` // 必填,1/2/3
Priority *int `json:"priority,omitempty"`
Remark string `json:"remark,omitempty"`
}
// UpdateAuditRuleReq 局部更新规则。
type UpdateAuditRuleReq struct {
Name *string `json:"name,omitempty"`
RuleType *string `json:"rule_type,omitempty"`
@@ -417,6 +503,7 @@ type UpdateAuditRuleReq struct {
Remark *string `json:"remark,omitempty"`
}
// TestAuditRuleReq 在不发送邮件的前提下测试规则命中情况。
type TestAuditRuleReq struct {
Subject string `json:"subject,omitempty"`
Body string `json:"body,omitempty"`
@@ -425,24 +512,32 @@ type TestAuditRuleReq struct {
AccountID uint `json:"account_id,omitempty"`
}
// TestAuditRuleResp 规则测试结果。
type TestAuditRuleResp struct {
Action string `json:"action"`
HitRules []HitRuleEntry `json:"hit_rules"`
Action string `json:"action"` // approve/reject/to_manual/none
HitRules []HitRuleEntry `json:"hit_rules"` // 命中的规则列表
}
// HitRuleEntry 命中规则信息。
type HitRuleEntry struct {
RuleID uint `json:"rule_id"`
RuleName string `json:"rule_name"`
RuleType string `json:"rule_type"`
}
// --- Queue ---
// ============================================================
// Queue 发送队列
// ============================================================
// QueueStatusData 队列状态快照。
// - Queues: key = 通道 code, value = 该通道排队长度
// - DelayQueue: 延迟重试队列长度
type QueueStatusData struct {
Queues map[string]int `json:"queues"`
DelayQueue int `json:"delay_queue"`
}
// QueuePendingQuery 队列待发送邮件过滤参数。
type QueuePendingQuery struct {
PaginationQuery
ChannelID *uint `json:"channel_id,omitempty"`
@@ -450,20 +545,25 @@ type QueuePendingQuery struct {
AccountID *uint `json:"account_id,omitempty"`
}
// --- Check ---
// ============================================================
// Check 健康检查
// ============================================================
// CheckLog 发信账号健康检查记录。
// 通过向 verification 地址发测试邮件并等待 webhook 回调验证收信可用性。
type CheckLog struct {
ID uint `json:"id"`
SenderAccountID uint `json:"sender_account_id"`
VerificationCode string `json:"verification_code"`
SentAt time.Time `json:"sent_at"`
Received bool `json:"received"`
Received bool `json:"received"` // 是否收到回执
ReceivedAt *time.Time `json:"received_at"`
LatencyMs int `json:"latency_ms"`
LatencyMs int `json:"latency_ms"` // 端到端延迟,毫秒
ErrorMessage string `json:"error_message"`
CreatedAt time.Time `json:"created_at"`
}
// CheckLogQuery 健康检查日志过滤参数。
type CheckLogQuery struct {
PaginationQuery
SenderAccountID *uint `json:"sender_account_id,omitempty"`
@@ -471,6 +571,7 @@ type CheckLogQuery struct {
EndDate string `json:"end_date,omitempty"`
}
// SenderHealth 发信账号健康汇总。
type SenderHealth struct {
SenderAccountID uint `json:"sender_account_id"`
Name string `json:"name"`
@@ -481,8 +582,9 @@ type SenderHealth struct {
SuccessChecks int64 `json:"success_checks"`
}
// TriggerCheckResp 手动触发健康检查的返回。
type TriggerCheckResp struct {
Result string `json:"result"`
Result string `json:"result"` // ok / failed
Error string `json:"error,omitempty"`
CheckLog *CheckLog `json:"check_log,omitempty"`
}