postfix-log-parser 0.2.0

高性能模块化Postfix日志解析器,经3.2GB生产数据验证,SMTPD事件100%准确率
Documentation
//! ERROR组件事件类型定义
//!
//! 基于676万+条真实生产数据分析,ERROR组件占34.0%的日志
//! 主要处理邮件投递错误和系统故障信息

use serde::{Deserialize, Serialize};

/// ERROR事件类型枚举
///
/// 覆盖Postfix error组件的各种错误处理事件
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "event_type")]
pub enum ErrorEvent {
    /// 投递延迟错误 - 最常见的错误类型
    DeliveryDeferred {
        queue_id: String,
        to: String,
        relay: String,
        delay: f64,
        delays: String,
        dsn: String,
        status: String,
        reason: String,
        error_type: ErrorType,
    },

    /// 投递永久失败错误
    DeliveryFailed {
        queue_id: String,
        to: String,
        relay: String,
        delay: f64,
        delays: String,
        dsn: String,
        status: String,
        reason: String,
        error_type: ErrorType,
    },

    /// 系统配置错误
    SystemError {
        queue_id: Option<String>,
        error_type: ErrorType,
        message: String,
    },

    /// 网络连接错误
    ConnectionError {
        queue_id: String,
        to: String,
        relay: String,
        delay: f64,
        delays: String,
        dsn: String,
        reason: String,
        error_type: ErrorType,
    },

    /// 其他未分类错误
    Other {
        queue_id: Option<String>,
        error_type: String,
        message: String,
    },
}

impl ErrorEvent {
    /// 获取事件类型描述
    pub fn event_type(&self) -> &'static str {
        match self {
            ErrorEvent::DeliveryDeferred { .. } => "delivery_deferred",
            ErrorEvent::DeliveryFailed { .. } => "delivery_failed",
            ErrorEvent::SystemError { .. } => "system_error",
            ErrorEvent::ConnectionError { .. } => "connection_error",
            ErrorEvent::Other { .. } => "error_other",
        }
    }

    /// 获取队列ID
    pub fn queue_id(&self) -> Option<&str> {
        match self {
            ErrorEvent::DeliveryDeferred { queue_id, .. } => Some(queue_id),
            ErrorEvent::DeliveryFailed { queue_id, .. } => Some(queue_id),
            ErrorEvent::SystemError { queue_id, .. } => queue_id.as_deref(),
            ErrorEvent::ConnectionError { queue_id, .. } => Some(queue_id),
            ErrorEvent::Other { queue_id, .. } => queue_id.as_deref(),
        }
    }

    /// 获取错误严重性级别
    pub fn severity(&self) -> u8 {
        match self {
            ErrorEvent::DeliveryDeferred { error_type, .. } => error_type.severity().level(),
            ErrorEvent::DeliveryFailed { error_type, .. } => error_type.severity().level() + 1, // 永久失败更严重
            ErrorEvent::SystemError { error_type, .. } => error_type.severity().level(),
            ErrorEvent::ConnectionError { error_type, .. } => error_type.severity().level(),
            ErrorEvent::Other { .. } => 2, // 默认中等严重性
        }
    }
}

/// 错误类型分类
///
/// 基于真实数据分析的错误类型分类
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ErrorType {
    /// DNS解析错误 - 最常见
    #[serde(rename = "dns_resolution")]
    DnsResolution,

    /// 连接被拒绝
    #[serde(rename = "connection_refused")]
    ConnectionRefused,

    /// 连接丢失
    #[serde(rename = "connection_lost")]
    ConnectionLost,

    /// 连接超时
    #[serde(rename = "connection_timeout")]
    ConnectionTimeout,

    /// 主机不可达
    #[serde(rename = "host_unreachable")]
    HostUnreachable,

    /// 邮箱不存在
    #[serde(rename = "mailbox_not_found")]
    MailboxNotFound,

    /// 邮箱已满
    #[serde(rename = "mailbox_full")]
    MailboxFull,

    /// 认证失败
    #[serde(rename = "authentication_failed")]
    AuthenticationFailed,

    /// 速率限制
    #[serde(rename = "rate_limited")]
    RateLimited,

    /// 垃圾邮件拒绝
    #[serde(rename = "spam_rejected")]
    SpamRejected,

    /// 策略拒绝
    #[serde(rename = "policy_rejected")]
    PolicyRejected,

    /// 系统配置错误
    #[serde(rename = "system_config")]
    SystemConfig,

    /// 资源不足
    #[serde(rename = "resource_shortage")]
    ResourceShortage,

    /// 协议错误
    #[serde(rename = "protocol_error")]
    ProtocolError,

    /// TLS/SSL错误
    #[serde(rename = "tls_error")]
    TlsError,

    /// 其他未分类错误
    #[serde(rename = "other")]
    Other,
}

