Expand description
Outbound SMTP client primitives: MX resolution, DANE/STARTTLS, response parsing.
mailrs-smtp-client is the send-side counterpart to mailrs-smtp-proto.
It is not a full mail user agent — it is the wire-level pieces an MTA needs
to deliver a message that has already been built: looking up MX records,
choosing the right relay, opening a TLS connection that can be verified
against DNSSEC-anchored TLSA records (RFC 7672 DANE), and reading SMTP
replies that wrap across multiple lines.
Built on tokio + rustls + hickory_resolver. Extracted from
mailrs, a Rust mail server, and published independently so anyone
writing an MTA, a delivery-test harness, or a bounce probe in Rust can
share the same battle-tested foundation.
§Quick start
use mailrs_smtp_client::{MxCache, SmtpConnection, TokioResolver, sort_mx_records};
use std::time::Duration;
let resolver = TokioResolver::builder_tokio()?.build()?;
let cache = MxCache::new(Duration::from_secs(300));
let mut records = cache.resolve(&resolver, "example.com").await?;
sort_mx_records(&mut records);
let primary = records.first().ok_or("no MX")?;
// connect (reads the banner internally), EHLO, upgrade to TLS, then send
let mut conn = SmtpConnection::connect(&primary.exchange, 25).await?;
conn.ehlo("client.example.org").await?;
let mut conn = conn.starttls(&primary.exchange).await?;
conn.ehlo("client.example.org").await?;
conn.deliver(
"sender@example.org",
&["bob@example.com"],
b"Subject: hi\r\n\r\nhello\r\n",
).await?;
conn.quit().await?;§Module overview
mx— DNS MX lookup with preference-sort, in-memory cache, andA-record fallback for domains without an MX.dane— TLSA record resolution and certificate verification (RFC 7672) to defend STARTTLS against active MITM.connection—SmtpConnectionwraps the TLS-upgradable read/write loop with per-command timeouts (TimeoutConfig).response— single- and multi-line reply parser (RFC 5321 §4.2.1).
§What this crate does NOT do
- No DKIM signing, no SPF, no DMARC. Use
mail-authupstream. - No queue / retry / DSN. See
mailrs-outbound-queue. - No SMTP server. See
mailrs-smtp-protofor the receive-side state machine.
Re-exports§
pub use connection::SmtpConnection;pub use connection::TimeoutConfig;pub use dane::DaneVerifier;pub use dane::TlsaRecord;pub use dane::dane_tls_config;pub use dane::resolve_tlsa;pub use mx::MxCache;pub use mx::MxRecord;pub use mx::fallback_to_domain;pub use mx::resolve_mx;pub use mx::sort_mx_records;pub use response::SmtpResponse;pub use response::parse_response;pub use tls_outcome::StarttlsResult;pub use tls_outcome::TlsOutcome;
Modules§
- connection
SmtpConnection— async TLS / STARTTLS connection state machine + timeouts.- dane
- RFC 7672 DANE (DNS-Based Authentication of Named Entities): TLSA record lookup + TLS verification config.
- mx
- MX record lookup + priority sorting +
fallback_to_domainfor MX-less destinations. - response
- RFC 5321 multi-line response parser (
250-XXXcontinuation lines). Parsed SMTP reply from the wire — seeparse_response. - tls_
outcome - Structured outcomes of STARTTLS attempts — discriminated enum
suitable for direct mapping to
mailrs_tls_rpt::FailureType(RFC 8460 §4.3) and any downstream decision that wants more than an opaqueio::Error. Structured TLS outcomes for STARTTLS attempts.
Type Aliases§
- Tokio
Resolver - A Resolver used with Tokio