Rust

lettre, with a STARTTLS relay pointed at a sandbox.

Before you start

  • Rust 1.70 or later
  • lettre 0.11

1Add lettre

Cargo.toml
[dependencies]
lettre = "0.11"

2Send a test message

Your sandbox credentials
use lettre::transport::smtp::authentication::Credentials;
use lettre::{Message, SmtpTransport, Transport};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let email = Message::builder()
        .from("staging@example.com".parse()?)
        .to("anyone@example.com".parse()?)
        .subject("Sandbox check")
        .body(String::from("Hello from Rust."))?;

    let credentials = Credentials::new(
        "mc_0000000000000000".to_owned(),
        "pw_0000000000000000".to_owned(),
    );

    let mailer = SmtpTransport::starttls_relay("smtp.mailclutch.com")?
        .port(587)
        .credentials(credentials)
        .build();

    mailer.send(&email)?;
    Ok(())
}

Watch it land

Open the sandbox and the message is there — rendered HTML, plain text, raw source, attachments, and the SPF, DKIM and DMARC verdicts. It updates live, so you can leave it open next to your terminal.

Nothing is ever delivered onward, whatever address you send to; claim the inbox with an account and it stays.

Awaiting your email

Send from any address; it stops here rather than going onward. The inbox keeps what it catches for 24 hours.

What usually goes wrong

  • starttls_relay or relay

    starttls_relay connects in the clear and upgrades — that is port 587. relay is implicit TLS on 465. Pick one; mixing them is the usual cause of a handshake error.

  • Async

    AsyncSmtpTransport with the tokio1-native-tls feature takes the same builder, and send becomes .await.

Official documentationlettre (opens in a new tab)