From dbc2c11ac77f1fe9879bab84e69be12d7354b316 Mon Sep 17 00:00:00 2001 From: MTRNord Date: Thu, 27 Jul 2023 11:37:35 +0200 Subject: [PATCH] Add dmarc verify --- crates/erooster_smtp/src/commands/data.rs | 45 +++++++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/crates/erooster_smtp/src/commands/data.rs b/crates/erooster_smtp/src/commands/data.rs index bf6e33c2..53384922 100644 --- a/crates/erooster_smtp/src/commands/data.rs +++ b/crates/erooster_smtp/src/commands/data.rs @@ -16,7 +16,7 @@ use erooster_core::{ config::{Config, Rspamd}, }; use futures::{Sink, SinkExt}; -use mail_auth::{AuthenticatedMessage, DkimResult, Resolver}; +use mail_auth::{AuthenticatedMessage, DkimResult, DmarcResult, Resolver}; use simdutf8::compat::from_utf8; use std::io::Write; use std::{collections::BTreeMap, path::Path, sync::Arc, time::Duration}; @@ -189,16 +189,16 @@ impl DataCommand<'_> { .context("Failed to parse email")?; // Validate signature - let result = resolver.verify_dkim(&authenticated_message).await; + let dkim_result = resolver.verify_dkim(&authenticated_message).await; // Handle fail // TODO: generate reports - if !result + if !dkim_result .iter() .any(|s| matches!(s.result(), &DkimResult::Pass)) { // 'Strict' mode violates the advice of Section 6.1 of RFC6376 - if result + if dkim_result .iter() .any(|d| matches!(d.result(), DkimResult::TempError(_))) { @@ -217,6 +217,43 @@ impl DataCommand<'_> { return Ok(()); } + // Verify DMARC + let dmarc_result = resolver + .verify_dmarc( + &authenticated_message, + &dkim_result, + write_lock + .sender + .as_ref() + .context("Missing a MAIL-FROM sender")?, + write_lock + .spf_result + .as_ref() + .context("Missing an SPF result")?, + ) + .await; + + // These should pass at this point + if matches!(dmarc_result.dkim_result(), &DmarcResult::Fail(_)) + || matches!(dmarc_result.spf_result(), &DmarcResult::Fail(_)) + { + lines + .send(String::from( + "550 5.7.1 Email rejected per DMARC policy.\r\n", + )) + .await?; + return Ok(()); + } else if matches!(dmarc_result.dkim_result(), &DmarcResult::TempError(_)) + || matches!(dmarc_result.spf_result(), &DmarcResult::TempError(_)) + { + lines + .send(String::from( + "451 4.7.1 Email temporarily rejected per DMARC policy.\r\n", + )) + .await?; + return Ok(()); + } + let message_id = storage.store_new(&mailbox_path, data.as_bytes()).await?; debug!("Stored message: {}", message_id); }