2 unstable releases

0.2.0 Nov 5, 2024
0.1.0 Oct 19, 2024

#49 in Email

Download history 125/week @ 2024-10-15 18/week @ 2024-10-22 120/week @ 2024-11-05 1/week @ 2024-11-12 7/week @ 2024-11-19

128 downloads per month

Apache-2.0

43KB
810 lines

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: Synchronous client using attohttpc.
  • Async: Asynchronous client using reqwest.
  • Easily configurable with support for proxy and custom TLS settings.
  • Supports scanning emails for spam scores and other metrics.

Installation

Add the following to your Cargo.toml:

[dependencies]
rspamd-client = { version = "0.1", features = ["async"] }

Enable the sync and/or async features based on your requirements.

Usage

Synchronous Client

This example demonstrates how to scan an email using the synchronous client.

use rspamd_client::{Config, scan_sync};

fn main() {
    let config = Config::builder()
        .base_url("http://localhost:11333".to_string())
        .build();
    let email = "From: user@example.com\nTo: recipient@example.com\nSubject: Test\n\nThis is a test email.";

    match scan_sync(&config, email) {
        Ok(response) => println!("Scan result: {:?}", response),
        Err(e) => eprintln!("Error scanning email: {}", e),
    }
}

Asynchronous Client

This example demonstrates how to scan an email using the asynchronous client.

use rspamd_client::{Config, scan_async};
use tokio;

#[tokio::main]
async fn main() {
    let config = Config::builder()
        .base_url("http://localhost:11333".to_string())
        .build();
    let email = "From: user@example.com\nTo: recipient@example.com\nSubject: Test\n\nThis is a test email.";

    match scan_async(&config, email).await {
        Ok(response) => println!("Scan result: {:?}", response),
        Err(e) => eprintln!("Error scanning email: {}", e),
    }
}

Scan File Example

You can scan a file by reading its content into a bytes::Bytes object and sending it to Rspamd.

use rspamd_client::{Config, scan_sync};
use bytes::Bytes;
use std::fs;

fn main() {
    let config = Config::builder()
        .base_url("http://localhost:11333".to_string())
        .build();
    let file_content = fs::read("path/to/email.eml")
        .expect("Unable to read file");
    let email = Bytes::from(file_content);

    match scan_sync(&config, &email) {
        Ok(response) => println!("Scan result: {:?}", response),
        Err(e) => eprintln!("Error scanning email: {}", e),
    }
}

Configuration

The Config struct allows you to customize various aspects of the client, including the base URL, proxy settings, and TLS settings.

#[derive(Debug)]
pub struct Config<'a> {
    pub base_url: &'a str,
    pub password: Option<String>,
    pub timeout: f64,
    pub retries: u32,
    pub zstd: bool,
    pub proxy_config: Option<ProxyConfig>,
    pub tls_settings: Option<TlsSettings>,
}

impl<'a> Config<'a> {
    pub fn builder() -> ConfigBuilder<'a> {
        ConfigBuilder::default()
    }
}

#[derive(Debug)]
pub struct ProxyConfig {
    pub proxy_url: String,
}

#[derive(Debug)]
pub struct TlsSettings {
    pub ca_path: Option<String>,
}

Response Structures

The following structures are used to deserialize the responses from Rspamd:

#[derive(Debug, Serialize, Deserialize)]
pub struct RspamdScanReply {
    #[serde(default)]
    pub is_skipped: bool,
    #[serde(default)]
    pub score: f64,
    #[serde(default)]
    pub required_score: f64,
    #[serde(default)]
    pub action: String,
    #[serde(default)]
    pub thresholds: HashMap<String, f64>,
    #[serde(default)]
    pub symbols: HashMap<String, Symbol>,
    #[serde(default)]
    pub messages: HashMap<String, String>,
    #[serde(default)]
    pub urls: Vec<String>,
    #[serde(default)]
    pub emails: Vec<String>,
    #[serde(rename = "message-id", default)]
    pub message_id: String,
    #[serde(default)]
    pub time_real: f64,
    #[serde(default)]
    pub milter: Option<Milter>,
    #[serde(default)]
    pub filename: String,
    #[serde(default)]
    pub scan_time: f64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Symbol {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub score: f64,
    #[serde(default)]
    pub metric_score: f64,
    #[serde(default)]
    pub description: Option<String>,
    #[serde(default)]
    pub options: Option<Vec<String>>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Milter {
    #[serde(default)]
    pub add_headers: HashMap<String, MailHeader>,
    #[serde(default)]
    pub remove_headers: HashMap<String, i32>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct MailHeader {
    #[serde(default)]
    pub value: String,
    #[serde(default)]
    pub order: i32,
}

License

This project is licensed under the Apache 2.0 License.

Contributing

Contributions are welcome! Please open a pull request or issue on GitHub.


For more information, please refer to the Rust documentation and Rspamd documentation.

Dependencies

~10–25MB
~380K SLoC