Rust
De officiële wesender crate biedt een volledig async client gebouwd op Tokio.
Werkt met Rust 2021 edition en hoger.
github.com/wesender/wesender-rust
Installatie
Voeg toe aan Cargo.toml:
[dependencies]
wesender = "1"
tokio = { version = "1", features = ["full"] } Initialisatie
use wesender::Wesender;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let ws = Wesender::new(std::env::var("WS_API_KEY")?);
// ...
Ok(())
} E-mail versturen
let result = ws.send_email(wesender::SendEmailOptions {
from: "noreply@joudomein.nl".to_string(),
to: vec!["klant@voorbeeld.nl".to_string()],
subject: "Welkom!".to_string(),
html: Some("<p>Bedankt voor je registratie.</p>".to_string()),
..Default::default()
}).await?;
println!("{} {}", result.id, result.status); // em_01hw... queued Meerdere ontvangers
ws.send_email(wesender::SendEmailOptions {
from: "nieuwsbrief@joudomein.nl".to_string(),
to: vec!["a@voorbeeld.nl".to_string(), "b@voorbeeld.nl".to_string()],
cc: Some(vec!["manager@bedrijf.nl".to_string()]),
subject: "Maandelijks rapport".to_string(),
html: Some("<p>Zie bijgevoegde informatie.</p>".to_string()),
..Default::default()
}).await?; Bijlagen
// Cargo.toml: base64 = "0.22"
use base64::{engine::general_purpose, Engine};
let data = std::fs::read("factuur.pdf")?;
let pdf = general_purpose::STANDARD.encode(&data);
ws.send_email(wesender::SendEmailOptions {
from: "facturen@joudomein.nl".to_string(),
to: vec!["klant@voorbeeld.nl".to_string()],
subject: "Factuur 2026-0142".to_string(),
html: Some("<p>Bijgevoegd vind je jouw factuur.</p>".to_string()),
attachments: Some(vec![wesender::Attachment {
filename: "factuur-2026-0142.pdf".to_string(),
content: pdf,
content_type: "application/pdf".to_string(),
}]),
..Default::default()
}).await?; Domeinen beheren
// Alle domeinen
let domeinen = ws.list_domains().await?;
// Domein toevoegen
let domein = ws.create_domain("joudomein.nl").await?;
println!("{}", domein["dns_records"]); // SPF, DKIM, DMARC
// DNS verifiëren
let resultaat = ws.verify_domain(domein["id"].as_str().unwrap()).await?;
println!("{} {}", resultaat.spf_ok, resultaat.dkim_ok); API-sleutels beheren
// Nieuwe sleutel aanmaken
let sleutel = ws.create_api_key("Productie-server").await?;
println!("{}", sleutel.token); // ws_live_... (sla op!)
// Alle sleutels
let sleutels = ws.list_api_keys().await?;
// Sleutel verwijderen
ws.delete_api_key(&sleutel.id).await?; Foutafhandeling
use wesender::WesenderError;
match ws.send_email(wesender::SendEmailOptions {
from: "noreply@joudomein.nl".to_string(),
to: vec!["klant@voorbeeld.nl".to_string()],
subject: "Test".to_string(),
html: Some("<p>Test</p>".to_string()),
..Default::default()
}).await {
Ok(r) => println!("{}", r.id),
Err(WesenderError::Api { status, message }) => {
eprintln!("Status: {status}, Melding: {message}");
// bijv. Status: 422, Melding: Domain not verified
}
Err(e) => eprintln!("HTTP-fout: {e}"),
} Actix-web integratie
use actix_web::{web, HttpResponse};
use wesender::Wesender;
use std::sync::Arc;
pub struct AppState {
pub ws: Arc<Wesender>,
}
pub async fn stuur_welkomstmail(
state: web::Data<AppState>,
naam: String,
email: String,
) -> HttpResponse {
match state.ws.send_email(wesender::SendEmailOptions {
from: "noreply@joudomein.nl".to_string(),
to: vec![email],
subject: format!("Welkom, {naam}!"),
html: Some(format!("<h1>Hoi {naam}!</h1><p>Bedankt voor je aanmelding.</p>")),
..Default::default()
}).await {
Ok(_) => HttpResponse::Ok().finish(),
Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
}
} Zonder SDK (reqwest)
// Cargo.toml: reqwest = { version = "0.12", features = ["json"] }, serde_json = "1"
use reqwest::Client;
use serde_json::json;
Client::new()
.post("https://api.wesender.nl/emails")
.bearer_auth(std::env::var("WS_API_KEY")?)
.json(&json!({
"from": "noreply@joudomein.nl",
"to": "klant@voorbeeld.nl",
"subject": "Hallo!",
"html": "<p>Via reqwest.</p>",
}))
.send()
.await?;