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
//! SMTP session state machine.
//!
//! [`SessionState`] enumerates the well-defined points in an SMTP exchange.
//! [`crate::client::SmtpClient`] tracks the current state and uses
//! [`SessionState::can_transition_to`] to reject API misuse before any byte
//! is sent on the wire. This converts ordering bugs in caller code into
//! [`crate::error::InvalidInputError`] returns instead of confusing server
//! responses.
//!
//! ## State diagram
//!
//! ```text
//! Greeting --> Ehlo --> Authentication --> MailFrom --> RcptTo --> Data
//! ^ | \ ^ | |
//! | | \ | | v
//! (re-EHLO | | \--------------| | Quit
//! after | | (skip auth) | | |
//! TLS) v v | v v
//! StartTls<----+ | MailFrom Closed
//! | (next msg)
//! (loop for more recipients)
//! ```
//!
//! `StartTls` is only entered when the caller invokes
//! [`crate::SmtpClient::starttls`] on a transport that implements
//! [`crate::transport::StartTlsCapable`]. After the TLS handshake completes
//! the state machine transitions back to `Ehlo` to re-issue the greeting
//! per RFC 3207 §4.2, and from there to `Authentication`.
//!
//! Any state may also transition directly to `Quit` and then `Closed` on a
//! caller-initiated shutdown or to `Closed` on a fatal error.
/// The phases of an SMTP exchange tracked by the client.
///
/// This enum is `non_exhaustive` so that future SMTP extensions can add
/// new phases without forcing a major version bump.