Fix IMAP port, add tests, and verify functionality
Co-authored-by: setoelkahfi <1797197+setoelkahfi@users.noreply.github.com>
copilot-swe-agent[bot] committed
Oct 13, 2025 at 16:12 UTC
80141e00a3402bb26eda92d204c168c0c24220a9
3 files changed
+70
-4
README.md
+3
-3
@@ -31,7 +31,7 @@ A basic SMTP and IMAP server implementation in Rust with TLS/STARTTLS support.
31
cargo run
32
```
33
34
-The SMTP server listens on `127.0.0.1:2525` and the IMAP server listens on `127.0.0.1:143` by default.
34
+The SMTP server listens on `127.0.0.1:2525` and the IMAP server listens on `127.0.0.1:1143` by default.
35
36
## Testing
37
@@ -49,10 +49,10 @@ You can test the IMAP server using `nc` (netcat) or `telnet`:
49
50
```bash
51
# Connect and login
52
-echo -e "a1 CAPABILITY\r\na2 LOGIN user pass\r\na3 LIST \"\" \"*\"\r\na4 SELECT INBOX\r\na5 LOGOUT\r\n" | nc localhost 143
52
+echo -e "a1 CAPABILITY\r\na2 LOGIN user pass\r\na3 LIST \"\" \"*\"\r\na4 SELECT INBOX\r\na5 LOGOUT\r\n" | nc localhost 1143
53
54
# Fetch messages
55
-echo -e "a1 LOGIN user pass\r\na2 SELECT INBOX\r\na3 FETCH 1 (FLAGS BODY[])\r\na4 LOGOUT\r\n" | nc localhost 143
55
+echo -e "a1 LOGIN user pass\r\na2 SELECT INBOX\r\na3 FETCH 1 (FLAGS BODY[])\r\na4 LOGOUT\r\n" | nc localhost 1143
56
```
57
58
## Supported Commands
src/imap/listen.rs
+1
-1
@@ -5,7 +5,7 @@ use std::sync::Arc;
5
use tokio::net::{TcpListener, TcpStream};
6
7
pub async fn listen(store: Arc<MailboxStore>) -> anyhow::Result<()> {
8
- let addr = SocketAddr::from(([127, 0, 0, 1], 143));
8
+ let addr = SocketAddr::from(([127, 0, 0, 1], 1143));
9
let listener = TcpListener::bind(addr).await?;
10
11
tracing::info!("IMAP server listening on {}", addr);
src/storage.rs
+66
@@ -27,3 +27,69 @@ impl Default for MessageStorage {
27
Self::new()
28
}
29
}
30
+
31
+#[cfg(test)]
32
+mod tests {
33
+ use super::*;
34
+
35
+ #[test]
36
+ fn test_message_storage() {
37
+ let storage = MessageStorage::new();
38
+
39
+ // Store a message
40
+ let from = "sender@example.com".to_string();
41
+ let to = vec!["recipient@example.com".to_string()];
42
+ let content = "Subject: Test\r\n\r\nTest body".to_string();
43
+
44
+ storage.store_message(from.clone(), to.clone(), content.clone());
45
+
46
+ // Verify message was stored
47
+ if let Some(inbox) = storage.mailbox_store.get_mailbox("INBOX") {
48
+ let messages = inbox.get_messages();
49
+ assert_eq!(messages.len(), 1);
50
+ assert_eq!(messages[0].from, from);
51
+ assert_eq!(messages[0].to, to);
52
+ assert_eq!(messages[0].subject, "Test");
53
+ } else {
54
+ panic!("INBOX mailbox not found");
55
+ }
56
+ }
57
+
58
+ #[test]
59
+ fn test_multiple_messages() {
60
+ let storage = MessageStorage::new();
61
+
62
+ // Store multiple messages
63
+ storage.store_message(
64
+ "sender1@example.com".to_string(),
65
+ vec!["recipient@example.com".to_string()],
66
+ "Subject: First\r\n\r\nFirst message".to_string()
67
+ );
68
+
69
+ storage.store_message(
70
+ "sender2@example.com".to_string(),
71
+ vec!["recipient@example.com".to_string()],
72
+ "Subject: Second\r\n\r\nSecond message".to_string()
73
+ );
74
+
75
+ // Verify both messages were stored
76
+ if let Some(inbox) = storage.mailbox_store.get_mailbox("INBOX") {
77
+ let messages = inbox.get_messages();
78
+ assert_eq!(messages.len(), 2);
79
+ assert_eq!(messages[0].subject, "First");
80
+ assert_eq!(messages[1].subject, "Second");
81
+ }
82
+ }
83
+
84
+ #[test]
85
+ fn test_mailbox_list() {
86
+ let storage = MessageStorage::new();
87
+ let mailboxes = storage.mailbox_store.list_mailboxes();
88
+
89
+ // Verify default mailboxes exist
90
+ assert!(mailboxes.contains(&"INBOX".to_string()));
91
+ assert!(mailboxes.contains(&"Sent".to_string()));
92
+ assert!(mailboxes.contains(&"Drafts".to_string()));
93
+ assert!(mailboxes.contains(&"Trash".to_string()));
94
+ }
95
+}