impl ErrorType {
    /// 从错误原因字符串推断错误类型
    pub fn from_reason(reason: &str) -> Self {
        let reason_lower = reason.to_lowercase();

        if reason_lower.contains("host or domain name not found")
            || reason_lower.contains("name service error")
            || reason_lower.contains("host not found")
        {
            Self::DnsResolution
        } else if reason_lower.contains("connection refused") {
            Self::ConnectionRefused
        } else if reason_lower.contains("lost connection") {
            Self::ConnectionLost
        } else if reason_lower.contains("connection timed out") || reason_lower.contains("timeout")
        {
            Self::ConnectionTimeout
        } else if reason_lower.contains("host unreachable")
            || reason_lower.contains("network unreachable")
        {
            Self::HostUnreachable
        } else if reason_lower.contains("user unknown")
            || reason_lower.contains("recipient address rejected")
            || reason_lower.contains("mailbox unavailable")
        {
            Self::MailboxNotFound
        } else if reason_lower.contains("mailbox full")
            || reason_lower.contains("quota exceeded")
            || reason_lower.contains("insufficient storage")
        {
            Self::MailboxFull
        } else if reason_lower.contains("authentication") || reason_lower.contains("auth") {
            Self::AuthenticationFailed
        } else if reason_lower.contains("rate limit")
            || reason_lower.contains("too many")
            || reason_lower.contains("throttl")
        {
            Self::RateLimited
        } else if reason_lower.contains("spam")
            || reason_lower.contains("blacklist")
            || reason_lower.contains("blocked")
        {
            Self::SpamRejected
        } else if reason_lower.contains("policy") || reason_lower.contains("rejected") {
            Self::PolicyRejected
        } else if reason_lower.contains("tls")
            || reason_lower.contains("ssl")
            || reason_lower.contains("certificate")
        {
            Self::TlsError
        } else if reason_lower.contains("protocol") {
            Self::ProtocolError
        } else if reason_lower.contains("config") || reason_lower.contains("permission") {
            Self::SystemConfig
        } else if reason_lower.contains("resource")
            || reason_lower.contains("memory")
            || reason_lower.contains("disk")
        {
            Self::ResourceShortage
        } else {
            Self::Other
        }
    }

    /// 获取错误类型的描述
    pub fn description(&self) -> &'static str {
        match self {
            Self::DnsResolution => "DNS解析错误",
            Self::ConnectionRefused => "连接被拒绝",
            Self::ConnectionLost => "连接丢失",
            Self::ConnectionTimeout => "连接超时",
            Self::HostUnreachable => "主机不可达",
            Self::MailboxNotFound => "邮箱不存在",
            Self::MailboxFull => "邮箱已满",
            Self::AuthenticationFailed => "认证失败",
            Self::RateLimited => "速率限制",
            Self::SpamRejected => "垃圾邮件拒绝",
            Self::PolicyRejected => "策略拒绝",
            Self::SystemConfig => "系统配置错误",
            Self::ResourceShortage => "资源不足",
            Self::ProtocolError => "协议错误",
            Self::TlsError => "TLS/SSL错误",
            Self::Other => "其他错误",
        }
    }

    /// 获取错误严重性级别
    pub fn severity(&self) -> ErrorSeverity {
        match self {
            Self::DnsResolution | Self::ConnectionTimeout | Self::ConnectionLost => {
                ErrorSeverity::Temporary
            }
            Self::ConnectionRefused | Self::HostUnreachable => ErrorSeverity::Network,
            Self::MailboxNotFound | Self::MailboxFull => ErrorSeverity::RecipientIssue,
            Self::AuthenticationFailed | Self::PolicyRejected | Self::SpamRejected => {
                ErrorSeverity::PolicyIssue
            }
            Self::SystemConfig | Self::ResourceShortage => ErrorSeverity::SystemIssue,
            Self::TlsError | Self::ProtocolError => ErrorSeverity::ProtocolIssue,
            Self::RateLimited => ErrorSeverity::Temporary,
            Self::Other => ErrorSeverity::Unknown,
        }
    }
}

/// 错误严重性级别
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ErrorSeverity {
    /// 临时性错误,可重试
    #[serde(rename = "temporary")]
    Temporary,

    /// 网络相关错误
    #[serde(rename = "network")]
    Network,

    /// 收件人相关问题
    #[serde(rename = "recipient_issue")]
    RecipientIssue,

    /// 策略或安全问题
    #[serde(rename = "policy_issue")]
    PolicyIssue,

    /// 系统问题
    #[serde(rename = "system_issue")]
    SystemIssue,

    /// 协议问题
    #[serde(rename = "protocol_issue")]
    ProtocolIssue,

    /// 未知错误
    #[serde(rename = "unknown")]
    Unknown,
}

impl ErrorSeverity {
    /// 获取严重性级别的数值表示 (1-5)
    pub fn level(&self) -> u8 {
        match self {
            Self::Temporary => 1,
            Self::Network => 2,
            Self::RecipientIssue => 3,
            Self::PolicyIssue => 3,
            Self::ProtocolIssue => 4,
            Self::SystemIssue => 5,
            Self::Unknown => 2,
        }
    }

    /// 获取严重性级别的描述
    pub fn description(&self) -> &'static str {
        match self {
            Self::Temporary => "临时性错误,通常可重试",
            Self::Network => "网络连接问题",
            Self::RecipientIssue => "收件人相关问题",
            Self::PolicyIssue => "策略或安全问题",
            Self::ProtocolIssue => "协议层面问题",
            Self::SystemIssue => "系统级别问题",
            Self::Unknown => "未知类型错误",
        }
    }
}