The official MailKite SDK for Rust — inbound email → webhook,
sending, templates, contact lists, broadcasts, at-rest encryption, and webhook signature
verification. One low-level request plus one thin method per API endpoint; bodies and
responses are plain [serde_json::Value].
[dependencies]
mailkite = "0.13"use mailkite::Client;
use serde_json::json;
fn main() -> Result<(), mailkite::Error> {
let mk = Client::new(std::env::var("MAILKITE_API_KEY").unwrap());
let res = mk.send(json!({
"from": "hello@app.mailkite.dev",
"to": "ada@example.com",
"subject": "Hi",
"text": "It works.",
}))?;
println!("sent {}", res["id"]);
Ok(())
}The credential is always a Bearer token, so an OAuth access token works anywhere an API key does. Rule of thumb: server-to-server code → API key; anything that renders on a public URL → OAuth (so each user acts as themselves, not through a shared key).
use mailkite::Client;
// Server-to-server: a static API key (mk_live_…).
let mk = Client::new(std::env::var("MAILKITE_API_KEY").unwrap());
// OAuth: a static access token — same constructor, any Bearer credential.
let mk = Client::new(access_token);
// …or, because OAuth access tokens are short-lived, a get_token callback the SDK
// calls before each request so it always sends a fresh one (you refresh it):
let mk = Client::new_with_token(move || {
Ok(current_session_access_token()) // -> Result<String, mailkite::Error>
});
// Point at a custom base URL (self-hosted / testing):
let mk = Client::new_with_base_url(api_key, "https://api.mailkite.dev");Get an OAuth token from MailKite's authorization server (mcp.mailkite.dev, OAuth 2.1 +
PKCE, dynamic client registration).
Verify the signature before trusting an inbound event — a local HMAC-SHA256 check, no network call. Pass the raw, unparsed request body.
if mk.verify_webhook(signature_header, raw_body, webhook_secret) {
// trusted — handle the event, then acknowledge:
return mk.reply_ok(); // {"status":"ok"} (also reply_spam / reply_drop / reply_block_sender)
}Hybrid RSA-OAEP (SHA-256) + AES-256-GCM. The envelope is byte-compatible with every other MailKite SDK and MailKite's own WebCrypto, so you can encrypt in one language and decrypt in another.
let envelope = mk.encrypt("secret", public_key_pem)?; // -> compact JSON string
let plaintext = mk.decrypt(&envelope, private_key_pem)?;Get a secure, time-limited URL instead of base64-inlining large files on every send. Provide
the file one of four ways (url, bytes, path, or base64 content):
use mailkite::AttachmentUpload;
let up = mk.upload_attachment(AttachmentUpload {
path: Some("invoice.pdf".into()),
..Default::default()
})?;
// then reference up["url"] as a send() attachment { filename, url }MIT
