mirror of
https://github.com/chatmail/relay.git
synced 2026-09-16 12:23:15 +00:00
feat: Save rejected messages to /tmp (#55)
This commit is contained in:
@@ -6,7 +6,7 @@ use crate::dkim_verifier::DkimVerifier;
|
|||||||
use crate::message::{check_encrypted, is_securejoin};
|
use crate::message::{check_encrypted, is_securejoin};
|
||||||
pub use crate::smtp_server::Envelope;
|
pub use crate::smtp_server::Envelope;
|
||||||
use crate::smtp_server::SmtpHandler;
|
use crate::smtp_server::SmtpHandler;
|
||||||
use crate::utils::{AddressDomain, extract_address};
|
use crate::utils::{AddressDomain, extract_address, log_eml};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use mailparse::{MailHeaderMap, parse_mail};
|
use mailparse::{MailHeaderMap, parse_mail};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
@@ -69,8 +69,18 @@ impl SmtpHandler for IncomingBeforeQueueHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
AddressDomain::Name(domain) => {
|
AddressDomain::Name(domain) => {
|
||||||
if !self.skip_dkim {
|
if !self.skip_dkim
|
||||||
self.dkim_verifier.verify(&envelope.data, &domain).await?;
|
&& let Err(e) = self.dkim_verifier.verify(&envelope.data, &domain).await
|
||||||
|
{
|
||||||
|
let eml_path = log_eml("dkim-verify", &envelope.data)
|
||||||
|
.await
|
||||||
|
.map(|path| path.to_string_lossy().to_string())
|
||||||
|
.unwrap_or_else(|e| {
|
||||||
|
log::error!("Failed to save rejected message to file: {e}");
|
||||||
|
"ERR".to_string()
|
||||||
|
});
|
||||||
|
log::info!("Rejected message stored at: {eml_path}");
|
||||||
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use mailparse::MailAddr;
|
use mailparse::MailAddr;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
/// Extracts the first email address found in SMTP command or email header.
|
/// Extracts the first email address found in SMTP command or email header.
|
||||||
@@ -75,6 +76,23 @@ impl FromStr for AddressDomain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Logs email to `/tmp/filtermail-rejected/<reason>/<timestamp>.eml`
|
||||||
|
/// and returns the file path.
|
||||||
|
///
|
||||||
|
/// Returns [`crate::error::Error`] on IO error.
|
||||||
|
pub async fn log_eml(reason: &str, data: &[u8]) -> Result<PathBuf, crate::error::Error> {
|
||||||
|
let timestamp = std::time::SystemTime::now()
|
||||||
|
.duration_since(std::time::UNIX_EPOCH)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.as_secs();
|
||||||
|
let filename = format!("{timestamp}.eml");
|
||||||
|
let mut path = PathBuf::from(format!("/tmp/filtermail-rejected/{reason}"));
|
||||||
|
tokio::fs::create_dir_all(&path).await?;
|
||||||
|
path.push(filename);
|
||||||
|
tokio::fs::write(&path, data).await?;
|
||||||
|
Ok(path)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
Reference in New Issue
Block a user