daaki-smtp 0.2.0

An async SMTP client library
Documentation

daaki-smtp

A Rust SMTP/LMTP client built with tokio & rustls.

Highlights

  • SMTP and LMTP — support for RFC 5321 and RFC 2033.
  • Pipelining — batches commands automatically when the server advertises it.
  • CHUNKING/BINARYMIME — send large or binary messages via BDAT without dot-stuffing.
  • Async with explicit timeouts — built on tokio. Every operation takes a Duration.
  • TLS by default — rustls-based TLS with implicit TLS (port 465) and STARTTLS.
  • Typed API — validated newtypes (ReversePath, ForwardPath, Domain, Mailbox) and typed results (SendResult, LmtpSendResult) catch errors at construction time.
  • Zero unsafe code — enforced by #![deny(unsafe_code)] crate-wide.
  • Optional serde — enable the serde feature for Serialize/Deserialize on all public types.

Quick Start

[dependencies]
daaki-smtp = "0.2"

Connect, authenticate, and send a message:

use daaki_smtp::{SmtpConnection, TlsMode, ReversePath, ForwardPath};
use std::time::Duration;

#[tokio::main]
async fn main() -> daaki_smtp::Result<()> {
    let timeout = Duration::from_secs(30);

    let conn = SmtpConnection::connect(
        "smtp.example.com", 465, TlsMode::Implicit, timeout,
    ).await?;
    conn.auth_plain("user@example.com", "password", timeout).await?;

    let message = b"From: user@example.com\r\n\
                    To: recipient@example.com\r\n\
                    Subject: Hello\r\n\
                    \r\n\
                    Hello, world!\r\n";

    let from = ReversePath::new("user@example.com")?;
    let to = vec![ForwardPath::new("recipient@example.com")?];
    conn.send(&from, &to, message, timeout).await?;
    conn.quit(timeout).await?;
    Ok(())
}

LMTP

Connect to an LMTP server for local delivery. Returns per-recipient results:

# use daaki_smtp::{SmtpConnection, TlsMode, ReversePath, ForwardPath};
# use std::time::Duration;
# async fn example() -> daaki_smtp::Result<()> {
let timeout = Duration::from_secs(30);

let conn = SmtpConnection::connect_lmtp(
    "localhost", 24, TlsMode::None, timeout,
).await?;

let from = ReversePath::new("user@example.com")?;
let to = vec![ForwardPath::new("local@example.com")?];
let result = conn.send_lmtp(&from, &to, b"Subject: Hi\r\n\r\nHello\r\n", None, timeout).await?;

for r in &result.results {
    println!("{}: {}", r.recipient, r.response.text());
}
# Ok(())
# }

Supported Extensions

Category Extensions RFCs
Content encoding 8BITMIME, CHUNKING, BINARYMIME RFC 1652, 3030
Transport PIPELINING, SIZE, STARTTLS, Implicit TLS RFC 1854, 1870, 3207, 8314
Auth AUTH (PLAIN, LOGIN, OAUTHBEARER, XOAUTH2) RFC 4954, 4616, 7628
Delivery DSN (NOTIFY, ORCPT, RET, ENVID), REQUIRETLS, DELIVERBY, FUTURERELEASE, MT-PRIORITY RFC 3461, 8689, 2852, 4865, 6758
Status & addressing ENHANCEDSTATUSCODES, SMTPUTF8, VRFY, EXPN, NO-SOLICITING RFC 2034, 6531, 5321, 3865

Compatibility note: some servers advertise a legacy, non-standard SASL-IR EHLO keyword. daaki-smtp preserves it for introspection, but RFC 4954 Section 4 already allows SMTP AUTH initial responses without a separate standard extension.

License

The contents of this package are licensed under the terms of the MIT license.