mirror of
https://github.com/stalwartlabs/stalwart.git
synced 2026-03-17 14:34:03 +00:00
97 lines
3.1 KiB
Rust
97 lines
3.1 KiB
Rust
/*
|
|
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
|
*/
|
|
|
|
use mail_parser::{HeaderName, HeaderValue, MimeHeaders, parsers::fields::thread::thread_name};
|
|
use sieve::{Context, compiler::ReceivedPart, runtime::Variable};
|
|
|
|
use super::ApplyString;
|
|
|
|
pub fn fn_received_part<'x>(ctx: &'x Context<'x>, v: Vec<Variable>) -> Variable {
|
|
if let (Ok(part), Some(HeaderValue::Received(rcvd))) = (
|
|
ReceivedPart::try_from(v[1].to_string().as_ref()),
|
|
ctx.message()
|
|
.part(ctx.part())
|
|
.and_then(|p| {
|
|
p.headers
|
|
.iter()
|
|
.filter(|h| h.name == HeaderName::Received)
|
|
.nth((v[0].to_integer() as usize).saturating_sub(1))
|
|
})
|
|
.map(|h| &h.value),
|
|
) {
|
|
part.eval(rcvd).unwrap_or_default()
|
|
} else {
|
|
Variable::default()
|
|
}
|
|
}
|
|
|
|
pub fn fn_is_encoding_problem<'x>(ctx: &'x Context<'x>, _: Vec<Variable>) -> Variable {
|
|
ctx.message()
|
|
.part(ctx.part())
|
|
.map(|p| p.is_encoding_problem)
|
|
.unwrap_or_default()
|
|
.into()
|
|
}
|
|
|
|
pub fn fn_is_attachment<'x>(ctx: &'x Context<'x>, _: Vec<Variable>) -> Variable {
|
|
ctx.message().attachments.contains(&ctx.part()).into()
|
|
}
|
|
|
|
pub fn fn_is_body<'x>(ctx: &'x Context<'x>, _: Vec<Variable>) -> Variable {
|
|
(ctx.message().text_body.contains(&ctx.part()) || ctx.message().html_body.contains(&ctx.part()))
|
|
.into()
|
|
}
|
|
|
|
pub fn fn_attachment_name<'x>(ctx: &'x Context<'x>, _: Vec<Variable>) -> Variable {
|
|
ctx.message()
|
|
.part(ctx.part())
|
|
.and_then(|p| p.attachment_name())
|
|
.unwrap_or_default()
|
|
.into()
|
|
}
|
|
|
|
pub fn fn_mime_part_len<'x>(ctx: &'x Context<'x>, _: Vec<Variable>) -> Variable {
|
|
ctx.message()
|
|
.part(ctx.part())
|
|
.map(|p| p.len())
|
|
.unwrap_or_default()
|
|
.into()
|
|
}
|
|
|
|
pub fn fn_thread_name<'x>(_: &'x Context<'x>, v: Vec<Variable>) -> Variable {
|
|
v[0].transform(|s| thread_name(s).into())
|
|
}
|
|
|
|
pub fn fn_is_header_utf8_valid<'x>(ctx: &'x Context<'x>, v: Vec<Variable>) -> Variable {
|
|
ctx.message()
|
|
.part(ctx.part())
|
|
.map(|p| {
|
|
let raw = ctx.message().raw_message();
|
|
let mut is_valid = true;
|
|
if let Some(header_name) = HeaderName::parse(v[0].to_string().as_ref()) {
|
|
for header in &p.headers {
|
|
if header.name == header_name
|
|
&& raw
|
|
.get(header.offset_start() as usize..header.offset_end() as usize)
|
|
.and_then(|raw| std::str::from_utf8(raw).ok())
|
|
.is_none()
|
|
{
|
|
is_valid = false;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
is_valid = raw
|
|
.get(p.raw_header_offset() as usize..p.raw_body_offset() as usize)
|
|
.and_then(|raw| std::str::from_utf8(raw).ok())
|
|
.is_some();
|
|
}
|
|
|
|
Variable::from(is_valid)
|
|
})
|
|
.unwrap_or(Variable::Integer(1))
|
|
}
|