postfix_log_parser/events/
cleanup.rs

1//! Cleanup邮件清理模块
2//!
3//! 处理Postfix cleanup守护进程的事件,包括邮件内容处理、头部重写和队列准备
4
5use serde::{Deserialize, Serialize};
6
7/// Cleanup组件事件
8/// 基于896,788个真实生产数据分析,cleanup组件占4.5%的日志
9/// cleanup主要负责邮件内容处理、重写和清理
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub enum CleanupEvent {
12    /// Message-ID处理 - 最常见的cleanup事件
13    MessageId {
14        queue_id: String,
15        message_id: String,
16    },
17
18    /// 队列文件操作警告
19    QueueFileWarning {
20        operation: String,    // 如 "mail_queue_enter"
21        file_path: String,    // 如 "incoming/635139.92"
22        error_reason: String, // 如 "Permission denied"
23    },
24
25    /// 邮件内容重写
26    /// cleanup可能会重写邮件头、地址等
27    MessageRewrite {
28        queue_id: String,
29        rewrite_type: String, // 重写类型
30        original: String,     // 原始内容
31        rewritten: String,    // 重写后内容
32    },
33
34    /// 邮件大小信息
35    /// cleanup处理邮件时会记录大小信息
36    MessageSize {
37        queue_id: String,
38        size: u64, // 邮件大小(字节)
39    },
40
41    /// 邮件头处理
42    /// cleanup处理各种邮件头
43    HeaderProcessing {
44        queue_id: String,
45        header_name: String,  // 头字段名
46        header_value: String, // 头字段值
47        action: String,       // 动作 (add, remove, replace)
48    },
49
50    /// 邮件过滤器处理
51    /// 与milter等过滤器交互的事件
52    FilterAction {
53        queue_id: String,
54        filter_name: String,     // 过滤器名称
55        action: String,          // 过滤器动作
56        details: Option<String>, // 详细信息
57    },
58
59    /// 地址重写
60    /// cleanup可能重写发件人或收件人地址
61    AddressRewrite {
62        queue_id: String,
63        address_type: String, // "from" 或 "to"
64        original_address: String,
65        rewritten_address: String,
66    },
67
68    /// 邮件拒绝
69    /// cleanup阶段的邮件拒绝
70    MessageReject {
71        queue_id: String,
72        reason: String, // 拒绝原因
73        action: String, // 拒绝动作
74    },
75
76    /// 资源限制警告
77    /// 磁盘空间、内存等资源限制
78    ResourceLimit {
79        resource_type: String, // 资源类型
80        limit_details: String, // 限制详情
81        current_value: Option<u64>,
82        limit_value: Option<u64>,
83    },
84
85    /// Milter交互
86    /// 与邮件过滤器的交互事件
87    MilterInteraction {
88        queue_id: String,
89        milter_name: String,      // milter名称
90        command: String,          // milter命令
91        response: Option<String>, // milter响应
92    },
93
94    /// 配置警告
95    /// cleanup相关的配置问题
96    ConfigurationWarning {
97        warning_type: String, // 警告类型
98        message: String,      // 警告消息
99    },
100
101    /// 统计信息
102    /// cleanup处理统计
103    Statistics {
104        processed: Option<u32>, // 处理的邮件数
105        rejected: Option<u32>,  // 拒绝的邮件数
106        errors: Option<u32>,    // 错误数
107    },
108
109    /// Snowflake ID生成器初始化
110    /// 记录唯一ID生成器的初始化配置
111    SnowflakeInit {
112        node_id: u32,   // 节点ID
113        node_bits: u32, // 节点位数
114        seq_bits: u32,  // 序列位数
115    },
116
117    /// 邮件隔离/保留事件
118    /// 当邮件被隔离或保留时记录的事件
119    MessageHold {
120        queue_id: String,
121        hold_reason: String, // 保留原因,如 "header X-Decision-Result: Quarantine"
122        sender: Option<String>, // 发件人地址(统一命名)
123        recipient: Option<String>, // 收件人地址(统一命名)
124        client_ip: Option<String>, // 客户端IP地址
125        client_hostname: Option<String>, // 客户端主机名
126        client_port: Option<u16>, // 客户端端口
127        protocol: Option<String>, // 协议信息
128        helo: Option<String>, // HELO信息
129        description: String, // 详细描述
130    },
131
132    /// 邮件丢弃事件
133    /// 当邮件被丢弃时记录的事件
134    MessageDiscard {
135        queue_id: String,
136        discard_reason: String, // 丢弃原因,如 "header X-Decision-Result: Discard"
137        sender: Option<String>, // 发件人地址(统一命名)
138        recipient: Option<String>, // 收件人地址(统一命名)
139        client_ip: Option<String>, // 客户端IP地址
140        client_hostname: Option<String>, // 客户端主机名
141        client_port: Option<u16>, // 客户端端口
142        protocol: Option<String>, // 协议信息
143        helo: Option<String>,   // HELO信息
144        description: String,    // 详细描述
145    },
146
147    /// 邮件移除事件
148    /// 当邮件从队列中被移除时记录的事件
149    MessageRemoved {
150        queue_id: String,
151        removal_reason: String, // 移除原因,如 "discarded", "bounced", "delivered"
152        details: Option<String>, // 额外详细信息
153    },
154
155    /// 其他cleanup事件
156    /// 用于处理暂时无法分类的cleanup事件
157    Other {
158        event_type: String,
159        message: String,
160        queue_id: Option<String>,
161    },
162}
163
164impl CleanupEvent {
165    pub fn event_type(&self) -> &'static str {
166        match self {
167            CleanupEvent::MessageId { .. } => "message_id",
168            CleanupEvent::QueueFileWarning { .. } => "queue_file_warning",
169            CleanupEvent::MessageRewrite { .. } => "message_rewrite",
170            CleanupEvent::MessageSize { .. } => "message_size",
171            CleanupEvent::HeaderProcessing { .. } => "header_processing",
172            CleanupEvent::FilterAction { .. } => "filter_action",
173            CleanupEvent::AddressRewrite { .. } => "address_rewrite",
174            CleanupEvent::MessageReject { .. } => "message_reject",
175            CleanupEvent::ResourceLimit { .. } => "resource_limit",
176            CleanupEvent::MilterInteraction { .. } => "milter_interaction",
177            CleanupEvent::ConfigurationWarning { .. } => "configuration_warning",
178            CleanupEvent::Statistics { .. } => "statistics",
179            CleanupEvent::SnowflakeInit { .. } => "snowflake_init",
180            CleanupEvent::MessageHold { .. } => "message_hold",
181            CleanupEvent::MessageDiscard { .. } => "message_discard",
182            CleanupEvent::MessageRemoved { .. } => "message_removed",
183            CleanupEvent::Other { .. } => "other",
184        }
185    }
186
187    /// 获取队列ID(如果存在)
188    pub fn queue_id(&self) -> Option<&str> {
189        match self {
190            CleanupEvent::MessageId { queue_id, .. } => Some(queue_id),
191            CleanupEvent::MessageRewrite { queue_id, .. } => Some(queue_id),
192            CleanupEvent::MessageSize { queue_id, .. } => Some(queue_id),
193            CleanupEvent::HeaderProcessing { queue_id, .. } => Some(queue_id),
194            CleanupEvent::FilterAction { queue_id, .. } => Some(queue_id),
195            CleanupEvent::AddressRewrite { queue_id, .. } => Some(queue_id),
196            CleanupEvent::MessageReject { queue_id, .. } => Some(queue_id),
197            CleanupEvent::MilterInteraction { queue_id, .. } => Some(queue_id),
198            CleanupEvent::MessageHold { queue_id, .. } => Some(queue_id),
199            CleanupEvent::MessageDiscard { queue_id, .. } => Some(queue_id),
200            CleanupEvent::MessageRemoved { queue_id, .. } => Some(queue_id),
201            CleanupEvent::Other { queue_id, .. } => queue_id.as_deref(),
202            _ => None,
203        }
204    }
205
206    /// 检查是否为错误级别事件
207    pub fn is_error_event(&self) -> bool {
208        matches!(
209            self,
210            CleanupEvent::QueueFileWarning { .. }
211                | CleanupEvent::MessageReject { .. }
212                | CleanupEvent::ResourceLimit { .. }
213        )
214    }
215
216    /// 检查是否为警告级别事件
217    pub fn is_warning_event(&self) -> bool {
218        matches!(
219            self,
220            CleanupEvent::QueueFileWarning { .. }
221                | CleanupEvent::ConfigurationWarning { .. }
222                | CleanupEvent::ResourceLimit { .. }
223        )
224    }
225
226    /// 检查是否为正常处理事件
227    pub fn is_normal_event(&self) -> bool {
228        matches!(
229            self,
230            CleanupEvent::MessageId { .. }
231                | CleanupEvent::MessageSize { .. }
232                | CleanupEvent::HeaderProcessing { .. }
233                | CleanupEvent::FilterAction { .. }
234                | CleanupEvent::MessageDiscard { .. }
235                | CleanupEvent::MessageRemoved { .. }
236                | CleanupEvent::SnowflakeInit { .. }
237        )
238    }
239}