fix: 优化邮件推送,防止邮件轰炸攻击
This commit is contained in:
1 parent
0ad0eb7927
commit
faacb3f5e3
2 files changed
+39
-1
No files matched your search
@@ -59,7 +59,13 @@ func (c *Client) EnqueueOrderStatusEmail(payload OrderStatusEmailPayload, opts .
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
options := append([]asynq.Option{asynq.Queue(c.defaultQueue)}, opts...)
|
||||
// 限制重试次数与保留期,避免 SMTP 长时间不可用时邮件任务堆积成雪崩;
|
||||
// 调用方可通过 opts 覆盖。
|
||||
options := append([]asynq.Option{
|
||||
asynq.Queue(c.defaultQueue),
|
||||
asynq.MaxRetry(3),
|
||||
asynq.Retention(24 * time.Hour),
|
||||
}, opts...)
|
||||
_, err = c.client.Enqueue(task, options...)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -74,6 +74,23 @@ func (c *Consumer) handleOrderStatusEmail(_ context.Context, task *asynq.Task) e
|
||||
logger.Debugw("worker_order_status_email_skip_invalid_payload", "order_id", payload.OrderID)
|
||||
return nil
|
||||
}
|
||||
// 消费侧二次校验开关:避免 SMTP/订单通知关闭后,旧任务(含 retry/scheduled 中的任务)继续触发发送。
|
||||
if c.SettingService != nil && c.Config != nil {
|
||||
smtpSetting, smtpErr := c.SettingService.GetSMTPSetting(c.Config.Email)
|
||||
if smtpErr != nil {
|
||||
// fail-closed:读不到设置就视作关闭,不重试,避免 DB 抖动放大成邮件雪崩。
|
||||
logger.Warnw("worker_order_status_email_load_smtp_setting_failed", "order_id", payload.OrderID, "error", smtpErr)
|
||||
return nil
|
||||
}
|
||||
if !smtpSetting.Enabled || !smtpSetting.OrderNotificationEnabled {
|
||||
logger.Debugw("worker_order_status_email_skip_setting_disabled",
|
||||
"order_id", payload.OrderID,
|
||||
"smtp_enabled", smtpSetting.Enabled,
|
||||
"order_notification_enabled", smtpSetting.OrderNotificationEnabled,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
order, err := c.OrderRepo.GetByID(payload.OrderID)
|
||||
if err != nil {
|
||||
logger.Warnw("worker_order_status_email_fetch_order_failed", "order_id", payload.OrderID, "error", err)
|
||||
@@ -83,6 +100,21 @@ func (c *Consumer) handleOrderStatusEmail(_ context.Context, task *asynq.Task) e
|
||||
logger.Debugw("worker_order_status_email_skip_order_not_found", "order_id", payload.OrderID)
|
||||
return nil
|
||||
}
|
||||
// 游客订单的"取消"通知价值极低(用户大概率已离开),但极易被滥用为退信轰炸载体:
|
||||
// 攻击者可用伪造邮箱批量下单等过期取消触发发送。统一不发,保留登录用户与其它状态。
|
||||
if order.UserID == 0 {
|
||||
emailStatus := strings.TrimSpace(payload.Status)
|
||||
if emailStatus == "" {
|
||||
emailStatus = order.Status
|
||||
}
|
||||
if emailStatus == constants.OrderStatusCanceled {
|
||||
logger.Debugw("worker_order_status_email_skip_guest_canceled",
|
||||
"order_id", order.ID,
|
||||
"order_no", order.OrderNo,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
var receiverEmail string
|
||||
var locale string
|
||||
if order.UserID != 0 {
|
||||
|
||||
Reference in new issue
Block a user