use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use super::{
anvil::AnvilEvent, bounce::BounceEvent, discard::DiscardEvent, master::MasterEvent,
pickup::PickupEvent, postfix_script::PostfixScriptEvent, postmap::PostmapEvent,
postsuper::PostsuperEvent, relay::RelayEvent, trivial_rewrite::TrivialRewriteEvent,
CleanupEvent, ErrorEvent, LocalEvent, QmgrEvent, SmtpEvent, SmtpdEvent, VirtualEvent,
};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct BaseEvent {
pub timestamp: DateTime<Utc>,
pub hostname: String,
pub component: String,
pub process_id: u32,
pub log_level: PostfixLogLevel,
pub raw_message: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PostfixLogEvent {
pub raw_log: String,
pub timestamp: DateTime<Utc>,
pub hostname: String,
pub component: String,
pub process_id: u32,
pub log_level: PostfixLogLevel,
pub event: ComponentEvent,
pub queue_id: Option<String>,
}
impl PostfixLogEvent {
#[allow(clippy::too_many_arguments)]
pub fn new(
raw_log: String,
timestamp: DateTime<Utc>,
hostname: String,
component: String,
process_id: u32,
log_level: PostfixLogLevel,
event: ComponentEvent,
queue_id: Option<String>,
) -> Self {
Self {
raw_log,
timestamp,
hostname,
component,
process_id,
log_level,
event,
queue_id,
}
}
pub fn event_type(&self) -> &'static str {
self.event.event_type()
}
pub fn is_error_level(&self) -> bool {
self.log_level.is_error_level()
}
pub fn is_warning_level(&self) -> bool {
self.log_level.is_warning_level()
}
pub fn is_debug_level(&self) -> bool {
self.log_level.is_debug_level()
}
pub fn severity_level(&self) -> u8 {
self.log_level.severity_level()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ComponentEvent {
Smtpd(SmtpdEvent),
Qmgr(QmgrEvent),
Smtp(SmtpEvent),
Cleanup(CleanupEvent),
Error(ErrorEvent),
Relay(RelayEvent),
Discard(DiscardEvent),
Bounce(BounceEvent),
PostfixScript(PostfixScriptEvent),
Master(MasterEvent),
Local(LocalEvent),
Pickup(PickupEvent),
Postmap(PostmapEvent),
Postsuper(PostsuperEvent),
Anvil(AnvilEvent),
TrivialRewrite(TrivialRewriteEvent),
Virtual(VirtualEvent),
Postlogd(crate::events::postlogd::PostlogdEvent),
Proxymap(crate::events::proxymap::ProxymapEvent),
Sendmail(crate::events::sendmail::SendmailEvent),
Unknown(UnknownEvent),
}
impl ComponentEvent {
pub fn event_type(&self) -> &'static str {
match self {
ComponentEvent::Smtpd(event) => event.event_type(),
ComponentEvent::Qmgr(event) => event.event_type(),
ComponentEvent::Smtp(event) => event.event_type(),
ComponentEvent::Cleanup(event) => event.event_type(),
ComponentEvent::Error(event) => event.event_type(),
ComponentEvent::Relay(_) => "relay",
ComponentEvent::Discard(_) => "discard",
ComponentEvent::Bounce(event) => event.event_type(),
ComponentEvent::PostfixScript(_) => "postfix-script",
ComponentEvent::Master(event) => event.event_type(),
ComponentEvent::Local(event) => event.event_type(),
ComponentEvent::Pickup(_) => "pickup",
ComponentEvent::Postmap(_) => "postmap",
ComponentEvent::Postsuper(_) => "postsuper",
ComponentEvent::Anvil(_) => "anvil",
ComponentEvent::TrivialRewrite(_) => "trivial-rewrite",
ComponentEvent::Virtual(event) => event.event_type(),
ComponentEvent::Postlogd(_) => "postlogd",
ComponentEvent::Proxymap(_) => "proxymap",
ComponentEvent::Sendmail(_) => "sendmail",
ComponentEvent::Unknown(_) => "unknown",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UnknownEvent {
pub component: String,
pub message: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub enum PostfixLogLevel {
Debug,
Info,
Warning,
Error,
Fatal,
Panic,
}
impl PostfixLogLevel {
pub fn severity_level(&self) -> u8 {
match self {
PostfixLogLevel::Debug => 1,
PostfixLogLevel::Info => 2,
PostfixLogLevel::Warning => 3,
PostfixLogLevel::Error => 4,
PostfixLogLevel::Fatal => 5,
PostfixLogLevel::Panic => 6,
}
}
pub fn is_error_level(&self) -> bool {
matches!(
self,
PostfixLogLevel::Error | PostfixLogLevel::Fatal | PostfixLogLevel::Panic
)
}
pub fn is_warning_level(&self) -> bool {
matches!(self, PostfixLogLevel::Warning)
}
pub fn is_debug_level(&self) -> bool {
matches!(self, PostfixLogLevel::Debug)
}
pub fn as_str(&self) -> &'static str {
match self {
PostfixLogLevel::Debug => "debug",
PostfixLogLevel::Info => "info",
PostfixLogLevel::Warning => "warning",
PostfixLogLevel::Error => "error",
PostfixLogLevel::Fatal => "fatal",
PostfixLogLevel::Panic => "panic",
}
}
pub fn from_prefix(prefix: &str) -> Option<Self> {
match prefix.to_lowercase().as_str() {
"debug:" => Some(PostfixLogLevel::Debug),
"warning:" => Some(PostfixLogLevel::Warning),
"error:" => Some(PostfixLogLevel::Error),
"fatal:" => Some(PostfixLogLevel::Fatal),
"panic:" => Some(PostfixLogLevel::Panic),
_ => None,
}
}
}
impl Default for PostfixLogLevel {
fn default() -> Self {
PostfixLogLevel::Info
}
}
impl std::fmt::Display for PostfixLogLevel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}