postfix_log_parser/events/
base.rs

1//! 基础事件类型和通用数据结构
2//!
3//! 定义所有Postfix日志事件的基础类型,包括通用字段、日志等级和组件事件枚举
4
5use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7
8use super::{
9    anvil::AnvilEvent, bounce::BounceEvent, discard::DiscardEvent, master::MasterEvent,
10    pickup::PickupEvent, postfix_script::PostfixScriptEvent, postmap::PostmapEvent,
11    postsuper::PostsuperEvent, relay::RelayEvent, trivial_rewrite::TrivialRewriteEvent,
12    CleanupEvent, ErrorEvent, LocalEvent, QmgrEvent, SmtpEvent, SmtpdEvent, VirtualEvent,
13};
14
15/// 基础事件信息
16/// 包含所有Postfix事件的通用字段
17#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
18pub struct BaseEvent {
19    /// 日志时间戳(UTC时间)
20    /// 从日志行开头解析的时间信息,统一转换为UTC时间格式
21    pub timestamp: DateTime<Utc>,
22
23    /// 主机名(产生日志的服务器名称)
24    /// 从日志行第二个字段提取,用于标识日志来源服务器
25    pub hostname: String,
26
27    /// 组件名称(Postfix组件标识)
28    /// 如smtpd、qmgr、smtp等,对应Postfix架构中的不同模块
29    pub component: String,
30
31    /// 进程ID(组件进程的系统标识符)
32    /// 从方括号内提取,用于区分同一组件的不同进程实例
33    pub process_id: u32,
34
35    /// 日志等级(消息的重要程度分类)
36    /// 基于Postfix源码中的消息等级分类系统
37    pub log_level: PostfixLogLevel,
38
39    /// 原始消息内容(冒号后的完整消息文本)
40    /// 保留原始格式,用于组件特定的解析和调试
41    pub raw_message: String,
42}
43
44/// 统一的Postfix日志事件结构
45///
46/// 这是解析后的日志事件的完整表示,包含所有基础字段和具体的事件数据
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct PostfixLogEvent {
49    /// 原始日志行(完整的原始日志字符串)
50    /// 用途:审计、调试、追溯原始数据
51    /// 示例:"Jun 05 15:40:52 m01 postfix/smtpd\[89\]: connect from localhost\[127.0.0.1\]"
52    pub raw_log: String,
53
54    /// 日志时间戳(UTC时间)
55    /// 从日志行提取的时间信息,自动转换为UTC格式
56    /// 格式:ISO 8601标准时间格式
57    pub timestamp: DateTime<Utc>,
58
59    /// 主机名(产生日志的服务器主机名)
60    /// 从日志行中的第二个字段提取
61    /// 示例:"m01", "mail.example.com"
62    pub hostname: String,
63
64    /// Postfix组件名称(产生此日志的Postfix组件)
65    /// 可能的值:smtpd, qmgr, smtp, cleanup, local, virtual等
66    /// 对应Postfix架构中的不同功能模块
67    pub component: String,
68
69    /// 进程ID(产生日志的进程标识符)
70    /// 从日志行中方括号内提取的数字
71    /// 用于区分同一组件的不同进程实例
72    pub process_id: u32,
73
74    /// 日志等级(日志的重要性和严重程度)
75    /// 基于Postfix源码中的msg_*函数分类
76    /// 影响日志的过滤和告警策略
77    pub log_level: PostfixLogLevel,
78
79    /// 具体的业务事件数据(解析后的结构化事件信息)
80    /// 根据不同组件类型包含不同的事件结构
81    /// 这是日志解析的核心价值所在
82    pub event: ComponentEvent,
83
84    /// 队列ID(邮件在Postfix队列系统中的唯一标识符)
85    /// 用于跟踪单个邮件在系统中的完整生命周期
86    /// 格式:通常为十六进制字符串,如"5BC302B027ED"
87    pub queue_id: Option<String>,
88}
89
90impl PostfixLogEvent {
91    /// 创建新的日志事件
92    #[allow(clippy::too_many_arguments)]
93    pub fn new(
94        raw_log: String,
95        timestamp: DateTime<Utc>,
96        hostname: String,
97        component: String,
98        process_id: u32,
99        log_level: PostfixLogLevel,
100        event: ComponentEvent,
101        queue_id: Option<String>,
102    ) -> Self {
103        Self {
104            raw_log,
105            timestamp,
106            hostname,
107            component,
108            process_id,
109            log_level,
110            event,
111            queue_id,
112        }
113    }
114
115    /// 获取事件类型描述
116    pub fn event_type(&self) -> &'static str {
117        self.event.event_type()
118    }
119
120    /// 检查是否为错误级别的日志
121    pub fn is_error_level(&self) -> bool {
122        self.log_level.is_error_level()
123    }
124
125    /// 检查是否为警告级别的日志
126    pub fn is_warning_level(&self) -> bool {
127        self.log_level.is_warning_level()
128    }
129
130    /// 检查是否为调试级别的日志
131    pub fn is_debug_level(&self) -> bool {
132        self.log_level.is_debug_level()
133    }
134
135    /// 获取日志等级的严重程度数值
136    pub fn severity_level(&self) -> u8 {
137        self.log_level.severity_level()
138    }
139}
140
141/// 组件事件枚举
142///
143/// 每个Postfix组件都有对应的事件类型
144#[derive(Debug, Clone, Serialize, Deserialize)]
145pub enum ComponentEvent {
146    /// SMTPD组件事件
147    Smtpd(SmtpdEvent),
148    /// 队列管理器组件事件
149    Qmgr(QmgrEvent),
150    /// SMTP投递组件事件
151    Smtp(SmtpEvent),
152    /// 清理组件事件
153    Cleanup(CleanupEvent),
154    /// 错误处理组件事件
155    Error(ErrorEvent),
156    /// 中继组件事件
157    Relay(RelayEvent),
158    /// 丢弃组件事件
159    Discard(DiscardEvent),
160    /// 退信处理组件事件
161    Bounce(BounceEvent),
162    /// Postfix脚本组件事件
163    PostfixScript(PostfixScriptEvent),
164    /// Master守护进程组件事件
165    Master(MasterEvent),
166    /// 本地投递组件事件
167    Local(LocalEvent),
168    /// 邮件拾取组件事件
169    Pickup(PickupEvent),
170    /// Postmap工具组件事件
171    Postmap(PostmapEvent),
172    /// Postsuper邮件队列管理工具组件事件
173    Postsuper(PostsuperEvent),
174    /// Anvil连接计数组件事件
175    Anvil(AnvilEvent),
176    /// 地址重写和解析组件事件
177    TrivialRewrite(TrivialRewriteEvent),
178    /// 虚拟投递组件事件
179    Virtual(VirtualEvent),
180    /// Postlogd组件事件
181    Postlogd(crate::events::postlogd::PostlogdEvent),
182    /// Proxymap组件事件  
183    Proxymap(crate::events::proxymap::ProxymapEvent),
184    Sendmail(crate::events::sendmail::SendmailEvent),
185    /// 未知或不支持的组件事件
186    Unknown(UnknownEvent),
187}
188
189impl ComponentEvent {
190    /// 获取事件类型描述
191    pub fn event_type(&self) -> &'static str {
192        match self {
193            ComponentEvent::Smtpd(event) => event.event_type(),
194            ComponentEvent::Qmgr(event) => event.event_type(),
195            ComponentEvent::Smtp(event) => event.event_type(),
196            ComponentEvent::Cleanup(event) => event.event_type(),
197            ComponentEvent::Error(event) => event.event_type(),
198            ComponentEvent::Relay(_) => "relay",
199            ComponentEvent::Discard(_) => "discard",
200            ComponentEvent::Bounce(event) => event.event_type(),
201            ComponentEvent::PostfixScript(_) => "postfix-script",
202            ComponentEvent::Master(event) => event.event_type(),
203            ComponentEvent::Local(event) => event.event_type(),
204            ComponentEvent::Pickup(_) => "pickup",
205            ComponentEvent::Postmap(_) => "postmap",
206            ComponentEvent::Postsuper(_) => "postsuper",
207            ComponentEvent::Anvil(_) => "anvil",
208            ComponentEvent::TrivialRewrite(_) => "trivial-rewrite",
209            ComponentEvent::Virtual(event) => event.event_type(),
210            ComponentEvent::Postlogd(_) => "postlogd",
211            ComponentEvent::Proxymap(_) => "proxymap",
212            ComponentEvent::Sendmail(_) => "sendmail",
213            ComponentEvent::Unknown(_) => "unknown",
214        }
215    }
216}
217
218/// 未知组件事件(无法识别的组件产生的事件)
219/// 当遇到未知组件或解析失败时使用此结构
220#[derive(Debug, Clone, Serialize, Deserialize)]
221pub struct UnknownEvent {
222    /// 组件名称(即使未知也保留原始组件名)
223    pub component: String,
224    /// 消息内容(去除前缀后的原始消息内容)
225    pub message: String,
226}
227
228/// Postfix日志等级,对应Postfix源码中的msg_*函数
229/// 基于Postfix源码:msg_debug, msg_info, msg_warn, msg_error, msg_fatal, msg_panic
230#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
231pub enum PostfixLogLevel {
232    /// msg_debug() - 调试信息(默认关闭)
233    Debug,
234    /// msg_info() - 正常业务操作(最常见,默认等级)
235    Info,
236    /// msg_warn() - 警告,可恢复问题
237    Warning,
238    /// msg_error() - 错误,操作失败但系统可继续
239    Error,
240    /// msg_fatal() - 致命错误,导致进程退出
241    Fatal,
242    /// msg_panic() - 系统崩溃级别
243    Panic,
244}
245
246impl PostfixLogLevel {
247    /// 获取日志等级的严重程度数值(1-6,数值越高越严重)
248    pub fn severity_level(&self) -> u8 {
249        match self {
250            PostfixLogLevel::Debug => 1,
251            PostfixLogLevel::Info => 2,
252            PostfixLogLevel::Warning => 3,
253            PostfixLogLevel::Error => 4,
254            PostfixLogLevel::Fatal => 5,
255            PostfixLogLevel::Panic => 6,
256        }
257    }
258
259    /// 检查是否为错误级别(Error/Fatal/Panic)
260    pub fn is_error_level(&self) -> bool {
261        matches!(
262            self,
263            PostfixLogLevel::Error | PostfixLogLevel::Fatal | PostfixLogLevel::Panic
264        )
265    }
266
267    /// 检查是否为警告级别
268    pub fn is_warning_level(&self) -> bool {
269        matches!(self, PostfixLogLevel::Warning)
270    }
271
272    /// 检查是否为调试级别
273    pub fn is_debug_level(&self) -> bool {
274        matches!(self, PostfixLogLevel::Debug)
275    }
276
277    /// 获取日志等级的字符串表示
278    pub fn as_str(&self) -> &'static str {
279        match self {
280            PostfixLogLevel::Debug => "debug",
281            PostfixLogLevel::Info => "info",
282            PostfixLogLevel::Warning => "warning",
283            PostfixLogLevel::Error => "error",
284            PostfixLogLevel::Fatal => "fatal",
285            PostfixLogLevel::Panic => "panic",
286        }
287    }
288
289    /// 从字符串解析日志等级(用于解析日志中的等级前缀)
290    pub fn from_prefix(prefix: &str) -> Option<Self> {
291        match prefix.to_lowercase().as_str() {
292            "debug:" => Some(PostfixLogLevel::Debug),
293            "warning:" => Some(PostfixLogLevel::Warning),
294            "error:" => Some(PostfixLogLevel::Error),
295            "fatal:" => Some(PostfixLogLevel::Fatal),
296            "panic:" => Some(PostfixLogLevel::Panic),
297            _ => None,
298        }
299    }
300}
301
302impl Default for PostfixLogLevel {
303    /// 默认为Info级别(Postfix大部分日志都是Info级别)
304    fn default() -> Self {
305        PostfixLogLevel::Info
306    }
307}
308
309impl std::fmt::Display for PostfixLogLevel {
310    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
311        write!(f, "{}", self.as_str())
312    }
313}