diff --git a/src/daemon/mod.rs b/src/daemon/mod.rs index 63d398d..d552ad9 100644 --- a/src/daemon/mod.rs +++ b/src/daemon/mod.rs @@ -26,6 +26,7 @@ use indymilter::{ use crate::types::husk_context::HuskContext; use crate::config::{HuskConfig, HuskConfigContainer}; +use crate::mail; pub struct Daemon { } @@ -105,19 +106,19 @@ impl Daemon { async fn handle_mail(cx: &mut Context>, args: Vec) -> Status { log::debug!("MAIL: {args:?}"); - // XXX - let sender = match args.first() { - Some(cs) => { - match cs.to_str() { - Ok(s) => s.to_string(), - _ => "corrupt".to_string() - } - }, - None => { "missing".to_string() } - }; + let mut sender: Option = None; + + for arg in args { + if let Some(s) = mail::to_email(&arg) { + sender = Some(s); + break; + } + } + if sender.is_none() { return Status::Tempfail; } if let Some(ref mut context) = cx.data { - context.set_sender(sender); + context.reset_mail(); + context.set_sender(sender.unwrap()); Status::Continue } else { Status::Tempfail @@ -129,9 +130,23 @@ impl Daemon { if let Some(ref mut context) = cx.data { + let mut rcpt: Option = None; + for arg in args { + if let Some(s) = mail::to_email(&arg) { + rcpt = Some(s); + break; + } + } + if rcpt.is_none() { + Status::Tempfail + } else { + context.add_recipient(rcpt.unwrap()).unwrap(); + Status::Continue + } + + } else { + Status::Tempfail } - - Status::Continue } async fn handle_data(_cx: &mut Context>) -> Status { @@ -163,6 +178,7 @@ impl Daemon { if let Some(ref mut context) = cx.data { log::debug!("Mail from {:?} complete", context.mail.sender); + log::debug!("recipients: {:?}", context.mail.recipients); } Status::Continue diff --git a/src/mail.rs b/src/mail.rs new file mode 100644 index 0000000..96ba6c7 --- /dev/null +++ b/src/mail.rs @@ -0,0 +1,22 @@ +// +// Husk milter +// +// mail functions +// + +use std::ffi::CString; +use sequoia_openpgp::packet::UserID; + +pub fn to_userid(rcpt: &CString) -> Option { + match rcpt.to_str() { + Ok(s) => Some(UserID::from(s)), + _ => None + } +} + +pub fn to_email(rcpt: &CString) -> Option { + if let Some(u) = to_userid(rcpt) { + if let Ok(Some(e)) = u.email() { Some(e.to_string()) } + else { None } + } else { None } +} diff --git a/src/main.rs b/src/main.rs index 5d156a0..f7ad76d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ pub mod config; use config::{HuskConfig, HuskConfigContainer}; pub mod types; pub mod crypto; +pub mod mail; pub mod daemon; use daemon::Daemon; diff --git a/src/types/husk_context.rs b/src/types/husk_context.rs index bb97bdf..dab8da5 100644 --- a/src/types/husk_context.rs +++ b/src/types/husk_context.rs @@ -5,6 +5,7 @@ // use anyhow; +use sequoia_openpgp::policy::StandardPolicy; use std::path::PathBuf; use sequoia_openpgp::Cert; use sequoia_cert_store::{CertStore, StoreUpdate}; @@ -14,6 +15,7 @@ use crate::{config::HuskConfig, crypto}; use crate::types::mail_context::MailContext; pub struct HuskContext<'hc> { + pub policy: StandardPolicy<'hc>, pub cert_store: CertStore<'hc>, pub local_trust_root: Cert, pub mail: MailContext<'hc>, @@ -28,9 +30,12 @@ impl<'hc> HuskContext<'hc> { let cert_store_base = sequoia_home.data_dir(sequoia_directories::Component::CertD); let cert_store = CertStore::open(cert_store_base)?; + let policy = StandardPolicy::new(); + let local_trust_root = crypto::get_local_trust_root(&cert_store)?; Ok(HuskContext { + policy, cert_store, local_trust_root, mail: MailContext::new(), @@ -41,4 +46,12 @@ impl<'hc> HuskContext<'hc> { self.mail.set_sender(sender); } + pub fn reset_mail(&mut self) { + self.mail = MailContext::new(); + } + + pub fn add_recipient(&mut self, rcpt: String) -> anyhow::Result<()> { + self.mail.add_recipient(rcpt) + } + } diff --git a/src/types/mail_context.rs b/src/types/mail_context.rs index 498cf6a..f60c8ec 100644 --- a/src/types/mail_context.rs +++ b/src/types/mail_context.rs @@ -4,15 +4,25 @@ // Mail Context // -use std::ffi::CString; +use anyhow; use sequoia_openpgp::cert::ValidCert; +#[derive(Debug, Clone)] pub struct Recipient<'r> { - pub email: CString, + pub email: String, pub cert: Option>, } +impl From for Recipient<'_> { + fn from(email: String) -> Self { + Recipient { + email: email, + cert: None + } + } +} + pub struct MailContext<'c> { pub sender: Option, pub recipients: Vec>, @@ -34,4 +44,12 @@ impl MailContext<'_> { self.sender = Some(sender); } + pub fn add_recipient(&mut self, rcpt: String) -> anyhow::Result<()> { + let recipient: Recipient = rcpt.into(); + + self.recipients.push(recipient); + + Ok(()) + } + }