postfix_log_parser/events/
postlogd.rs

1//! Postlogd内部日志服务模块
2//!
3//! 处理Postfix postlogd守护进程的事件,负责内部日志处理和配置管理
4
5use serde::{Deserialize, Serialize};
6use std::fmt;
7
8/// POSTLOGD events - Postfix internal log server
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
10pub struct PostlogdEvent {
11    pub timestamp: String,
12    pub process_id: String,
13    pub event_type: PostlogdEventType,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
17pub enum PostlogdEventType {
18    /// Configuration override warning
19    ConfigOverrideWarning {
20        file_path: String,
21        line_number: u32,
22        parameter: String,
23        value: String,
24    },
25}
26
27impl fmt::Display for PostlogdEvent {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        write!(
30            f,
31            "[{}] postlogd[{}]: {}",
32            self.timestamp, self.process_id, self.event_type
33        )
34    }
35}
36
37impl fmt::Display for PostlogdEventType {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        match self {
40            PostlogdEventType::ConfigOverrideWarning {
41                file_path,
42                line_number,
43                parameter,
44                value,
45            } => {
46                write!(
47                    f,
48                    "Config override warning: {}, line {}: overriding earlier entry: {}={}",
49                    file_path, line_number, parameter, value
50                )
51            }
52        }
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    #[test]
61    fn test_config_override_warning_event() {
62        let event = PostlogdEvent {
63            timestamp: "Apr 08 17:54:30".to_string(),
64            process_id: "78".to_string(),
65            event_type: PostlogdEventType::ConfigOverrideWarning {
66                file_path: "/etc/postfix/main.cf".to_string(),
67                line_number: 820,
68                parameter: "smtpd_recipient_restrictions".to_string(),
69                value: "check_client_access pcre:/etc/postfix/filter_trusted".to_string(),
70            },
71        };
72
73        assert_eq!(event.process_id, "78");
74
75        let PostlogdEventType::ConfigOverrideWarning {
76            file_path,
77            line_number,
78            parameter,
79            ..
80        } = &event.event_type;
81
82        assert_eq!(file_path, "/etc/postfix/main.cf");
83        assert_eq!(*line_number, 820);
84        assert_eq!(parameter, "smtpd_recipient_restrictions");
85    }
86
87    #[test]
88    fn test_event_serialization() {
89        let event = PostlogdEvent {
90            timestamp: "Apr 08 17:54:30".to_string(),
91            process_id: "78".to_string(),
92            event_type: PostlogdEventType::ConfigOverrideWarning {
93                file_path: "/etc/postfix/main.cf".to_string(),
94                line_number: 806,
95                parameter: "smtpd_client_message_rate_limit".to_string(),
96                value: "0".to_string(),
97            },
98        };
99
100        let serialized = serde_json::to_string(&event).unwrap();
101        let deserialized: PostlogdEvent = serde_json::from_str(&serialized).unwrap();
102        assert_eq!(event, deserialized);
103    }
104
105    #[test]
106    fn test_event_display() {
107        let event = PostlogdEvent {
108            timestamp: "Apr 08 17:54:30".to_string(),
109            process_id: "78".to_string(),
110            event_type: PostlogdEventType::ConfigOverrideWarning {
111                file_path: "/etc/postfix/main.cf".to_string(),
112                line_number: 826,
113                parameter: "smtpd_discard_ehlo_keywords".to_string(),
114                value: "silent-discard,dsn,etrn".to_string(),
115            },
116        };
117
118        let display = format!("{}", event);
119        assert!(display.contains("postlogd[78]"));
120        assert!(display.contains("Config override warning"));
121        assert!(display.contains("main.cf"));
122        assert!(display.contains("line 826"));
123    }
124
125    #[test]
126    fn test_complex_parameter_value() {
127        let event = PostlogdEvent {
128            timestamp: "Apr 08 17:54:30".to_string(),
129            process_id: "78".to_string(),
130            event_type: PostlogdEventType::ConfigOverrideWarning {
131                file_path: "/etc/postfix/main.cf".to_string(),
132                line_number: 820,
133                parameter: "smtpd_recipient_restrictions".to_string(),
134                value: "check_client_access pcre:/etc/postfix/filter_trusted, permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination, pcre:/etc/postfix/filter_default".to_string(),
135            },
136        };
137
138        let PostlogdEventType::ConfigOverrideWarning { value, .. } = &event.event_type;
139        assert!(value.contains("check_client_access"));
140        assert!(value.contains("permit_sasl_authenticated"));
141        assert!(value.contains("reject_unauth_destination"));
142    }
143
144    #[test]
145    fn test_different_parameters() {
146        let events = vec![
147            (
148                "smtpd_recipient_restrictions",
149                "check_client_access pcre:/etc/postfix/filter_trusted",
150            ),
151            ("smtpd_client_message_rate_limit", "0"),
152            ("smtpd_discard_ehlo_keywords", "silent-discard,dsn,etrn"),
153        ];
154
155        for (param, val) in events {
156            let event = PostlogdEvent {
157                timestamp: "Apr 10 11:17:10".to_string(),
158                process_id: "78".to_string(),
159                event_type: PostlogdEventType::ConfigOverrideWarning {
160                    file_path: "/etc/postfix/main.cf".to_string(),
161                    line_number: 806,
162                    parameter: param.to_string(),
163                    value: val.to_string(),
164                },
165            };
166
167            let PostlogdEventType::ConfigOverrideWarning {
168                parameter, value, ..
169            } = &event.event_type;
170
171            assert_eq!(parameter, param);
172            assert_eq!(value, val);
173        }
174    }
175}