mockforge_smtp/
lib.rs

1//! SMTP server mocking for MockForge
2//!
3//! This crate provides SMTP server functionality for MockForge, allowing you to mock
4//! email servers for testing purposes.
5//!
6//! # Example
7//!
8//! ```no_run
9//! use mockforge_smtp::{SmtpConfig, SmtpServer, SmtpSpecRegistry};
10//! use std::sync::Arc;
11//!
12//! #[tokio::main]
13//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
14//!     let config = SmtpConfig::default();
15//!     let registry = Arc::new(SmtpSpecRegistry::new());
16//!
17//!     let server = SmtpServer::new(config, registry)?;
18//!     server.start().await?;
19//!
20//!     Ok(())
21//! }
22//! ```
23
24mod fixtures;
25mod server;
26mod spec_registry;
27
28pub use fixtures::*;
29pub use server::*;
30pub use spec_registry::*;
31
32use serde::{Deserialize, Serialize};
33use std::path::PathBuf;
34
35/// SMTP server configuration
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct SmtpConfig {
38    /// Server port (default: 1025)
39    pub port: u16,
40    /// Host address (default: 0.0.0.0)
41    pub host: String,
42    /// Server hostname for SMTP greeting
43    pub hostname: String,
44    /// Directory containing fixture files
45    pub fixtures_dir: Option<PathBuf>,
46    /// Connection timeout in seconds
47    pub timeout_secs: u64,
48    /// Maximum connections
49    pub max_connections: usize,
50    /// Enable mailbox storage
51    pub enable_mailbox: bool,
52    /// Maximum mailbox size
53    pub max_mailbox_messages: usize,
54    /// Enable STARTTLS support
55    pub enable_starttls: bool,
56    /// Path to TLS certificate file
57    pub tls_cert_path: Option<PathBuf>,
58    /// Path to TLS private key file
59    pub tls_key_path: Option<PathBuf>,
60}
61
62impl Default for SmtpConfig {
63    fn default() -> Self {
64        Self {
65            port: 1025,
66            host: "0.0.0.0".to_string(),
67            hostname: "mockforge-smtp".to_string(),
68            fixtures_dir: Some(PathBuf::from("./fixtures/smtp")),
69            timeout_secs: 300,
70            max_connections: 10,
71            enable_mailbox: true,
72            max_mailbox_messages: 1000,
73            enable_starttls: false,
74            tls_cert_path: None,
75            tls_key_path: None,
76        }
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83    use mockforge_core::protocol_abstraction::Protocol;
84
85    #[test]
86    fn test_default_config() {
87        let config = SmtpConfig::default();
88        assert_eq!(config.port, 1025);
89        assert_eq!(config.host, "0.0.0.0");
90        assert_eq!(config.hostname, "mockforge-smtp");
91    }
92
93    #[test]
94    fn test_protocol_display() {
95        assert_eq!(Protocol::Smtp.to_string(), "SMTP");
96    }
97
98    #[test]
99    fn test_smtp_config_all_defaults() {
100        let config = SmtpConfig::default();
101        assert_eq!(config.timeout_secs, 300);
102        assert_eq!(config.max_connections, 10);
103        assert!(config.enable_mailbox);
104        assert_eq!(config.max_mailbox_messages, 1000);
105        assert!(!config.enable_starttls);
106        assert!(config.tls_cert_path.is_none());
107        assert!(config.tls_key_path.is_none());
108        assert_eq!(config.fixtures_dir, Some(PathBuf::from("./fixtures/smtp")));
109    }
110
111    #[test]
112    fn test_smtp_config_serialize() {
113        let config = SmtpConfig::default();
114        let json = serde_json::to_string(&config).unwrap();
115        assert!(json.contains("\"port\":1025"));
116        assert!(json.contains("mockforge-smtp"));
117    }
118
119    #[test]
120    fn test_smtp_config_deserialize() {
121        let json = r#"{
122            "port": 2025,
123            "host": "127.0.0.1",
124            "hostname": "test-smtp",
125            "timeout_secs": 600,
126            "max_connections": 20,
127            "enable_mailbox": false,
128            "max_mailbox_messages": 500,
129            "enable_starttls": true,
130            "fixtures_dir": "/tmp/fixtures"
131        }"#;
132        let config: SmtpConfig = serde_json::from_str(json).unwrap();
133        assert_eq!(config.port, 2025);
134        assert_eq!(config.host, "127.0.0.1");
135        assert_eq!(config.hostname, "test-smtp");
136        assert_eq!(config.timeout_secs, 600);
137        assert_eq!(config.max_connections, 20);
138        assert!(!config.enable_mailbox);
139        assert!(config.enable_starttls);
140    }
141
142    #[test]
143    fn test_smtp_config_clone() {
144        let config = SmtpConfig::default();
145        let cloned = config.clone();
146        assert_eq!(config.port, cloned.port);
147        assert_eq!(config.hostname, cloned.hostname);
148    }
149
150    #[test]
151    fn test_smtp_config_debug() {
152        let config = SmtpConfig::default();
153        let debug = format!("{:?}", config);
154        assert!(debug.contains("SmtpConfig"));
155        assert!(debug.contains("1025"));
156    }
157
158    #[test]
159    fn test_smtp_config_with_tls() {
160        let config = SmtpConfig {
161            enable_starttls: true,
162            tls_cert_path: Some(PathBuf::from("/path/to/cert.pem")),
163            tls_key_path: Some(PathBuf::from("/path/to/key.pem")),
164            ..SmtpConfig::default()
165        };
166        assert!(config.enable_starttls);
167        assert!(config.tls_cert_path.is_some());
168        assert!(config.tls_key_path.is_some());
169    }
170
171    #[test]
172    fn test_smtp_config_custom_fixtures_dir() {
173        let config = SmtpConfig {
174            fixtures_dir: Some(PathBuf::from("/custom/fixtures")),
175            ..SmtpConfig::default()
176        };
177        assert_eq!(config.fixtures_dir, Some(PathBuf::from("/custom/fixtures")));
178    }
179}