mailkite 0.13.0

Official MailKite SDK for Rust — inbound email → webhook, sending, templates, broadcasts, at-rest encryption, and webhook signature verification.
Documentation

MailKite Rust SDK

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"

Quickstart

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(())
}

Authentication — API key or OAuth

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).

Receiving email (webhooks)

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)
}

At-rest encryption

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)?;

Uploading attachments

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 }

License

MIT