1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
// Copyright 2019 Alexandros Frantzis // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. // // SPDX-License-Identifier: MPL-2.0 //! Email processing and filtering. use std::io::Write; use std::process::{Command, Output, Stdio}; use crate::{Email, Result}; impl Email { /// Filters the contents of the email using an external command, /// returning a new email with the filtered contents. /// /// The command is expected to be provided as a `&str` array, with the /// first element being the command name and the remaining elements the /// command arguments. /// /// # Example /// /// ```no_run /// use mda::Email; /// let email = Email::from_stdin()?; /// let email = email.filter(&["bogofilter", "-ep"])?; /// # Ok::<(), Box<dyn std::error::Error>>(()) /// ``` pub fn filter(&self, cmd: &[&str]) -> Result<Email> { Email::from_vec(self.process(cmd)?.stdout) } /// Process the contents of the email using an external command, /// returning a `std::process::Output` for the executed command. /// /// The command is expected to be provided as a `&str` array, with the /// first element being the command name and the remaining elements the /// command arguments. /// /// # Example /// /// ```no_run /// use mda::Email; /// let email = Email::from_stdin()?; /// let output = email.process(&["bogofilter"])?; /// if let Some(0) = output.status.code() { /// email.deliver_to_maildir("/my/spam/path")?; /// } /// # Ok::<(), Box<dyn std::error::Error>>(()) /// ``` pub fn process(&self, cmd: &[&str]) -> Result<Output> { let mut child = Command::new(cmd[0]) .args(&cmd[1..]) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .spawn()?; child.stdin .as_mut() .ok_or("Failed to write to stdin")? .write_all(&self.data)?; Ok(child.wait_with_output()?) } /// Creates an `Email` by filtering the contents from stdin. /// /// This can be more efficient than creating an `Email` from stdin and /// filtering separately, since it can avoid an extra data copy. /// /// The command is expected to be provided as a `&str` array, with the /// first element being the command name and the remaining elements the /// command arguments. /// /// # Example /// /// ```no_run /// use mda::Email; /// let email = Email::from_stdin_filtered(&["bogofilter", "-ep"])?; /// # Ok::<(), Box<dyn std::error::Error>>(()) /// ``` pub fn from_stdin_filtered(cmd: &[&str]) -> Result<Self> { let output = Command::new(cmd[0]) .args(&cmd[1..]) .stdin(Stdio::inherit()) .output()?; Email::from_vec(output.stdout) } }