This parameter allows to send mails to the email address configured for users from the product's user database.
`proxmox-notify` now has a `Context` that must be set via `proxmox_notify::context::set_context` before the crate is used. Signed-off-by: Lukas Wagner <l.wag...@proxmox.com> --- pve-rs/Cargo.toml | 1 + pve-rs/src/lib.rs | 3 +- pve-rs/src/notify.rs | 81 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/pve-rs/Cargo.toml b/pve-rs/Cargo.toml index b28c118..954665f 100644 --- a/pve-rs/Cargo.toml +++ b/pve-rs/Cargo.toml @@ -23,6 +23,7 @@ env_logger = "0.9" hex = "0.4" http = "0.2.7" libc = "0.2" +log = "0.4.17" nix = "0.26" openssl = "0.10.40" serde = "1.0" diff --git a/pve-rs/src/lib.rs b/pve-rs/src/lib.rs index 0d63c28..49483d7 100644 --- a/pve-rs/src/lib.rs +++ b/pve-rs/src/lib.rs @@ -11,10 +11,11 @@ pub mod tfa; #[perlmod::package(name = "Proxmox::Lib::PVE", lib = "pve_rs")] mod export { - use crate::common; + use crate::{common, notify}; #[export] pub fn init() { common::logger::init("PVE_LOG", "info"); + notify::init(); } } diff --git a/pve-rs/src/notify.rs b/pve-rs/src/notify.rs index a6143fc..ea34bfe 100644 --- a/pve-rs/src/notify.rs +++ b/pve-rs/src/notify.rs @@ -1,3 +1,78 @@ +use std::path::Path; + +use log; + +use proxmox_notify::context::Context; + +// Some helpers borrowed and slightly adapted from `proxmox-mail-forward` + +fn normalize_for_return(s: Option<&str>) -> Option<String> { + match s?.trim() { + "" => None, + s => Some(s.to_string()), + } +} + +fn attempt_file_read<P: AsRef<Path>>(path: P) -> Option<String> { + match proxmox_sys::fs::file_read_optional_string(path) { + Ok(contents) => contents, + Err(err) => { + log::error!("{err}"); + None + } + } +} + +fn lookup_mail_address(content: &str, user: &str) -> Option<String> { + normalize_for_return(content.lines().find_map(|line| { + let fields: Vec<&str> = line.split(':').collect(); + #[allow(clippy::get_first)] // to keep expression style consistent + match fields.get(0)?.trim() == "user" && fields.get(1)?.trim() == user { + true => fields.get(6).copied(), + false => None, + } + })) +} + +struct PVEContext; + +impl Context for PVEContext { + fn lookup_email_for_user(&self, user: &str) -> Option<String> { + let content = attempt_file_read("/etc/pve/user.cfg"); + content.and_then(|content| lookup_mail_address(&content, user)) + } +} + +#[cfg(test)] +mod tests { + use crate::notify::lookup_mail_address; + + const USER_CONFIG: &str = " +user:root@pam:1:0:::r...@example.com::: +user:test@pve:1:0:::t...@example.com::: +user:no-mail@pve:1:0:::::: + "; + + #[test] + fn test_parse_mail() { + assert_eq!( + lookup_mail_address(USER_CONFIG, "root@pam"), + Some("r...@example.com".to_string()) + ); + assert_eq!( + lookup_mail_address(USER_CONFIG, "test@pve"), + Some("t...@example.com".to_string()) + ); + assert_eq!(lookup_mail_address(USER_CONFIG, "no-mail@pve"), None); + } +} + +static CONTEXT: PVEContext = PVEContext; + +pub fn init() { + proxmox_notify::context::set_context(&CONTEXT) +} + #[perlmod::package(name = "PVE::RS::Notify")] mod export { use anyhow::{bail, Error}; @@ -201,7 +276,8 @@ mod export { fn add_sendmail_endpoint( #[try_from_ref] this: &NotificationConfig, name: String, - mailto: Vec<String>, + mailto: Option<Vec<String>>, + mailto_user: Option<Vec<String>>, from_address: Option<String>, author: Option<String>, comment: Option<String>, @@ -214,6 +290,7 @@ mod export { &SendmailConfig { name, mailto, + mailto_user, from_address, author, comment, @@ -228,6 +305,7 @@ mod export { #[try_from_ref] this: &NotificationConfig, name: &str, mailto: Option<Vec<String>>, + mailto_user: Option<Vec<String>>, from_address: Option<String>, author: Option<String>, comment: Option<String>, @@ -245,6 +323,7 @@ mod export { name, &SendmailConfigUpdater { mailto, + mailto_user, from_address, author, comment, -- 2.39.2 _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel