Skip to main content

Crate wasm_smtp_tokio

Crate wasm_smtp_tokio 

Source
Expand description

Tokio + rustls transport adapter for wasm-smtp.

wasm-smtp is runtime-agnostic: it drives the SMTP state machine and parses replies, but knows nothing about sockets or TLS. This crate provides the concrete Transport implementation that most tokio-based servers — axum, actix, warp, hyper, plain tokio — need to connect to a real SMTP submission endpoint.

§Cargo features

Two pairs of mutually-exclusive features select the TLS stack:

Trust sourcePick one
native-rootsOS trust store via rustls-native-certs (default)
webpki-rootsBundled Mozilla root set
Crypto providerPick one
aws-lc-rsBoringSSL-derived, default, FIPS paths
ringTraditional rustls provider, faster to compile

Picking both members of a pair, or neither, is a configuration error: this crate fails to compile in either case (see the compile_error! block below) so the misconfiguration is caught at cargo build time rather than in production.

§Quick start (implicit TLS, port 465)

use wasm_smtp::SmtpClient;
use wasm_smtp_tokio::TokioTlsTransport;

let transport = TokioTlsTransport::connect_implicit_tls(
    "smtp.example.com",
    465,
    "smtp.example.com", // SNI / certificate hostname
).await?;

let mut client = SmtpClient::connect(transport, "client.example.com").await?;
client.login("user@example.com", "secret").await?;
client.send_mail(
    "user@example.com",
    &["recipient@example.org"],
    "Subject: hi\r\n\r\nhello\r\n",
).await?;
client.quit().await?;

§STARTTLS (port 587)

For STARTTLS-on-587 endpoints, connect plaintext first and let wasm-smtp drive the STARTTLS upgrade:

use wasm_smtp::SmtpClient;
use wasm_smtp_tokio::TokioPlainTransport;

let transport = TokioPlainTransport::connect(
    "smtp.example.com",
    587,
    "smtp.example.com",
).await?;

// `connect_starttls` runs the EHLO + STARTTLS dance and asks the
// transport to upgrade to TLS in place.
let mut client = SmtpClient::connect_starttls(transport, "client.example.com").await?;
client.login("user@example.com", "secret").await?;

§Trust anchors

Two cargo features control where the trust roots come from:

  • native-roots (default): use the system trust store via rustls-native-certs. Best for desktop / server deployments that already manage CA trust through the OS.
  • webpki-roots: use the bundled Mozilla root set via webpki-roots. Best for minimal containers, distroless images, or any environment without a system CA store.

Pick exactly one. They are mutually exclusive at the API level — the connect helpers will fail to compile if neither is enabled.

§Custom configuration

For more control (custom root stores, ALPN, alternate SNI), use TokioTlsTransport::connect_with together with ConnectOptions:

use wasm_smtp_tokio::{TokioTlsTransport, ConnectOptions};

let opts = ConnectOptions::new()
    .with_server_name("alt-name.example.com");

let transport = TokioTlsTransport::connect_with(
    "smtp.example.com",
    465,
    opts,
).await?;

§Security

Certificate validation is on by default and cannot be disabled through the public API. There is intentionally no dangerous_configuration-style escape hatch on this crate. To talk to a server with a self-signed certificate (a development mail catcher, for instance), construct a custom root store containing the test CA and pass it through ConnectOptions::with_root_store.

Structs§

ConnectOptions
Connection-time options for TokioTlsTransport::connect_with.
TokioPlainTransport
Plaintext TCP transport, primed to be upgraded to TLS via StartTlsCapable.
TokioTlsTransport
TLS-wrapped TCP transport for implicit-TLS submission (port 465).