use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PickupEvent {
pub timestamp: DateTime<Utc>,
pub pid: Option<u32>,
pub event_type: PickupEventType,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum PickupEventType {
ConfigOverrideWarning {
file_path: String,
line_number: u32,
parameter_name: String,
parameter_value: String,
},
MailPickup {
queue_id: String,
uid: u32,
sender: String,
},
}
impl PickupEvent {
pub fn new(timestamp: DateTime<Utc>, pid: Option<u32>, event_type: PickupEventType) -> Self {
Self {
timestamp,
pid,
event_type,
}
}
pub fn config_override_warning(
timestamp: DateTime<Utc>,
pid: Option<u32>,
file_path: String,
line_number: u32,
parameter_name: String,
parameter_value: String,
) -> Self {
Self::new(
timestamp,
pid,
PickupEventType::ConfigOverrideWarning {
file_path,
line_number,
parameter_name,
parameter_value,
},
)
}
pub fn mail_pickup(
timestamp: DateTime<Utc>,
pid: Option<u32>,
queue_id: String,
uid: u32,
sender: String,
) -> Self {
Self::new(
timestamp,
pid,
PickupEventType::MailPickup {
queue_id,
uid,
sender,
},
)
}
pub fn severity(&self) -> &'static str {
match &self.event_type {
PickupEventType::ConfigOverrideWarning { .. } => "warning",
PickupEventType::MailPickup { .. } => "info",
}
}
pub fn parameter_name(&self) -> Option<&str> {
match &self.event_type {
PickupEventType::ConfigOverrideWarning { parameter_name, .. } => Some(parameter_name),
_ => None,
}
}
pub fn queue_id(&self) -> Option<&str> {
match &self.event_type {
PickupEventType::MailPickup { queue_id, .. } => Some(queue_id),
_ => None,
}
}
pub fn sender(&self) -> Option<&str> {
match &self.event_type {
PickupEventType::MailPickup { sender, .. } => Some(sender),
_ => None,
}
}
pub fn uid(&self) -> Option<u32> {
match &self.event_type {
PickupEventType::MailPickup { uid, .. } => Some(*uid),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::Utc;
#[test]
fn test_config_override_warning_event() {
let timestamp = Utc::now();
let event = PickupEvent::config_override_warning(
timestamp,
Some(76),
"/etc/postfix/main.cf".to_string(),
820,
"smtpd_recipient_restrictions".to_string(),
"check_client_access pcre:/etc/postfix/filter_trusted".to_string(),
);
assert_eq!(event.timestamp, timestamp);
assert_eq!(event.pid, Some(76));
assert_eq!(event.severity(), "warning");
assert_eq!(event.parameter_name(), Some("smtpd_recipient_restrictions"));
assert_eq!(event.queue_id(), None);
assert_eq!(event.sender(), None);
assert_eq!(event.uid(), None);
match event.event_type {
PickupEventType::ConfigOverrideWarning {
file_path,
line_number,
parameter_name,
parameter_value,
} => {
assert_eq!(file_path, "/etc/postfix/main.cf");
assert_eq!(line_number, 820);
assert_eq!(parameter_name, "smtpd_recipient_restrictions");
assert!(parameter_value.contains("check_client_access"));
}
_ => panic!("Expected ConfigOverrideWarning"),
}
}
#[test]
fn test_mail_pickup_event() {
let timestamp = Utc::now();
let event = PickupEvent::mail_pickup(
timestamp,
Some(76),
"226751E20F00".to_string(),
0,
"<root>".to_string(),
);
assert_eq!(event.timestamp, timestamp);
assert_eq!(event.pid, Some(76));
assert_eq!(event.severity(), "info");
assert_eq!(event.parameter_name(), None);
assert_eq!(event.queue_id(), Some("226751E20F00"));
assert_eq!(event.sender(), Some("<root>"));
assert_eq!(event.uid(), Some(0));
match event.event_type {
PickupEventType::MailPickup {
queue_id,
uid,
sender,
} => {
assert_eq!(queue_id, "226751E20F00");
assert_eq!(uid, 0);
assert_eq!(sender, "<root>");
}
_ => panic!("Expected MailPickup"),
}
}
#[test]
fn test_event_equality() {
let timestamp = Utc::now();
let event1 = PickupEvent::config_override_warning(
timestamp,
Some(76),
"/etc/postfix/main.cf".to_string(),
806,
"smtpd_client_message_rate_limit".to_string(),
"0".to_string(),
);
let event2 = PickupEvent::config_override_warning(
timestamp,
Some(76),
"/etc/postfix/main.cf".to_string(),
806,
"smtpd_client_message_rate_limit".to_string(),
"0".to_string(),
);
assert_eq!(event1, event2);
}
}