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
//! SMTP relay transport.
//!
//! Implements RFC 062–063: initializes the async SMTP transport to localhost:25
//! and submits mail messages. SMTP errors are mapped to `AppError`.
//!
//! # Transport
//!
//! Uses `lettre::AsyncSmtpTransport` over plain TCP to localhost (no TLS
//! needed for loopback relay). The transport is initialized once and stored
//! in `AppState`.
//!
//! # Timeout
//!
//! Submission is wrapped in `tokio::time::timeout` using
//! `config.smtp.submission_timeout_seconds`.
use Duration;
use ;
use timeout;
use error;
use crate::;
// ---------------------------------------------------------------------------
// Transport type alias
// ---------------------------------------------------------------------------
/// Async SMTP transport used for all submissions.
pub type SmtpTransport = ;
// ---------------------------------------------------------------------------
// Initialization
// ---------------------------------------------------------------------------
/// Build the SMTP transport from config.
///
/// Uses unencrypted ("dangerous") transport to localhost — appropriate for
/// loopback relay to a local SMTP daemon.
///
/// # Errors
///
/// Returns `AppError::Internal` if the transport cannot be constructed
/// (e.g., invalid host name).
// ---------------------------------------------------------------------------
// Submission
// ---------------------------------------------------------------------------
/// Submit a `lettre::Message` to the SMTP server.
///
/// - Wraps the SMTP call in a timeout (`submission_timeout_seconds`).
/// - Maps SMTP-level errors to `AppError::SmtpUnavailable`.
///
/// # Errors
///
/// | Condition | Error |
/// |---------------------|------------------------|
/// | Timeout | `AppError::SmtpUnavailable` |
/// | Connection refused | `AppError::SmtpUnavailable` |
/// | SMTP rejection | `AppError::SmtpUnavailable` |
pub async
// ---------------------------------------------------------------------------
// Readiness check (RFC 064)
// ---------------------------------------------------------------------------
/// Test whether the SMTP server is reachable by attempting a TCP connection.
///
/// Used by `/readyz`. Returns `true` if SMTP responds, `false` otherwise.
pub async