rspamd_client/protocol/
scan.rs1use crate::error::RspamdError;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5#[derive(Debug, Serialize, Deserialize)]
7pub struct RspamdScanReply {
8 #[serde(default)]
10 pub is_skipped: bool,
11 #[serde(default)]
13 pub score: f64,
14 #[serde(default)]
16 pub required_score: f64,
17 #[serde(default)]
19 pub action: String,
20 #[serde(default)]
22 pub thresholds: HashMap<String, f64>,
23 #[serde(default)]
25 pub symbols: HashMap<String, Symbol>,
26 #[serde(default)]
28 pub messages: HashMap<String, String>,
29 #[serde(default)]
31 pub urls: Vec<String>,
32 #[serde(default)]
34 pub emails: Vec<String>,
35 #[serde(rename = "message-id", default)]
37 pub message_id: String,
38 #[serde(default)]
40 pub time_real: f64,
41 #[serde(default)]
43 pub milter: Option<Milter>,
44 #[serde(default)]
45 pub filename: String,
47 #[serde(default)]
48 pub scan_time: f64,
49 #[serde(skip)]
52 pub rewritten_body: Option<Vec<u8>>,
53}
54
55#[derive(Debug, Serialize, Deserialize)]
57pub struct Symbol {
58 #[serde(default)]
59 pub name: String,
60 #[serde(default)]
61 pub score: f64,
62 #[serde(default)]
63 pub metric_score: f64,
64 #[serde(default)]
65 pub description: Option<String>,
66 #[serde(default)]
67 pub options: Option<Vec<String>>,
68}
69
70#[derive(Debug, Serialize, Deserialize)]
72pub struct Milter {
73 #[serde(default)]
74 pub add_headers: HashMap<String, MailHeader>,
75 #[serde(default)]
76 pub remove_headers: HashMap<String, i32>,
77}
78
79#[derive(Debug, Serialize, Deserialize)]
81pub struct MailHeader {
82 #[serde(default)]
83 pub value: String,
84 #[serde(default)]
85 pub order: i32,
86}
87
88#[derive(Debug, Serialize, Deserialize)]
90pub struct RspamdLearnReply {
91 #[serde(default)]
92 pub success: bool,
93 #[serde(default)]
94 pub error: Option<String>,
95}
96
97pub fn parse_scan_reply(
101 message_offset: Option<&str>,
102 body: &[u8],
103) -> Result<RspamdScanReply, RspamdError> {
104 if let Some(offset_str) = message_offset {
105 let offset = offset_str
106 .parse::<usize>()
107 .map_err(|e| RspamdError::HttpError(format!("Invalid Message-Offset value: {}", e)))?;
108
109 if offset < body.len() {
110 let mut response = serde_json::from_slice::<RspamdScanReply>(&body[..offset])?;
112 response.rewritten_body = Some(body[offset..].to_vec());
113 return Ok(response);
114 }
115 }
117 Ok(serde_json::from_slice::<RspamdScanReply>(body)?)
118}