use crate::{
api::{
EngineResult, {Context, SharedObject},
},
get_global,
};
use rhai::plugin::{
Dynamic, FnAccess, FnNamespace, Module, NativeCallContext, PluginFunction, RhaiResult, TypeId,
};
use vsmtp_plugin_vsl::objects::Object;
pub use mail_context::*;
#[rhai::plugin::export_module]
mod mail_context {
#[rhai_fn(global, pure, return_raw)]
pub fn to_string(context: &mut Context) -> EngineResult<String> {
let guard = vsl_guard_ok!(context.read());
serde_json::to_string_pretty(&*guard)
.map_err::<Box<rhai::EvalAltResult>, _>(|e| e.to_string().into())
}
#[rhai_fn(name = "client_address", return_raw)]
pub fn client_address(ncc: NativeCallContext) -> EngineResult<String> {
Ok(vsl_guard_ok!(get_global!(ncc, ctx).read())
.client_addr()
.to_string())
}
#[rhai_fn(name = "client_ip", return_raw)]
pub fn client_ip(ncc: NativeCallContext) -> EngineResult<String> {
Ok(vsl_guard_ok!(get_global!(ncc, ctx).read())
.client_addr()
.ip()
.to_string())
}
#[rhai_fn(name = "client_port", return_raw)]
pub fn client_port(ncc: NativeCallContext) -> EngineResult<rhai::INT> {
Ok(rhai::INT::from(
vsl_guard_ok!(get_global!(ncc, ctx).read())
.client_addr()
.port(),
))
}
#[rhai_fn(name = "server_address", return_raw)]
pub fn server_address(ncc: NativeCallContext) -> EngineResult<String> {
Ok(vsl_guard_ok!(get_global!(ncc, ctx).read())
.server_addr()
.to_string())
}
#[rhai_fn(name = "server_ip", return_raw)]
pub fn server_ip(ncc: NativeCallContext) -> EngineResult<String> {
Ok(vsl_guard_ok!(get_global!(ncc, ctx).read())
.server_addr()
.ip()
.to_string())
}
#[rhai_fn(name = "server_port", return_raw)]
pub fn server_port(ncc: NativeCallContext) -> EngineResult<rhai::INT> {
Ok(rhai::INT::from(
vsl_guard_ok!(get_global!(ncc, ctx).read())
.server_addr()
.port(),
))
}
#[rhai_fn(name = "connection_timestamp", return_raw)]
pub fn connection_timestamp(ncc: NativeCallContext) -> EngineResult<time::OffsetDateTime> {
Ok(*vsl_guard_ok!(get_global!(ncc, ctx).read()).connection_timestamp())
}
#[rhai_fn(name = "server_name", return_raw)]
pub fn server_name(ncc: NativeCallContext) -> EngineResult<String> {
Ok(vsl_guard_ok!(get_global!(ncc, ctx).read())
.server_name()
.to_string())
}
#[rhai_fn(name = "is_secured", return_raw)]
pub fn is_secured(ncc: NativeCallContext) -> EngineResult<bool> {
Ok(vsl_guard_ok!(get_global!(ncc, ctx).read()).tls().is_some())
}
#[rhai_fn(name = "helo", return_raw)]
pub fn helo(ncc: NativeCallContext) -> EngineResult<String> {
Ok(vsl_guard_ok!(get_global!(ncc, ctx).read())
.client_name()
.map(ToString::to_string)
.map_err(Into::<crate::error::RuntimeError>::into)?)
}
#[rhai_fn(return_raw)]
pub fn mail_from(ncc: NativeCallContext) -> EngineResult<SharedObject> {
let reverse_path = vsl_guard_ok!(get_global!(ncc, ctx).read())
.reverse_path()
.map_err(Into::<crate::error::RuntimeError>::into)?
.clone();
Ok(std::sync::Arc::new(reverse_path.map_or_else(
|| Object::Identifier("null".to_string()),
Object::Address,
)))
}
#[rhai_fn(name = "rcpt_list", return_raw)]
pub fn rcpt_list(ncc: NativeCallContext) -> EngineResult<rhai::Array> {
Ok(vsl_guard_ok!(get_global!(ncc, ctx).read())
.forward_paths()
.map_err(Into::<crate::error::RuntimeError>::into)?
.iter()
.cloned()
.map(Object::Address)
.map(std::sync::Arc::new)
.map(rhai::Dynamic::from)
.collect())
}
#[rhai_fn(name = "rcpt", return_raw)]
pub fn rcpt(ncc: NativeCallContext) -> EngineResult<SharedObject> {
let rcpt = vsl_guard_ok!(get_global!(ncc, ctx).read())
.forward_paths()
.map_err(Into::<crate::error::RuntimeError>::into)?
.last()
.ok_or_else(|| crate::error::RuntimeError::Generic {
message: "recipient are empty".to_string(),
})?
.clone();
Ok(std::sync::Arc::new(Object::Address(rcpt)))
}
#[rhai_fn(name = "mail_timestamp", return_raw)]
pub fn mail_timestamp(ncc: NativeCallContext) -> EngineResult<time::OffsetDateTime> {
Ok(*vsl_guard_ok!(get_global!(ncc, ctx).read())
.mail_timestamp()
.map_err(Into::<crate::error::RuntimeError>::into)?)
}
#[rhai_fn(name = "message_id", return_raw)]
pub fn message_id(ncc: NativeCallContext) -> EngineResult<String> {
Ok(vsl_guard_ok!(get_global!(ncc, ctx).read())
.message_uuid()
.map_err(Into::<crate::error::RuntimeError>::into)?
.to_string())
}
}