| Crates.io | rspamd-client |
| lib.rs | rspamd-client |
| version | 0.5.0 |
| created_at | 2024-10-19 15:36:03.690938+00 |
| updated_at | 2025-10-15 09:15:58.081921+00 |
| description | Rspamd client API |
| homepage | https://rspamd.com |
| repository | https://github.com/rspamd/rspamdclient-rs |
| max_upload_size | |
| id | 1415476 |
| size | 138,978 |
This crate provides an HTTP client for interacting with the Rspamd service in Rust. It supports both synchronous and asynchronous operations using the attohttpc and reqwest libraries, respectively.
attohttpc) or asynchronous (reqwest) clientFile header)body_block flag)Add the following to your Cargo.toml:
[dependencies]
rspamd-client = { version = "0.4", features = ["async"] }
Enable either the sync or async feature (but not both):
async (default): Uses reqwest and tokiosync: Uses attohttpcuse rspamd_client::{Config, EnvelopeData, scan_async};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::builder()
.base_url("http://localhost:11333".to_string())
.build();
let envelope = EnvelopeData::builder()
.from("sender@example.com".to_string())
.rcpt(vec!["recipient@example.com".to_string()])
.ip("127.0.0.1".to_string())
.build();
let email = "From: user@example.com\nTo: recipient@example.com\nSubject: Test\n\nThis is a test email.";
let response = scan_async(&config, email, envelope).await?;
println!("Score: {}, Action: {}", response.score, response.action);
Ok(())
}
use rspamd_client::{Config, EnvelopeData, scan_sync};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::builder()
.base_url("http://localhost:11333".to_string())
.build();
let envelope = EnvelopeData::builder()
.from("sender@example.com".to_string())
.build();
let email = "From: user@example.com\nTo: recipient@example.com\nSubject: Test\n\nThis is a test email.";
let response = scan_sync(&config, email, envelope)?;
println!("Score: {}, Action: {}", response.score, response.action);
Ok(())
}
When the client and Rspamd server are on the same host, you can scan files without transferring the body by using the file_path option. This is a significant performance optimization:
use rspamd_client::{Config, EnvelopeData, scan_async};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::builder()
.base_url("http://localhost:11333".to_string())
.build();
let envelope = EnvelopeData::builder()
.from("sender@example.com".to_string())
.file_path("/var/mail/message.eml".to_string()) // Rspamd reads file directly
.build();
// Empty body - file is read by Rspamd from disk
let response = scan_async(&config, "", envelope).await?;
println!("Scanned file with score: {}", response.score);
Ok(())
}
Request the rewritten message body from Rspamd when modifications are applied (e.g., subject rewriting, header changes):
use rspamd_client::{Config, EnvelopeData, scan_async};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::builder()
.base_url("http://localhost:11333".to_string())
.build();
let envelope = EnvelopeData::builder()
.from("sender@example.com".to_string())
.body_block(true) // Request rewritten body if modified
.build();
let email = "From: user@example.com\nTo: recipient@example.com\nSubject: Test\n\nBody content.";
let response = scan_async(&config, email, envelope).await?;
if let Some(rewritten_body) = response.rewritten_body {
println!("Message was rewritten, new body size: {} bytes", rewritten_body.len());
// Use rewritten_body instead of original
}
Ok(())
}
Use native Rspamd HTTPCrypt encryption:
let config = Config::builder()
.base_url("http://localhost:11333".to_string())
.encryption_key("k4nz984k36xmcynm1hr9kdbn6jhcxf4ggbrb1quay7f88rpm9kay".to_string())
.build();
The encryption key must be in Rspamd base32 format and match the server's public key.
ZSTD compression is enabled by default. To disable:
let config = Config::builder()
.base_url("http://localhost:11333".to_string())
.zstd(false)
.build();
use rspamd_client::{Config, ProxyConfig};
let proxy = ProxyConfig {
proxy_url: "http://proxy.example.com:8080".to_string(),
username: Some("user".to_string()),
password: Some("pass".to_string()),
};
let config = Config::builder()
.base_url("http://localhost:11333".to_string())
.proxy_config(proxy)
.build();
base_url: Rspamd server URL (required)password: Optional authentication passwordtimeout: Request timeout in seconds (default: 30.0)retries: Number of retry attempts (default: 1)zstd: Enable ZSTD compression (default: true)encryption_key: HTTPCrypt encryption key (optional)proxy_config: HTTP proxy settings (optional)tls_settings: Custom TLS configuration (optional)from: Sender email addressrcpt: List of recipient email addressesip: Sender IP addressuser: Authenticated usernamehelo: SMTP HELO stringhostname: Resolved hostnamefile_path: Local file path for scanning (instead of body transfer)body_block: Request rewritten body in responseadditional_headers: Custom HTTP headerspub struct RspamdScanReply {
pub score: f64, // Spam score
pub action: String, // Action to take (e.g., "reject", "add header")
pub symbols: HashMap<String, Symbol>, // Detected symbols
pub messages: HashMap<String, String>, // Messages from Rspamd
pub urls: Vec<String>, // Extracted URLs
pub emails: Vec<String>, // Extracted emails
pub message_id: String, // Message ID
pub time_real: f64, // Scan time
pub milter: Option<Milter>, // Milter actions (headers to add/remove)
pub rewritten_body: Option<Vec<u8>>, // Rewritten message body (if body_block enabled)
// ... other fields
}
This project is licensed under the Apache 2.0 License.
Contributions are welcome! Please open a pull request or issue on GitHub.