Author: Kevin Schoon [me@kevinschoon.com]
Hash: ccd72d39abe9822cc8fb4ccde261c25007ed5691
Timestamp: Thu, 05 Sep 2024 21:52:26 +0000 (1 month ago)

+218 -22 +/-7 browse
add neomutt demo accounts, improve maitred-debug
1diff --git a/Cargo.lock b/Cargo.lock
2index 14f2435..25f2088 100644
3--- a/Cargo.lock
4+++ b/Cargo.lock
5 @@ -949,7 +949,9 @@ dependencies = [
6 "clap",
7 "futures",
8 "maitred",
9+ "serde",
10 "tokio",
11+ "toml",
12 "tracing",
13 "tracing-subscriber",
14 ]
15 @@ -1306,18 +1308,18 @@ dependencies = [
16
17 [[package]]
18 name = "serde"
19- version = "1.0.204"
20+ version = "1.0.209"
21 source = "registry+https://github.com/rust-lang/crates.io-index"
22- checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
23+ checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09"
24 dependencies = [
25 "serde_derive",
26 ]
27
28 [[package]]
29 name = "serde_derive"
30- version = "1.0.204"
31+ version = "1.0.209"
32 source = "registry+https://github.com/rust-lang/crates.io-index"
33- checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
34+ checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170"
35 dependencies = [
36 "proc-macro2",
37 "quote",
38 @@ -1337,6 +1339,15 @@ dependencies = [
39 ]
40
41 [[package]]
42+ name = "serde_spanned"
43+ version = "0.6.7"
44+ source = "registry+https://github.com/rust-lang/crates.io-index"
45+ checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
46+ dependencies = [
47+ "serde",
48+ ]
49+
50+ [[package]]
51 name = "sha1"
52 version = "0.10.6"
53 source = "registry+https://github.com/rust-lang/crates.io-index"
54 @@ -1584,6 +1595,40 @@ dependencies = [
55 ]
56
57 [[package]]
58+ name = "toml"
59+ version = "0.8.19"
60+ source = "registry+https://github.com/rust-lang/crates.io-index"
61+ checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
62+ dependencies = [
63+ "serde",
64+ "serde_spanned",
65+ "toml_datetime",
66+ "toml_edit",
67+ ]
68+
69+ [[package]]
70+ name = "toml_datetime"
71+ version = "0.6.8"
72+ source = "registry+https://github.com/rust-lang/crates.io-index"
73+ checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
74+ dependencies = [
75+ "serde",
76+ ]
77+
78+ [[package]]
79+ name = "toml_edit"
80+ version = "0.22.20"
81+ source = "registry+https://github.com/rust-lang/crates.io-index"
82+ checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
83+ dependencies = [
84+ "indexmap",
85+ "serde",
86+ "serde_spanned",
87+ "toml_datetime",
88+ "winnow",
89+ ]
90+
91+ [[package]]
92 name = "tracing"
93 version = "0.1.40"
94 source = "registry+https://github.com/rust-lang/crates.io-index"
95 @@ -1954,6 +1999,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
96 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
97
98 [[package]]
99+ name = "winnow"
100+ version = "0.6.18"
101+ source = "registry+https://github.com/rust-lang/crates.io-index"
102+ checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
103+ dependencies = [
104+ "memchr",
105+ ]
106+
107+ [[package]]
108 name = "winreg"
109 version = "0.50.0"
110 source = "registry+https://github.com/rust-lang/crates.io-index"
111 diff --git a/cmd/maitred-debug/Cargo.toml b/cmd/maitred-debug/Cargo.toml
112index 9792cd0..973dda8 100644
113--- a/cmd/maitred-debug/Cargo.toml
114+++ b/cmd/maitred-debug/Cargo.toml
115 @@ -8,7 +8,9 @@ clap = { version = "4.5.16", features = ["derive"] }
116 futures = "0.3.30"
117
118 maitred = {path = "../../maitred"}
119+ serde = "1.0.209"
120 tokio = { version = "1.39.2", features = ["full"] }
121+ toml = "0.8.19"
122 tracing = { version = "0.1.40", features = ["log"] }
123 tracing-subscriber = "0.3.18"
124
125 diff --git a/cmd/maitred-debug/src/main.rs b/cmd/maitred-debug/src/main.rs
126index 5a2d19b..e8e4382 100644
127--- a/cmd/maitred-debug/src/main.rs
128+++ b/cmd/maitred-debug/src/main.rs
129 @@ -1,15 +1,13 @@
130- use std::{
131- path::{Path, PathBuf},
132- sync::Arc,
133- };
134+ use std::fs::read_to_string;
135+ use std::path::{Path, PathBuf};
136
137 use clap::Parser;
138- use tokio::sync::{Mutex, RwLock};
139+ use toml::from_str;
140 use tracing::Level;
141
142 use maitred::{
143- mail_parser::Message, Delivery, DeliveryError, DeliveryFunc, Envelope, Error, Maildir,
144- MilterFunc, PlainAuthFunc, Server, SessionOptions,
145+ mail_parser::Message, Delivery, DeliveryError, DeliveryFunc, Envelope, Maildir, MilterFunc,
146+ PlainAuthFunc, Server, SessionOptions,
147 };
148
149 async fn print_message(envelope: &Envelope) -> Result<(), DeliveryError> {
150 @@ -20,8 +18,27 @@ async fn print_message(envelope: &Envelope) -> Result<(), DeliveryError> {
151 Ok(())
152 }
153
154+ #[derive(Clone, serde::Deserialize)]
155+ struct Account {
156+ pub address: String,
157+ }
158+
159+ #[derive(serde::Deserialize)]
160+ struct Config {
161+ pub maildir: String,
162+ pub accounts: Vec<Account>,
163+ }
164+
165+ const LONG_ABOUT: &str = r#"
166+ Maitred SMTP Demo Server
167+
168+ NOTE: This tool only exists for illustrative purposes and should not be
169+ considered stable or suitable for a production environment.
170+ "#;
171+
172+ /// Maitred SMTP Demo Server
173 #[derive(Parser, Debug)]
174- #[clap(author, version, about, long_about = None)]
175+ #[clap(author, version, about, long_about = LONG_ABOUT)]
176 struct Args {
177 /// Enable DKIM verification of incoming e-mail.
178 #[clap(long, default_value_t = false)]
179 @@ -30,24 +47,29 @@ struct Args {
180 #[clap(long, default_value_t = false)]
181 spf: bool,
182 /// Addresses from which to accept e-mail for
183- #[clap(long)]
184- addresses: Vec<String>,
185- /// Path to a directory to store e-mails in the maildir format
186- #[clap(long, default_value_t = String::from("mail"))]
187- maildir: String,
188+ #[clap(long, default_value = "maitred.toml")]
189+ config: String,
190 }
191
192 #[tokio::main]
193- async fn main() -> Result<(), Error> {
194+ async fn main() -> Result<(), Box<dyn std::error::Error>> {
195 let args = Args::parse();
196+ let config_str = read_to_string(Path::new(&args.config))?;
197+ let config: Config = from_str(&config_str)?;
198 // Create a subscriber that logs events to the console
199 tracing_subscriber::fmt()
200 .compact()
201 .with_line_number(true)
202 .with_max_level(Level::DEBUG)
203 .init();
204- let maildir_path = PathBuf::from(&args.maildir);
205- let addresses = args.addresses.clone();
206+ let maildir_path = PathBuf::from(&config.maildir);
207+ let accounts = config.accounts.clone();
208+ let addresses: Vec<String> = accounts
209+ .iter()
210+ .map(|account| account.address.clone())
211+ .collect();
212+ // initialize maildirs before starting
213+ let _ = Maildir::new(maildir_path.as_path(), &addresses)?;
214 // Set the subscriber as the default subscriber
215 let mut mail_server = Server::default()
216 .address("127.0.0.1:2525")
217 @@ -61,7 +83,7 @@ async fn main() -> Result<(), Error> {
218 let cloned = envelope.clone();
219 async move {
220 print_message(&cloned).await?;
221- let maildir = Maildir::new(maildir_path.as_path(), addresses.as_slice())?;
222+ let maildir = Maildir::new(maildir_path.as_path(), &addresses)?;
223 maildir.deliver(&cloned).await
224 }
225 }))
226 diff --git a/demo/user-1.neomuttrc b/demo/user-1.neomuttrc
227new file mode 100644
228index 0000000..9974613
229--- /dev/null
230+++ b/demo/user-1.neomuttrc
231 @@ -0,0 +1,51 @@
232+ # vim: set filetype=neomuttrc :
233+
234+ set mbox_type=Maildir
235+ set folder="mail/demo-1@example.org"
236+ set spoolfile=+
237+
238+ set realname = 'Demo User 1'
239+ set from = demo-1@example.org
240+
241+ set smtp_url=smtp://demo-1@127.0.0.1:2525
242+ set ssl_starttls = no
243+ set ssl_force_tls = false
244+
245+ set sidebar_visible
246+ set sidebar_format = "%B%<F? [%F]>%* %<N?%N/>%S"
247+ # set mail_check_stats
248+
249+ color normal default default # Text is "Text"
250+ color index color2 default ~N # New Messages are Green
251+ color index color1 default ~F # Flagged messages are Red
252+ color index color13 default ~T # Tagged Messages are Red
253+ color index color1 default ~D # Messages to delete are Red
254+ color attachment color5 default # Attachments are Pink
255+ color signature color8 default # Signatures are Surface 2
256+ color search color4 default # Highlighted results are Blue
257+
258+ color indicator default color8 # currently highlighted message Surface 2=Background Text=Foreground
259+ color error color1 default # error messages are Red
260+ color status color15 default # status line "Subtext 0"
261+ color tree color15 default # thread tree arrows Subtext 0
262+ color tilde color15 default # blank line padding Subtext 0
263+
264+ color hdrdefault color13 default # default headers Pink
265+ color header color13 default "^From:"
266+ color header color13 default "^Subject:"
267+
268+ color quoted color15 default # Subtext 0
269+ color quoted1 color7 default # Subtext 1
270+ color quoted2 color8 default # Surface 2
271+ color quoted3 color0 default # Surface 1
272+ color quoted4 color0 default
273+ color quoted5 color0 default
274+
275+ color body color2 default [\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+ # email addresses Green
276+ color body color2 default (https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+ # URLs Green
277+ color body color4 default (^|[[:space:]])\\*[^[:space:]]+\\*([[:space:]]|$) # *bold* text Blue
278+ color body color4 default (^|[[:space:]])_[^[:space:]]+_([[:space:]]|$) # _underlined_ text Blue
279+ color body color4 default (^|[[:space:]])/[^[:space:]]+/([[:space:]]|$) # /italic/ text Blue
280+
281+ color sidebar_flagged color1 default # Mailboxes with flagged mails are Red
282+ color sidebar_new color10 default # Mailboxes with new mail are Green
283 diff --git a/demo/user-2.neomuttrc b/demo/user-2.neomuttrc
284new file mode 100644
285index 0000000..fda07f0
286--- /dev/null
287+++ b/demo/user-2.neomuttrc
288 @@ -0,0 +1,51 @@
289+ # vim: set filetype=neomuttrc :
290+
291+ set mbox_type=Maildir
292+ set folder="mail/demo-2@example.org"
293+ set spoolfile=+
294+
295+ set realname = 'kevin'
296+ set from = kevin@ayllu-dev.local
297+
298+ set smtp_url=smtp://kevin@127.0.0.1:2525
299+ set ssl_starttls = no
300+ set ssl_force_tls = false
301+
302+ set sidebar_visible
303+ set sidebar_format = "%B%<F? [%F]>%* %<N?%N/>%S"
304+ # set mail_check_stats
305+
306+ color normal default default # Text is "Text"
307+ color index color2 default ~N # New Messages are Green
308+ color index color1 default ~F # Flagged messages are Red
309+ color index color13 default ~T # Tagged Messages are Red
310+ color index color1 default ~D # Messages to delete are Red
311+ color attachment color5 default # Attachments are Pink
312+ color signature color8 default # Signatures are Surface 2
313+ color search color4 default # Highlighted results are Blue
314+
315+ color indicator default color8 # currently highlighted message Surface 2=Background Text=Foreground
316+ color error color1 default # error messages are Red
317+ color status color15 default # status line "Subtext 0"
318+ color tree color15 default # thread tree arrows Subtext 0
319+ color tilde color15 default # blank line padding Subtext 0
320+
321+ color hdrdefault color13 default # default headers Pink
322+ color header color13 default "^From:"
323+ color header color13 default "^Subject:"
324+
325+ color quoted color15 default # Subtext 0
326+ color quoted1 color7 default # Subtext 1
327+ color quoted2 color8 default # Surface 2
328+ color quoted3 color0 default # Surface 1
329+ color quoted4 color0 default
330+ color quoted5 color0 default
331+
332+ color body color2 default [\-\.+_a-zA-Z0-9]+@[\-\.a-zA-Z0-9]+ # email addresses Green
333+ color body color2 default (https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+ # URLs Green
334+ color body color4 default (^|[[:space:]])\\*[^[:space:]]+\\*([[:space:]]|$) # *bold* text Blue
335+ color body color4 default (^|[[:space:]])_[^[:space:]]+_([[:space:]]|$) # _underlined_ text Blue
336+ color body color4 default (^|[[:space:]])/[^[:space:]]+/([[:space:]]|$) # /italic/ text Blue
337+
338+ color sidebar_flagged color1 default # Mailboxes with flagged mails are Red
339+ color sidebar_new color10 default # Mailboxes with new mail are Green
340 diff --git a/maitred.toml b/maitred.toml
341new file mode 100644
342index 0000000..0fcf4e1
343--- /dev/null
344+++ b/maitred.toml
345 @@ -0,0 +1,9 @@
346+ # Path of the directory to deliver mail in the "maildir" format to
347+ maildir = "mail"
348+
349+ # List of user accounts and their hard coded username / passwords
350+ [[accounts]]
351+ address = "demo-1@example.org"
352+
353+ [[accounts]]
354+ address = "demo-2@example.org"
355 diff --git a/scripts/swaks_test.sh b/scripts/swaks_test.sh
356index e73450b..78c933b 100755
357--- a/scripts/swaks_test.sh
358+++ b/scripts/swaks_test.sh
359 @@ -3,4 +3,11 @@
360 # Uses swaks: https://www.jetmore.org/john/code/swaks/ to do some basic SMTP
361 # verification. Make sure you install the tool first!
362
363- printf "Subject: Hello\nWorld\n" | swaks --to hello@example.com --server localhost:2525 --pipeline --data -
364+ make_email() {
365+ printf "From: aaaa@example.org\n"
366+ printf "To: hello@example.org\n"
367+ printf "Subject: Hello\n"
368+ printf "World\n"
369+ }
370+
371+ make_email | swaks --to hello@example.org --server localhost:2525 --pipeline --data -