Rspamd Client for Rust
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.
Features
- Sync/Async: Choose between synchronous (
attohttpc) or asynchronous (reqwest) client - Mutually Exclusive: Async and sync features are mutually exclusive by design
- Connection Pooling: Persistent clients reuse TCP/TLS connections across scans (async)
- Encryption: Native HTTPCrypt encryption support
- Compression: ZSTD compression for requests and responses
- Local File Scanning: Scan files on the same host without transferring body (
Fileheader) - Body Rewriting: Receive rewritten message bodies (
body_blockflag) - Envelope Data: Configure sender, recipients, IP, HELO, hostname, and custom headers
- Proxy Support: HTTP proxy configuration
- TLS: Custom TLS settings
Installation
Add the following to your Cargo.toml:
[]
= { = "0.7", = ["async"] }
Enable either the sync or async feature (but not both):
async(default): Usesreqwestandtokiosync: Usesattohttpc
Usage
Asynchronous Client
Create one RspamdAsyncClient and reuse it for all scans: the underlying
reqwest client pools TCP (and TLS) connections, so subsequent scans skip
connection setup entirely. The client is cheap to clone and Send + Sync,
so it can be stored in a static or cached keyed by Config (which implements
Clone, Eq and Hash).
use ;
async
For a single scan, the deprecated one-shot scan_async(&config, email, envelope)
wrapper still works, but it opens a new connection on every call.
Synchronous Client
use ;
Note: attohttpc does not pool connections, so the sync client reuses
configuration and encryption state across calls, but each request still opens
a fresh connection.
Learning and Fuzzy Storage
Both clients expose the remaining commands (these target the controller
endpoint, so point base_url at it and set password):
let reply = client.learn_spam.await?;
let reply = client.learn_ham.await?;
// Flag/Weight go via EnvelopeData::additional_headers
let reply = client.fuzzy_add.await?;
let reply = client.fuzzy_del.await?;
assert!;
Advanced Features
Local File Scanning (File Header)
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 ;
async
Body Block (Rewritten Message)
Request the rewritten message body from Rspamd when modifications are applied (e.g., subject rewriting, header changes):
use ;
async
Encryption (HTTPCrypt)
Use native Rspamd HTTPCrypt encryption:
let config = builder
.base_url
.encryption_key
.build;
The encryption key must be in Rspamd base32 format and match the server's public key.
Compression
ZSTD compression is enabled by default. To disable:
let config = builder
.base_url
.zstd
.build;
Proxy Configuration
use ;
let proxy = ProxyConfig ;
let config = builder
.base_url
.proxy_config
.build;
Configuration
Config Options
base_url: Rspamd server URL (required)password: Optional authentication passwordtimeout: Request timeout as astd::time::Duration(default: 30 seconds)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)
EnvelopeData Options
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 headers
Response Structure
License
This project is licensed under the Apache 2.0 License.
Contributing
Contributions are welcome! Please open a pull request or issue on GitHub.