io_smtp/lib.rs
1#![no_std]
2#![deny(missing_docs)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4
5//! # io-smtp
6//!
7//! I/O-free SMTP client coroutines: every network exchange is a
8//! resumable state machine emitting read and write requests instead
9//! of performing I/O itself, so the caller owns the socket and pumps
10//! the coroutine (see the client feature for a ready-made
11//! std-blocking pump).
12//!
13//! ## The coroutine contract
14//!
15//! Every coroutine implements [`coroutine::SmtpCoroutine`], whose
16//! resume method takes an optional byte slice and yields a
17//! [`coroutine::SmtpCoroutineState`]: either an intermediate
18//! [`coroutine::SmtpYield`] asking the caller to read bytes from the
19//! stream (fed back on the next resume, an empty slice signalling
20//! EOF) or to write the yielded bytes, or a terminal value carrying
21//! the result. Each module ships a runnable example of the pump loop,
22//! and [`client::SmtpClientStd`] implements it once for blocking std
23//! streams.
24//!
25//! Most coroutines delegate their wire exchange to
26//! [`send::SmtpCommandSend`], the base coroutine owning the
27//! serialise, write, read and parse cycle; they only interpret the
28//! parsed reply code. The exceptions are the pure read coroutines
29//! (the greeting and EHLO ones), which own their read loop because
30//! nothing is written first, or because the multi-line reply needs
31//! dedicated parsing.
32//!
33//! ## Layout: one folder per RFC
34//!
35//! The source tree mirrors the SMTP specification landscape, one
36//! module per RFC. [`rfc5321`] hosts the SMTP core: the coroutines
37//! for the greeting, the EHLO and HELO handshakes, the mail
38//! transaction (MAIL FROM, RCPT TO, DATA with dot-stuffing), NOOP,
39//! RSET, QUIT and a raw passthrough, next to the flattened
40//! wire-format types (reply codes, responses, paths, domains,
41//! parameters). The extensions follow: [`rfc1870`] (message size
42//! declaration), [`rfc3207`] (STARTTLS), [`rfc3461`] (delivery status
43//! notifications), [`rfc3463`] (enhanced status codes) and [`rfc4954`]
44//! (the AUTH command and its continuation data).
45//!
46//! Authentication mechanisms split in two. [`rfc7628`] (OAUTHBEARER)
47//! and [`rfc7677`] (SCRAM-SHA-256, behind the scram feature) specify
48//! cryptographic or transport behaviour beyond plain SASL framing, so
49//! they live under their own RFC module. [`sasl`] hosts the
50//! mechanisms with no such glue: PLAIN, LOGIN, ANONYMOUS and XOAUTH2.
51//!
52//! Code spanning the RFC modules lives at the crate root:
53//! [`coroutine`] defines the coroutine contract and the smtp_try
54//! macro, [`send`] the base send-one-command coroutine, [`message`]
55//! the composite whole-message send coroutine, the private utils module the shared
56//! byte-escaping and parser helpers, and [`client`] the optional
57//! std-blocking client (client feature) exposing one method per
58//! coroutine plus, with a TLS feature enabled, an end-to-end connect
59//! covering transport, STARTTLS and SASL.
60//!
61//! ## Conventions
62//!
63//! The crate is unconditionally no_std; alloc is always required,
64//! std only under the client feature. Public items carry the bare
65//! Smtp domain prefix (SMTP is not versioned). Coroutine errors
66//! normalise to the shape "SMTP operation failed: cause", and RFC
67//! wire tokens (mechanism names, capability keywords) keep their
68//! exact spelling.
69
70extern crate alloc;
71#[cfg(feature = "client")]
72extern crate std;
73
74#[cfg(feature = "client")]
75pub mod client;
76pub mod coroutine;
77pub mod message;
78pub mod rfc1870;
79pub mod rfc3207;
80pub mod rfc3461;
81pub mod rfc3463;
82pub mod rfc4954;
83pub mod rfc5321;
84pub mod rfc7628;
85#[cfg(feature = "scram")]
86pub mod rfc7677;
87pub mod sasl;
88pub mod send;
89pub(crate) mod utils;