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
126
127
128
129
130
131
132
133
134
135
//! 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.