postfix_log_parser/events/
smtpd.rs

1//! SMTPD服务器模块
2//!
3//! 处理Postfix smtpd服务器的事件,包括客户端连接、SMTP会话管理和邮件接收
4
5use serde::{Deserialize, Serialize};
6
7/// SMTPD组件事件
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub enum SmtpdEvent {
10    /// 客户端连接
11    Connect {
12        client_ip: String,
13        client_hostname: String,
14        port: Option<u16>,
15    },
16    /// 客户端断开连接
17    Disconnect {
18        client_ip: String,
19        client_hostname: String,
20        port: Option<u16>,
21        /// SMTP命令统计信息
22        command_stats: Option<CommandStats>,
23    },
24    /// 连接丢失
25    LostConnection {
26        client_ip: String,
27        client_hostname: String,
28        /// 丢失连接时的SMTP命令
29        last_command: Option<String>,
30    },
31    /// 连接超时
32    Timeout {
33        client_ip: String,
34        client_hostname: String,
35        /// 超时时的SMTP命令
36        last_command: Option<String>,
37    },
38    /// 客户端邮件队列ID分配
39    ClientAssignment {
40        queue_id: String,
41        client_ip: String,
42        client_hostname: String,
43        port: Option<u16>,
44    },
45    /// SASL身份验证
46    Auth {
47        method: String,
48        username: String,
49        /// 认证是否成功
50        success: bool,
51        /// 失败原因(如果失败)
52        failure_reason: Option<String>,
53    },
54    /// 邮件被拒绝
55    Reject {
56        reason: String,
57        code: Option<u16>,
58        /// 拒绝类型(NOQUEUE, 普通拒绝等)
59        reject_type: RejectType,
60        /// 发送者地址
61        from: Option<String>,
62        /// 接收者地址
63        to: Option<String>,
64        /// 客户端信息
65        client_ip: Option<String>,
66        client_hostname: Option<String>,
67    },
68    /// NOQUEUE过滤器事件
69    NoQueueFilter {
70        client_ip: String,
71        client_hostname: String,
72        filter_info: String,
73        /// 触发的过滤器类型
74        filter_target: String,
75    },
76    /// HELO/EHLO命令
77    Helo {
78        hostname: String,
79        client_ip: Option<String>,
80        client_hostname: Option<String>,
81    },
82    /// 邮件接收完成
83    Accept {
84        from: Option<String>,
85        to: Vec<String>,
86        size: Option<u64>,
87        queue_id: Option<String>,
88    },
89    /// 协议违规
90    ProtocolViolation {
91        client_ip: String,
92        client_hostname: String,
93        violation_type: String,
94        details: String,
95    },
96    /// 系统警告
97    SystemWarning {
98        warning_type: String,
99        message: String,
100        client_info: Option<ClientInfo>,
101    },
102}
103
104/// SMTP命令统计信息
105///
106/// 记录在连接期间执行的各种SMTP命令的数量统计
107#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct CommandStats {
109    /// EHLO命令执行次数(扩展HELO)
110    pub ehlo: Option<u32>,
111
112    /// HELO命令执行次数(基础问候)
113    pub helo: Option<u32>,
114
115    /// MAIL FROM命令执行次数(指定发送者)
116    pub mail: Option<u32>,
117
118    /// RCPT TO命令执行次数(指定接收者)
119    pub rcpt: Option<u32>,
120
121    /// DATA命令执行次数(开始邮件内容传输)
122    pub data: Option<u32>,
123
124    /// BDAT命令执行次数(二进制数据传输)
125    pub bdat: Option<u32>,
126
127    /// QUIT命令执行次数(结束会话)
128    pub quit: Option<u32>,
129
130    /// 总命令数(所有类型命令的总和)
131    pub commands: Option<u32>,
132}
133
134/// 拒绝类型
135#[derive(Debug, Clone, Serialize, Deserialize)]
136pub enum RejectType {
137    /// NOQUEUE拒绝(邮件未进入队列)
138    NoQueue,
139    /// 队列拒绝(邮件已进入队列但被拒绝)
140    Queued,
141    /// 未知类型
142    Unknown,
143}
144
145/// 客户端信息
146///
147/// 连接到SMTP服务器的客户端的基本网络信息
148#[derive(Debug, Clone, Serialize, Deserialize)]
149pub struct ClientInfo {
150    /// 客户端IP地址(IPv4或IPv6格式)
151    pub ip: String,
152
153    /// 客户端主机名(通过反向DNS解析得到)
154    /// 如果无法解析则显示为"unknown"或保持IP地址格式
155    pub hostname: String,
156
157    /// 客户端连接端口号(可选)
158    /// 通常为随机分配的高端口号
159    pub port: Option<u16>,
160}
161
162impl SmtpdEvent {
163    pub fn event_type(&self) -> &'static str {
164        match self {
165            SmtpdEvent::Connect { .. } => "connect",
166            SmtpdEvent::Disconnect { .. } => "disconnect",
167            SmtpdEvent::LostConnection { .. } => "lost_connection",
168            SmtpdEvent::Timeout { .. } => "timeout",
169            SmtpdEvent::ClientAssignment { .. } => "client_assignment",
170            SmtpdEvent::Auth { .. } => "auth",
171            SmtpdEvent::Reject { .. } => "reject",
172            SmtpdEvent::NoQueueFilter { .. } => "noqueue_filter",
173            SmtpdEvent::Helo { .. } => "helo",
174            SmtpdEvent::Accept { .. } => "accept",
175            SmtpdEvent::ProtocolViolation { .. } => "protocol_violation",
176            SmtpdEvent::SystemWarning { .. } => "system_warning",
177        }
178    }
179
180    /// 获取队列ID(如果存在)
181    pub fn queue_id(&self) -> Option<&str> {
182        match self {
183            SmtpdEvent::ClientAssignment { queue_id, .. } => Some(queue_id),
184            SmtpdEvent::Accept { queue_id, .. } => queue_id.as_deref(),
185            _ => None,
186        }
187    }
188}