/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use std::borrow::Cow; use ahash::AHashMap; use common::{ Server, auth::AccessToken, expr::functions::ResolveVariable, scripts::ScriptModification, }; use mail_parser::Message; use sieve::{Envelope, SpamStatus, runtime::Variable}; pub mod envelope; pub mod event_loop; pub mod exec; #[derive(Debug, serde::Serialize)] pub enum ScriptResult { Accept { modifications: Vec, }, Replace { message: Vec, modifications: Vec, }, Reject(String), Discard, } pub struct ScriptParameters<'x> { message: Option>, headers: Option<&'x [u8]>, variables: AHashMap, Variable>, envelope: Vec<(Envelope, Variable)>, from_addr: String, from_name: String, return_path: String, sign_domain: Option, access_token: Option<&'x AccessToken>, spam_status: Option, session_id: u64, } impl<'x> ScriptParameters<'x> { pub fn new() -> Self { ScriptParameters { variables: AHashMap::with_capacity(10), envelope: Vec::with_capacity(6), message: None, headers: None, from_addr: Default::default(), from_name: Default::default(), return_path: Default::default(), sign_domain: Default::default(), access_token: None, spam_status: None, session_id: Default::default(), } } pub async fn with_envelope( mut self, server: &Server, vars: &impl ResolveVariable, session_id: u64, ) -> Self { for (variable, expr) in [ (&mut self.from_addr, &server.core.sieve.from_addr), (&mut self.from_name, &server.core.sieve.from_name), (&mut self.return_path, &server.core.sieve.return_path), ] { if let Some(value) = server.eval_if(expr, vars, session_id).await { *variable = value; } } self.sign_domain = server .eval_if(&server.core.sieve.sign, vars, session_id) .await; self } pub fn with_message(self, message: Message<'x>) -> Self { Self { message: message.into(), ..self } } pub fn with_auth_headers(self, headers: &'x [u8]) -> Self { Self { headers: headers.into(), ..self } } pub fn with_spam_status(self, status: SpamStatus) -> Self { Self { spam_status: status.into(), ..self } } pub fn set_variable( mut self, name: impl Into>, value: impl Into, ) -> Self { self.variables.insert(name.into(), value.into()); self } pub fn set_envelope(mut self, envelope: Envelope, value: impl Into) -> Self { self.envelope.push((envelope, value.into())); self } pub fn with_access_token(mut self, access_token: &'x AccessToken) -> Self { self.access_token = Some(access_token); self } pub fn with_session_id(mut self, session_id: u64) -> Self { self.session_id = session_id; self } } impl Default for ScriptParameters<'_> { fn default() -> Self { Self::new() } }