[pbs-devel] [PATCH proxmox v2 3/4] sendmail: add mail-forwarder feature
Shannon Sterz
s.sterz at proxmox.com
Mon Dec 2 13:58:58 CET 2024
this moves the mail forwarding implementation from `proxmox-notify` into
`proxmox-sendmail` to cover more `sendmail` related use-cases in one
place.
Signed-off-by: Shannon Sterz <s.sterz at proxmox.com>
---
proxmox-sendmail/Cargo.toml | 4 +++
proxmox-sendmail/src/lib.rs | 57 +++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+)
diff --git a/proxmox-sendmail/Cargo.toml b/proxmox-sendmail/Cargo.toml
index 790b324b..e04e2595 100644
--- a/proxmox-sendmail/Cargo.toml
+++ b/proxmox-sendmail/Cargo.toml
@@ -14,3 +14,7 @@ anyhow = { workspace = true }
base64 = { workspace = true }
percent-encoding = { workspace = true }
proxmox-time = { workspace = true }
+
+[features]
+default = []
+mail-forwarder = []
diff --git a/proxmox-sendmail/src/lib.rs b/proxmox-sendmail/src/lib.rs
index a42bb0cd..e1ddc63d 100644
--- a/proxmox-sendmail/src/lib.rs
+++ b/proxmox-sendmail/src/lib.rs
@@ -287,6 +287,56 @@ impl<'a> Mail<'a> {
Ok(())
}
+ /// Forwards an email message to a given list of recipients.
+ ///
+ /// `message` must be compatible with ``sendmail`` (the message is piped into stdin unmodified).
+ #[cfg(feature = "mail-forwarder")]
+ pub fn forward(
+ mailto: &[&str],
+ mailfrom: &str,
+ message: &[u8],
+ uid: Option<u32>,
+ ) -> Result<(), Error> {
+ use std::os::unix::process::CommandExt;
+
+ if mailto.is_empty() {
+ bail!("At least one recipient has to be specified!");
+ }
+
+ let mut builder = Command::new("/usr/sbin/sendmail");
+
+ builder
+ .args([
+ "-N", "never", // never send DSN (avoid mail loops)
+ "-f", mailfrom, "--",
+ ])
+ .args(mailto)
+ .stdin(Stdio::piped())
+ .stdout(Stdio::null())
+ .stderr(Stdio::null());
+
+ if let Some(uid) = uid {
+ builder.uid(uid);
+ }
+
+ let mut sendmail_process = builder
+ .spawn()
+ .with_context(|| "could not spawn sendmail process")?;
+
+ sendmail_process
+ .stdin
+ .take()
+ .unwrap()
+ .write_all(message)
+ .with_context(|| "couldn't write to sendmail stdin")?;
+
+ sendmail_process
+ .wait()
+ .with_context(|| "sendmail did not exit successfully")?;
+
+ Ok(())
+ }
+
fn format_mail(&self, now: i64) -> Result<String, Error> {
let file_boundary = format!("----_=_NextPart_001_{}", now);
let html_boundary = format!("----_=_NextPart_002_{}", now);
@@ -432,6 +482,13 @@ mod test {
assert!(result.is_err());
}
+ #[test]
+ #[cfg(feature = "mail-forwarder")]
+ fn forwarding_without_recipients_fails() {
+ let result = Mail::forward(&[], "me at example.com", String::from("text").as_bytes(), None);
+ assert!(result.is_err());
+ }
+
#[test]
fn simple_ascii_text_mail() {
let mail = Mail::new(
--
2.39.5
More information about the pbs-devel
mailing list