Merge pull request #665 from samwafgo/feat_recipient_mail

feat:add recipient mail
This commit is contained in:
samwafgo
2026-01-30 17:24:19 +08:00
committed by GitHub
9 changed files with 98 additions and 5 deletions
+1
View File
@@ -16,6 +16,7 @@ type NotifyLog struct {
MessageType string `json:"message_type"` // 消息类型
MessageTitle string `json:"message_title"` // 消息标题
MessageContent string `json:"message_content"` // 消息内容
Recipients string `json:"recipients"` // 收件人(仅邮件类型)
Status int `json:"status"` // 发送状态:1成功,0失败
ErrorMsg string `json:"error_msg"` // 错误信息
SendTime string `json:"send_time"` // 发送时间
+1
View File
@@ -12,6 +12,7 @@ type NotifySubscription struct {
baseorm.BaseOrm
ChannelId string `json:"channel_id"` // 关联的渠道ID
MessageType string `json:"message_type"` // 消息类型:user_login, attack_info, weekly_report等
Recipients string `json:"recipients"` // 收件人列表(逗号分隔,主要用于邮件类型)留空则使用渠道默认收件人
Status int `json:"status"` // 状态:1启用,0禁用
FilterJSON string `json:"filter_json"` // 过滤条件(JSON格式)
Remarks string `json:"remarks"` // 备注
@@ -4,6 +4,7 @@ package request
type WafNotifySubscriptionAddReq struct {
ChannelId string `json:"channel_id" binding:"required"`
MessageType string `json:"message_type" binding:"required"`
Recipients string `json:"recipients"`
Status int `json:"status"`
FilterJSON string `json:"filter_json"`
Remarks string `json:"remarks"`
@@ -14,6 +15,7 @@ type WafNotifySubscriptionEditReq struct {
Id string `json:"id" binding:"required"`
ChannelId string `json:"channel_id" binding:"required"`
MessageType string `json:"message_type" binding:"required"`
Recipients string `json:"recipients"`
Status int `json:"status"`
FilterJSON string `json:"filter_json"`
Remarks string `json:"remarks"`
+2 -1
View File
@@ -15,7 +15,7 @@ type WafNotifyLogService struct{}
var WafNotifyLogServiceApp = new(WafNotifyLogService)
// AddLog 添加通知日志
func (receiver *WafNotifyLogService) AddLog(channelId, channelName, channelType, messageType, messageTitle, messageContent string, status int, errorMsg string) error {
func (receiver *WafNotifyLogService) AddLog(channelId, channelName, channelType, messageType, messageTitle, messageContent string, recipients string, status int, errorMsg string) error {
var bean = &model.NotifyLog{
BaseOrm: baseorm.BaseOrm{
Id: uuid.GenUUID(),
@@ -30,6 +30,7 @@ func (receiver *WafNotifyLogService) AddLog(channelId, channelName, channelType,
MessageType: messageType,
MessageTitle: messageTitle,
MessageContent: messageContent,
Recipients: recipients,
Status: status,
ErrorMsg: errorMsg,
SendTime: time.Now().Format("2006-01-02 15:04:05"),
+26 -3
View File
@@ -10,6 +10,7 @@ import (
"SamWaf/wafnotify/feishu"
"SamWaf/wafnotify/serverchan"
"fmt"
"strings"
)
type WafNotifySenderService struct{}
@@ -35,8 +36,8 @@ func (receiver *WafNotifySenderService) SendNotification(messageType, title, con
continue
}
// 发送通知
go receiver.sendToChannel(channel, messageType, title, content)
// 发送通知(传入subscription以支持订阅级收件人)
go receiver.sendToChannel(channel, subscription, messageType, title, content)
}
}
@@ -46,10 +47,11 @@ func (receiver *WafNotifySenderService) getChannelById(channelId string, channel
}
// sendToChannel 发送到具体渠道
func (receiver *WafNotifySenderService) sendToChannel(channel model.NotifyChannel, messageType, title, content string) {
func (receiver *WafNotifySenderService) sendToChannel(channel model.NotifyChannel, subscription model.NotifySubscription, messageType, title, content string) {
var err error
status := 1
errorMsg := ""
recipients := "" // 用于记录实际使用的收件人
switch channel.Type {
case "dingtalk":
@@ -63,6 +65,26 @@ func (receiver *WafNotifySenderService) sendToChannel(channel model.NotifyChanne
if notifierErr != nil {
err = notifierErr
} else {
// 关键:支持订阅级别的收件人配置(向后兼容)
if subscription.Recipients != "" {
// 优先使用订阅中配置的收件人
recipientList := strings.Split(subscription.Recipients, ",")
var trimmedRecipients []string
for _, r := range recipientList {
trimmed := strings.TrimSpace(r)
if trimmed != "" {
trimmedRecipients = append(trimmedRecipients, trimmed)
}
}
if len(trimmedRecipients) > 0 {
notifier.SetRecipients(trimmedRecipients)
recipients = strings.Join(trimmedRecipients, ", ") // 记录实际收件人
}
} else {
// 使用渠道默认收件人(从notifier获取)
recipients = strings.Join(notifier.ToEmails, ", ")
}
// 如果订阅中没有配置收件人,则使用渠道配置中的收件人(向后兼容)
err = notifier.SendMarkdown(title, content)
}
case "serverchan":
@@ -90,6 +112,7 @@ func (receiver *WafNotifySenderService) sendToChannel(channel model.NotifyChanne
messageType,
title,
content,
recipients, // 传递收件人信息
status,
errorMsg,
)
@@ -26,6 +26,7 @@ func (receiver *WafNotifySubscriptionService) AddApi(req request.WafNotifySubscr
},
ChannelId: req.ChannelId,
MessageType: req.MessageType,
Recipients: req.Recipients,
Status: req.Status,
FilterJSON: req.FilterJSON,
Remarks: req.Remarks,
@@ -43,6 +44,7 @@ func (receiver *WafNotifySubscriptionService) ModifyApi(req request.WafNotifySub
editMap := map[string]interface{}{
"ChannelId": req.ChannelId,
"MessageType": req.MessageType,
"Recipients": req.Recipients,
"Status": req.Status,
"FilterJSON": req.FilterJSON,
"Remarks": req.Remarks,
@@ -90,7 +92,7 @@ func (receiver *WafNotifySubscriptionService) GetListApi(req request.WafNotifySu
whereValues = append(whereValues, req.Status)
}
global.GWAF_LOCAL_DB.Model(&model.NotifySubscription{}).Where(whereField, whereValues...).Limit(req.PageSize).Offset(req.PageSize * (req.PageIndex - 1)).Find(&list)
global.GWAF_LOCAL_DB.Model(&model.NotifySubscription{}).Where(whereField, whereValues...).Limit(req.PageSize).Order("create_time desc").Offset(req.PageSize * (req.PageIndex - 1)).Find(&list)
global.GWAF_LOCAL_DB.Model(&model.NotifySubscription{}).Where(whereField, whereValues...).Count(&total)
return list, total, nil
+28
View File
@@ -483,6 +483,34 @@ func RunCoreDBMigrations(db *gorm.DB) error {
return nil
},
},
// 迁移13: 为 notify_subscription 表添加 recipients 字段(订阅级收件人)
{
ID: "202601300001_add_notify_subscription_recipients",
Migrate: func(tx *gorm.DB) error {
zlog.Info("迁移 202601300001: 为 notify_subscription 表添加 recipients 字段")
// 检查字段是否已存在
if tx.Migrator().HasColumn(&model.NotifySubscription{}, "recipients") {
zlog.Info("recipients 字段已存在,跳过添加")
return nil
}
// 添加字段,默认值为空字符串(表示使用渠道默认收件人)
if err := tx.Migrator().AddColumn(&model.NotifySubscription{}, "recipients"); err != nil {
return fmt.Errorf("添加 recipients 字段失败: %w", err)
}
zlog.Info("recipients 字段添加成功(空值时将使用渠道配置的默认收件人,保持向后兼容)")
return nil
},
Rollback: func(tx *gorm.DB) error {
zlog.Info("回滚 202601300001: 删除 notify_subscription 表的 recipients 字段")
if tx.Migrator().HasColumn(&model.NotifySubscription{}, "recipients") {
return tx.Migrator().DropColumn(&model.NotifySubscription{}, "recipients")
}
return nil
},
},
})
// 执行迁移
+28
View File
@@ -108,6 +108,34 @@ func RunLogDBMigrations(db *gorm.DB) error {
)
},
},
// 迁移4: 为 notify_log 表添加 recipients 字段(记录邮件收件人)
{
ID: "202601300002_add_notify_log_recipients",
Migrate: func(tx *gorm.DB) error {
zlog.Info("迁移 202601300002: 为 notify_log 表添加 recipients 字段")
// 检查字段是否已存在
if tx.Migrator().HasColumn(&model.NotifyLog{}, "recipients") {
zlog.Info("recipients 字段已存在,跳过添加")
return nil
}
// 添加字段
if err := tx.Migrator().AddColumn(&model.NotifyLog{}, "recipients"); err != nil {
return fmt.Errorf("添加 recipients 字段失败: %w", err)
}
zlog.Info("recipients 字段添加成功(用于记录邮件通知的实际收件人)")
return nil
},
Rollback: func(tx *gorm.DB) error {
zlog.Info("回滚 202601300002: 删除 notify_log 表的 recipients 字段")
if tx.Migrator().HasColumn(&model.NotifyLog{}, "recipients") {
return tx.Migrator().DropColumn(&model.NotifyLog{}, "recipients")
}
return nil
},
},
})
// 执行迁移
+7
View File
@@ -79,6 +79,13 @@ func NewEmailNotifier(configJSON string) (*EmailNotifier, error) {
}, nil
}
// SetRecipients 设置收件人(用于订阅级别的收件人配置)
func (e *EmailNotifier) SetRecipients(recipients []string) {
if len(recipients) > 0 {
e.ToEmails = recipients
}
}
// SendMarkdown 发送Markdown格式消息(转换为HTML)
func (e *EmailNotifier) SendMarkdown(title, content string) error {
// 将Markdown格式转换为简单的HTML