1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//! Transport abstraction for SMTP I/O.
//!
//! The SMTP state machine in this crate is environment-independent. Adapter
//! crates (e.g. `wasm-smtp-cloudflare`) connect a runtime-native socket to
//! the state machine by implementing [`Transport`].
//!
//! ## Contract
//!
//! Implementations wrap a connected, byte-oriented stream. The trait
//! intentionally exposes only the minimum surface needed by the SMTP state
//! machine:
//!
//! - [`read`](Transport::read) returns the number of bytes filled into the
//! buffer, or `Ok(0)` to signal that the peer cleanly closed the connection.
//! - [`write_all`](Transport::write_all) must perform short-write retries
//! internally and only return after every byte has been accepted, or after
//! a fatal error.
//! - [`close`](Transport::close) releases the connection. The transport must
//! not be used for further I/O once `close` has returned.
//!
//! Errors of any kind originating below SMTP must be converted to
//! [`IoError`] at this boundary, which keeps adapter-specific types out of
//! the core public API.
//!
//! ## TLS
//!
//! Two TLS models are supported, selected by the transport:
//!
//! - **Implicit TLS** (port 465): the transport is already TLS-secured before
//! the SMTP state machine sees it. Plain [`Transport`] is sufficient.
//! - **STARTTLS** (port 587 / 25): the transport is initially plaintext and
//! is upgraded to TLS in-place after the `STARTTLS` SMTP command. Such
//! transports must additionally implement [`StartTlsCapable`].
//!
//! The TLS handshake itself, in either model, is the transport
//! implementation's responsibility.
use crateIoError;
/// Async byte-oriented transport contract used by [`crate::SmtpClient`].
///
/// See the [module-level documentation](self) for the contract.
///
/// # Security responsibilities of implementors
///
/// `wasm-smtp` deliberately knows nothing about TLS, certificates,
/// or peer identity. The transport implementation is the entire trust
/// boundary for the encrypted byte stream:
///
/// - **Certificate validation must be enforced.** When the transport
/// wraps a TLS stream, certificate-chain validation, hostname
/// matching, and trust-anchor selection are the implementor's
/// responsibility. Disabling verification (e.g. rustls'
/// `dangerous_configuration` builder) is appropriate only in tests
/// against an offline server; never ship such a transport in
/// production code.
/// - **The SNI / hostname presented at handshake time must match the
/// `host` argument the caller passed to the connect helper.** Without
/// this, an attacker who can redirect TCP traffic could hand you a
/// valid certificate for a different domain.
/// - **Failures during the TLS handshake should surface as
/// [`IoError`].** Do not paper over verification failures — a
/// silently-downgraded connection is worse than a hard error.
///
/// [`crate::SmtpClient`] depends on the transport upholding these
/// invariants; it has no way to detect their violation from inside
/// the SMTP state machine.
// Single-threaded WASM runtimes (the primary target) do not need a `Send`
// bound on the returned futures. Adapter crates that target multi-threaded
// runtimes can wrap their transport in a type that adds a `Send` bound at
// the call site.
/// Marker for a [`Transport`] that can be upgraded to TLS in-place after
/// connection.
///
/// This is what enables the SMTP `STARTTLS` flow (RFC 3207). The plaintext
/// SMTP greeting and the initial `EHLO` are exchanged in cleartext; the
/// client then issues `STARTTLS`, awaits a `220` reply, and asks the
/// transport to upgrade. From that point on the byte stream is TLS-secured
/// and the SMTP state machine continues as if it had always been so (with
/// a second `EHLO` per RFC 3207 §4.2).
///
/// Transports that are connected with Implicit TLS (port 465) need not
/// implement this trait — they are already secure at construction time.