package service import ( "fmt" "html" "strings" "time" ) func buildContentModerationViolationEmailBody(siteName string, log *ContentModerationLog, cfg *ContentModerationConfig) string { if log == nil { return "" } userName := strings.TrimSpace(log.UserEmail) if userName == "" && log.UserID != nil { userName = fmt.Sprintf("UID %d", *log.UserID) } threshold := cfg.BanThreshold if threshold <= 0 { threshold = defaultContentModerationBanThreshold } statusBlock := "" if log.AutoBanned { statusBlock = `
账户当前处于封禁状态,所有 API 请求将被拒绝
` } return fmt.Sprintf(`
Risk Control / 风控提醒

账户触发内容审计规则

尊敬的用户 %s,您的 API 请求在内容审计中触发平台风控策略。详情如下。

触发详情

触发时间%s
触发来源内容审核
所属分组%s
命中类别%s / %.3f
累计触发次数%d 次(阈值 %d)
%s

此邮件由 %s 自动发送,请勿回复。

`, html.EscapeString(userName), html.EscapeString(time.Now().Format("2006-01-02 15:04:05")), html.EscapeString(defaultContentModerationString(log.GroupName, "-")), html.EscapeString(defaultContentModerationString(log.HighestCategory, "-")), log.HighestScore, log.ViolationCount, threshold, statusBlock, html.EscapeString(siteName), ) } func buildContentModerationAccountDisabledEmailBody(siteName string, log *ContentModerationLog, cfg *ContentModerationConfig) string { if log == nil { return "" } userName := strings.TrimSpace(log.UserEmail) if userName == "" && log.UserID != nil { userName = fmt.Sprintf("UID %d", *log.UserID) } threshold := cfg.BanThreshold if threshold <= 0 { threshold = defaultContentModerationBanThreshold } return fmt.Sprintf(`
Risk Control / 账户封禁

账户已被自动禁用

尊敬的用户 %s,您的账户在计数周期内多次触发平台风控策略,系统已自动禁用该账户。详情如下。

封禁详情

封禁时间%s
触发来源内容审核
所属分组%s
命中类别%s / %.3f
累计触发次数%d 次(阈值 %d)
账户当前处于封禁状态,所有 API 请求将被拒绝

如需申诉或恢复账号,请联系平台管理员处理。

此邮件由 %s 自动发送,请勿回复。

`, html.EscapeString(userName), html.EscapeString(time.Now().Format("2006-01-02 15:04:05")), html.EscapeString(defaultContentModerationString(log.GroupName, "-")), html.EscapeString(defaultContentModerationString(log.HighestCategory, "-")), log.HighestScore, log.ViolationCount, threshold, html.EscapeString(siteName), ) } func defaultContentModerationString(value string, fallback string) string { if strings.TrimSpace(value) == "" { return fallback } return strings.TrimSpace(value) } // buildCyberPolicyNoticeEmailBody 是 cyber_policy 通知邮件的内置兜底正文, // 当 notification email 模板渲染失败时使用(与 sendViolationEmail 的兜底同理)。 func buildCyberPolicyNoticeEmailBody(siteName string, log *ContentModerationLog) string { if log == nil { return "" } userName := strings.TrimSpace(log.UserEmail) if userName == "" && log.UserID != nil { userName = fmt.Sprintf("UID %d", *log.UserID) } return fmt.Sprintf(`
Risk Control / 网络安全策略

请求被网络安全策略拦截

尊敬的用户 %s,您的请求被上游网络安全策略(cyber policy)拦截。

触发时间%s
模型%s
上游说明%s

如认为系误判,可调整请求措辞后重试,或申请获得授权的安全访问权限。

此邮件由 %s 自动发送,请勿回复。

`, html.EscapeString(userName), html.EscapeString(log.CreatedAt.Format("2006-01-02 15:04:05")), html.EscapeString(defaultContentModerationString(log.Model, "-")), html.EscapeString(defaultContentModerationString(log.Error, "-")), html.EscapeString(siteName), ) }