vsmtp-rule-engine 2.0.1-rc.4

Next-gen MTA. Secured, Faster and Greener
Documentation
/*
 * vSMTP mail transfer agent
 * Copyright (C) 2022 viridIT SAS
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see https://www.gnu.org/licenses/.
 *
*/

use crate::api::SharedObject;
#[allow(unused_imports)]
use rhai::plugin::{
    mem, Dynamic, FnAccess, FnNamespace, ImmutableString, Module, NativeCallContext,
    PluginFunction, RhaiResult, TypeId,
};

pub use logging::*;

/// Logging mechanisms.
#[rhai::plugin::export_module]
mod logging {

    /// Log information to stdout in `nodaemon` mode or to a file.
    ///
    /// # Args
    ///
    /// * `level` - the level of the message, can be "trace", "debug", "info", "warn" or "error".
    /// * `message` - the message to log.
    ///
    /// # Effective smtp stage
    ///
    /// All of them.
    ///
    /// # Examples
    ///
    /// ```
    /// # vsmtp_test::vsl::run(
    /// # |builder| Ok(builder.add_root_filter_rules(r#"
    /// #{
    ///   connect: [
    ///     action "log on connection (str/str)" || {
    ///       log("info", `[${date()}/${time()}] client=${ctx::client_ip()}`);
    ///     },
    ///     action "log on connection (str/obj)" || {
    ///       log("error", identifier("Ehllo world!"));
    ///     },
    ///     action "log on connection (obj/obj)" || {
    ///       const level = "trace";
    ///       const message = "connection established";
    ///
    ///       log(identifier(level), identifier(message));
    ///     },
    ///     action "log on connection (obj/str)" || {
    ///       const level = "warn";
    ///
    ///       log(identifier(level), "I love vsl!");
    ///     },
    ///   ],
    /// }
    /// # "#)?.build()));
    /// ```
    #[doc(hidden)]
    #[allow(clippy::needless_pass_by_value)]
    #[rhai_fn(global, name = "log")]
    pub fn log_str_obj(level: &str, message: SharedObject) {
        log(level, &message.to_string());
    }

    /// Log information to stdout in `nodaemon` mode or to a file.
    ///
    /// # Args
    ///
    /// * `level` - the level of the message, can be "trace", "debug", "info", "warn" or "error".
    /// * `message` - the message to log.
    ///
    /// # Effective smtp stage
    ///
    /// All of them.
    ///
    /// # Examples
    ///
    /// ```
    /// # vsmtp_test::vsl::run(
    /// # |builder| Ok(builder.add_root_filter_rules(r#"
    /// #{
    ///   connect: [
    ///     action "log on connection (str/str)" || {
    ///       log("info", `[${date()}/${time()}] client=${ctx::client_ip()}`);
    ///     },
    ///     action "log on connection (str/obj)" || {
    ///       log("error", identifier("Ehllo world!"));
    ///     },
    ///     action "log on connection (obj/obj)" || {
    ///       const level = "trace";
    ///       const message = "connection established";
    ///
    ///       log(identifier(level), identifier(message));
    ///     },
    ///     action "log on connection (obj/str)" || {
    ///       const level = "warn";
    ///
    ///       log(identifier(level), "I love vsl!");
    ///     },
    ///   ],
    /// }
    /// # "#)?.build()));
    /// ```
    #[doc(hidden)]
    #[allow(clippy::needless_pass_by_value)]
    #[rhai_fn(global, name = "log", pure)]
    pub fn log_obj_str(level: &mut SharedObject, message: &str) {
        log(&level.to_string(), message);
    }

    /// Log information to stdout in `nodaemon` mode or to a file.
    ///
    /// # Args
    ///
    /// * `level` - the level of the message, can be "trace", "debug", "info", "warn" or "error".
    /// * `message` - the message to log.
    ///
    /// # Effective smtp stage
    ///
    /// All of them.
    ///
    /// # Examples
    ///
    /// ```
    /// # vsmtp_test::vsl::run(
    /// # |builder| Ok(builder.add_root_filter_rules(r#"
    /// #{
    ///   connect: [
    ///     action "log on connection (str/str)" || {
    ///       log("info", `[${date()}/${time()}] client=${ctx::client_ip()}`);
    ///     },
    ///     action "log on connection (str/obj)" || {
    ///       log("error", identifier("Ehllo world!"));
    ///     },
    ///     action "log on connection (obj/obj)" || {
    ///       const level = "trace";
    ///       const message = "connection established";
    ///
    ///       log(identifier(level), identifier(message));
    ///     },
    ///     action "log on connection (obj/str)" || {
    ///       const level = "warn";
    ///
    ///       log(identifier(level), "I love vsl!");
    ///     },
    ///   ],
    /// }
    /// # "#)?.build()));
    /// ```
    #[doc(hidden)]
    #[allow(clippy::needless_pass_by_value)]
    #[rhai_fn(global, name = "log", pure)]
    pub fn log_obj_obj(level: &mut SharedObject, message: SharedObject) {
        log(&level.to_string(), &message.to_string());
    }

    /// Log information to stdout in `nodaemon` mode or to a file.
    ///
    /// # Args
    ///
    /// * `level` - the level of the message, can be "trace", "debug", "info", "warn" or "error".
    /// * `message` - the message to log.
    ///
    /// # Effective smtp stage
    ///
    /// All of them.
    ///
    /// # Examples
    ///
    /// ```
    /// # vsmtp_test::vsl::run(
    /// # |builder| Ok(builder.add_root_filter_rules(r#"
    /// #{
    ///   connect: [
    ///     action "log on connection (str/str)" || {
    ///       log("info", `[${date()}/${time()}] client=${ctx::client_ip()}`);
    ///     },
    ///     action "log on connection (str/obj)" || {
    ///       log("error", identifier("Ehllo world!"));
    ///     },
    ///     action "log on connection (obj/obj)" || {
    ///       const level = "trace";
    ///       const message = "connection established";
    ///
    ///       log(identifier(level), identifier(message));
    ///     },
    ///     action "log on connection (obj/str)" || {
    ///       const level = "warn";
    ///
    ///       log(identifier(level), "I love vsl!");
    ///     },
    ///   ],
    /// }
    /// # "#)?.build()));
    /// ```
    #[rhai_fn(global, name = "log")]
    #[allow(clippy::cognitive_complexity)]
    pub fn log(level: &str, message: &str) {
        match <tracing::Level as std::str::FromStr>::from_str(level) {
            Ok(level) => match level {
                tracing::Level::TRACE => tracing::trace!(message),
                tracing::Level::DEBUG => tracing::debug!(message),
                tracing::Level::INFO => tracing::info!(message),
                tracing::Level::WARN => tracing::warn!(message),
                tracing::Level::ERROR => tracing::error!(message),
            },
            Err(e) => {
                tracing::warn!(
                    "level `{}` is invalid: `{}`. Message was: '{}'",
                    level,
                    e,
                    message,
                );
            }
        }
    }
}