postfix-log-parser 0.2.0

高性能模块化Postfix日志解析器,经3.2GB生产数据验证,SMTPD事件100%准确率
Documentation
//! SMTPD服务器模块
//!
//! 处理Postfix smtpd服务器的事件,包括客户端连接、SMTP会话管理和邮件接收

use serde::{Deserialize, Serialize};

/// SMTPD组件事件
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SmtpdEvent {
    /// 客户端连接
    Connect {
        client_ip: String,
        client_hostname: String,
        port: Option<u16>,
    },
    /// 客户端断开连接
    Disconnect {
        client_ip: String,
        client_hostname: String,
        port: Option<u16>,
        /// SMTP命令统计信息
        command_stats: Option<CommandStats>,
    },
    /// 连接丢失
    LostConnection {
        client_ip: String,
        client_hostname: String,
        /// 丢失连接时的SMTP命令
        last_command: Option<String>,
    },
    /// 连接超时
    Timeout {
        client_ip: String,
        client_hostname: String,
        /// 超时时的SMTP命令
        last_command: Option<String>,
    },
    /// 客户端邮件队列ID分配
    ClientAssignment {
        queue_id: String,
        client_ip: String,
        client_hostname: String,
        port: Option<u16>,
    },
    /// SASL身份验证
    Auth {
        method: String,
        username: String,
        /// 认证是否成功
        success: bool,
        /// 失败原因(如果失败)
        failure_reason: Option<String>,
    },
    /// 邮件被拒绝
    Reject {
        reason: String,
        code: Option<u16>,
        /// 拒绝类型(NOQUEUE, 普通拒绝等)
        reject_type: RejectType,
        /// 发送者地址
        from: Option<String>,
        /// 接收者地址
        to: Option<String>,
        /// 客户端信息
        client_ip: Option<String>,
        client_hostname: Option<String>,
    },
    /// NOQUEUE过滤器事件
    NoQueueFilter {
        client_ip: String,
        client_hostname: String,
        filter_info: String,
        /// 触发的过滤器类型
        filter_target: String,
    },
    /// HELO/EHLO命令
    Helo {
        hostname: String,
        client_ip: Option<String>,
        client_hostname: Option<String>,
    },
    /// 邮件接收完成
    Accept {
        from: Option<String>,
        to: Vec<String>,
        size: Option<u64>,
        queue_id: Option<String>,
    },
    /// 协议违规
    ProtocolViolation {
        client_ip: String,
        client_hostname: String,
        violation_type: String,
        details: String,
    },
    /// 系统警告
    SystemWarning {
        warning_type: String,
        message: String,
        client_info: Option<ClientInfo>,
    },
}

/// SMTP命令统计信息
///
/// 记录在连接期间执行的各种SMTP命令的数量统计
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommandStats {
    /// EHLO命令执行次数(扩展HELO)
    pub ehlo: Option<u32>,

    /// HELO命令执行次数(基础问候)
    pub helo: Option<u32>,

    /// MAIL FROM命令执行次数(指定发送者)
    pub mail: Option<u32>,

    /// RCPT TO命令执行次数(指定接收者)
    pub rcpt: Option<u32>,

    /// DATA命令执行次数(开始邮件内容传输)
    pub data: Option<u32>,

    /// BDAT命令执行次数(二进制数据传输)
    pub bdat: Option<u32>,

    /// QUIT命令执行次数(结束会话)
    pub quit: Option<u32>,

    /// 总命令数(所有类型命令的总和)
    pub commands: Option<u32>,
}

/// 拒绝类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RejectType {
    /// NOQUEUE拒绝(邮件未进入队列)
    NoQueue,
    /// 队列拒绝(邮件已进入队列但被拒绝)
    Queued,
    /// 未知类型
    Unknown,
}

/// 客户端信息
///
/// 连接到SMTP服务器的客户端的基本网络信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClientInfo {
    /// 客户端IP地址(IPv4或IPv6格式)
    pub ip: String,

    /// 客户端主机名(通过反向DNS解析得到)
    /// 如果无法解析则显示为"unknown"或保持IP地址格式
    pub hostname: String,

    /// 客户端连接端口号(可选)
    /// 通常为随机分配的高端口号
    pub port: Option<u16>,
}

impl SmtpdEvent {
    pub fn event_type(&self) -> &'static str {
        match self {
            SmtpdEvent::Connect { .. } => "connect",
            SmtpdEvent::Disconnect { .. } => "disconnect",
            SmtpdEvent::LostConnection { .. } => "lost_connection",
            SmtpdEvent::Timeout { .. } => "timeout",
            SmtpdEvent::ClientAssignment { .. } => "client_assignment",
            SmtpdEvent::Auth { .. } => "auth",
            SmtpdEvent::Reject { .. } => "reject",
            SmtpdEvent::NoQueueFilter { .. } => "noqueue_filter",
            SmtpdEvent::Helo { .. } => "helo",
            SmtpdEvent::Accept { .. } => "accept",
            SmtpdEvent::ProtocolViolation { .. } => "protocol_violation",
            SmtpdEvent::SystemWarning { .. } => "system_warning",
        }
    }

    /// 获取队列ID(如果存在)
    pub fn queue_id(&self) -> Option<&str> {
        match self {
            SmtpdEvent::ClientAssignment { queue_id, .. } => Some(queue_id),
            SmtpdEvent::Accept { queue_id, .. } => queue_id.as_deref(),
            _ => None,
        }
    }
}