Commit
Author: Kevin Schoon [me@kevinschoon.com]
Hash: 1ca5b4d80275a295d502f54e9cf9a9bc4dff5e71
Timestamp: Sat, 27 Jul 2024 19:02:26 +0000 (4 months ago)

+1525 -150 +/-18 browse
flesh out modules for the maitred crate, implement a very broken smtp server
1diff --git a/.gitignore b/.gitignore
2new file mode 100644
3index 0000000..eb5a316
4--- /dev/null
5+++ b/.gitignore
6 @@ -0,0 +1 @@
7+ target
8 diff --git a/Cargo.lock b/Cargo.lock
9index 162e1b5..90c9ea4 100644
10--- a/Cargo.lock
11+++ b/Cargo.lock
12 @@ -3,13 +3,341 @@
13 version = 3
14
15 [[package]]
16+ name = "addr2line"
17+ version = "0.22.0"
18+ source = "registry+https://github.com/rust-lang/crates.io-index"
19+ checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
20+ dependencies = [
21+ "gimli",
22+ ]
23+
24+ [[package]]
25+ name = "adler"
26+ version = "1.0.2"
27+ source = "registry+https://github.com/rust-lang/crates.io-index"
28+ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
29+
30+ [[package]]
31+ name = "ahash"
32+ version = "0.8.11"
33+ source = "registry+https://github.com/rust-lang/crates.io-index"
34+ checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
35+ dependencies = [
36+ "cfg-if",
37+ "once_cell",
38+ "version_check",
39+ "zerocopy",
40+ ]
41+
42+ [[package]]
43+ name = "allocator-api2"
44+ version = "0.2.18"
45+ source = "registry+https://github.com/rust-lang/crates.io-index"
46+ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
47+
48+ [[package]]
49+ name = "autocfg"
50+ version = "1.3.0"
51+ source = "registry+https://github.com/rust-lang/crates.io-index"
52+ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
53+
54+ [[package]]
55+ name = "backtrace"
56+ version = "0.3.73"
57+ source = "registry+https://github.com/rust-lang/crates.io-index"
58+ checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
59+ dependencies = [
60+ "addr2line",
61+ "cc",
62+ "cfg-if",
63+ "libc",
64+ "miniz_oxide",
65+ "object",
66+ "rustc-demangle",
67+ ]
68+
69+ [[package]]
70+ name = "bitflags"
71+ version = "2.6.0"
72+ source = "registry+https://github.com/rust-lang/crates.io-index"
73+ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
74+
75+ [[package]]
76+ name = "bytes"
77+ version = "1.6.1"
78+ source = "registry+https://github.com/rust-lang/crates.io-index"
79+ checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952"
80+
81+ [[package]]
82+ name = "cc"
83+ version = "1.1.6"
84+ source = "registry+https://github.com/rust-lang/crates.io-index"
85+ checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f"
86+
87+ [[package]]
88+ name = "cfg-if"
89+ version = "1.0.0"
90+ source = "registry+https://github.com/rust-lang/crates.io-index"
91+ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
92+
93+ [[package]]
94+ name = "futures"
95+ version = "0.3.30"
96+ source = "registry+https://github.com/rust-lang/crates.io-index"
97+ checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
98+ dependencies = [
99+ "futures-channel",
100+ "futures-core",
101+ "futures-executor",
102+ "futures-io",
103+ "futures-sink",
104+ "futures-task",
105+ "futures-util",
106+ ]
107+
108+ [[package]]
109+ name = "futures-channel"
110+ version = "0.3.30"
111+ source = "registry+https://github.com/rust-lang/crates.io-index"
112+ checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
113+ dependencies = [
114+ "futures-core",
115+ "futures-sink",
116+ ]
117+
118+ [[package]]
119+ name = "futures-core"
120+ version = "0.3.30"
121+ source = "registry+https://github.com/rust-lang/crates.io-index"
122+ checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
123+
124+ [[package]]
125+ name = "futures-executor"
126+ version = "0.3.30"
127+ source = "registry+https://github.com/rust-lang/crates.io-index"
128+ checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
129+ dependencies = [
130+ "futures-core",
131+ "futures-task",
132+ "futures-util",
133+ ]
134+
135+ [[package]]
136+ name = "futures-io"
137+ version = "0.3.30"
138+ source = "registry+https://github.com/rust-lang/crates.io-index"
139+ checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
140+
141+ [[package]]
142+ name = "futures-macro"
143+ version = "0.3.30"
144+ source = "registry+https://github.com/rust-lang/crates.io-index"
145+ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
146+ dependencies = [
147+ "proc-macro2",
148+ "quote",
149+ "syn",
150+ ]
151+
152+ [[package]]
153+ name = "futures-sink"
154+ version = "0.3.30"
155+ source = "registry+https://github.com/rust-lang/crates.io-index"
156+ checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
157+
158+ [[package]]
159+ name = "futures-task"
160+ version = "0.3.30"
161+ source = "registry+https://github.com/rust-lang/crates.io-index"
162+ checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
163+
164+ [[package]]
165+ name = "futures-util"
166+ version = "0.3.30"
167+ source = "registry+https://github.com/rust-lang/crates.io-index"
168+ checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
169+ dependencies = [
170+ "futures-channel",
171+ "futures-core",
172+ "futures-io",
173+ "futures-macro",
174+ "futures-sink",
175+ "futures-task",
176+ "memchr",
177+ "pin-project-lite",
178+ "pin-utils",
179+ "slab",
180+ ]
181+
182+ [[package]]
183+ name = "gimli"
184+ version = "0.29.0"
185+ source = "registry+https://github.com/rust-lang/crates.io-index"
186+ checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
187+
188+ [[package]]
189+ name = "hashbrown"
190+ version = "0.14.5"
191+ source = "registry+https://github.com/rust-lang/crates.io-index"
192+ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
193+ dependencies = [
194+ "ahash",
195+ "allocator-api2",
196+ ]
197+
198+ [[package]]
199+ name = "hermit-abi"
200+ version = "0.3.9"
201+ source = "registry+https://github.com/rust-lang/crates.io-index"
202+ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
203+
204+ [[package]]
205+ name = "lazy_static"
206+ version = "1.5.0"
207+ source = "registry+https://github.com/rust-lang/crates.io-index"
208+ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
209+
210+ [[package]]
211+ name = "libc"
212+ version = "0.2.155"
213+ source = "registry+https://github.com/rust-lang/crates.io-index"
214+ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
215+
216+ [[package]]
217+ name = "lock_api"
218+ version = "0.4.12"
219+ source = "registry+https://github.com/rust-lang/crates.io-index"
220+ checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
221+ dependencies = [
222+ "autocfg",
223+ "scopeguard",
224+ ]
225+
226+ [[package]]
227+ name = "log"
228+ version = "0.4.22"
229+ source = "registry+https://github.com/rust-lang/crates.io-index"
230+ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
231+
232+ [[package]]
233 name = "maitred"
234 version = "0.1.0"
235 dependencies = [
236+ "bytes",
237+ "futures",
238 "smtp-proto",
239+ "thiserror",
240+ "tokio",
241+ "tokio-stream",
242+ "tokio-util",
243+ "tracing",
244 ]
245
246 [[package]]
247+ name = "maitred-debug"
248+ version = "0.1.0"
249+ dependencies = [
250+ "futures",
251+ "maitred",
252+ "tokio",
253+ "tracing",
254+ "tracing-subscriber",
255+ ]
256+
257+ [[package]]
258+ name = "memchr"
259+ version = "2.7.4"
260+ source = "registry+https://github.com/rust-lang/crates.io-index"
261+ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
262+
263+ [[package]]
264+ name = "miniz_oxide"
265+ version = "0.7.4"
266+ source = "registry+https://github.com/rust-lang/crates.io-index"
267+ checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
268+ dependencies = [
269+ "adler",
270+ ]
271+
272+ [[package]]
273+ name = "mio"
274+ version = "1.0.1"
275+ source = "registry+https://github.com/rust-lang/crates.io-index"
276+ checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
277+ dependencies = [
278+ "hermit-abi",
279+ "libc",
280+ "wasi",
281+ "windows-sys",
282+ ]
283+
284+ [[package]]
285+ name = "nu-ansi-term"
286+ version = "0.46.0"
287+ source = "registry+https://github.com/rust-lang/crates.io-index"
288+ checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
289+ dependencies = [
290+ "overload",
291+ "winapi",
292+ ]
293+
294+ [[package]]
295+ name = "object"
296+ version = "0.36.2"
297+ source = "registry+https://github.com/rust-lang/crates.io-index"
298+ checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
299+ dependencies = [
300+ "memchr",
301+ ]
302+
303+ [[package]]
304+ name = "once_cell"
305+ version = "1.19.0"
306+ source = "registry+https://github.com/rust-lang/crates.io-index"
307+ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
308+
309+ [[package]]
310+ name = "overload"
311+ version = "0.1.1"
312+ source = "registry+https://github.com/rust-lang/crates.io-index"
313+ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
314+
315+ [[package]]
316+ name = "parking_lot"
317+ version = "0.12.3"
318+ source = "registry+https://github.com/rust-lang/crates.io-index"
319+ checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
320+ dependencies = [
321+ "lock_api",
322+ "parking_lot_core",
323+ ]
324+
325+ [[package]]
326+ name = "parking_lot_core"
327+ version = "0.9.10"
328+ source = "registry+https://github.com/rust-lang/crates.io-index"
329+ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
330+ dependencies = [
331+ "cfg-if",
332+ "libc",
333+ "redox_syscall",
334+ "smallvec",
335+ "windows-targets",
336+ ]
337+
338+ [[package]]
339+ name = "pin-project-lite"
340+ version = "0.2.14"
341+ source = "registry+https://github.com/rust-lang/crates.io-index"
342+ checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
343+
344+ [[package]]
345+ name = "pin-utils"
346+ version = "0.1.0"
347+ source = "registry+https://github.com/rust-lang/crates.io-index"
348+ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
349+
350+ [[package]]
351 name = "proc-macro2"
352 version = "1.0.86"
353 source = "registry+https://github.com/rust-lang/crates.io-index"
354 @@ -28,6 +356,27 @@ dependencies = [
355 ]
356
357 [[package]]
358+ name = "redox_syscall"
359+ version = "0.5.3"
360+ source = "registry+https://github.com/rust-lang/crates.io-index"
361+ checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
362+ dependencies = [
363+ "bitflags",
364+ ]
365+
366+ [[package]]
367+ name = "rustc-demangle"
368+ version = "0.1.24"
369+ source = "registry+https://github.com/rust-lang/crates.io-index"
370+ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
371+
372+ [[package]]
373+ name = "scopeguard"
374+ version = "1.2.0"
375+ source = "registry+https://github.com/rust-lang/crates.io-index"
376+ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
377+
378+ [[package]]
379 name = "serde"
380 version = "1.0.204"
381 source = "registry+https://github.com/rust-lang/crates.io-index"
382 @@ -48,6 +397,39 @@ dependencies = [
383 ]
384
385 [[package]]
386+ name = "sharded-slab"
387+ version = "0.1.7"
388+ source = "registry+https://github.com/rust-lang/crates.io-index"
389+ checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
390+ dependencies = [
391+ "lazy_static",
392+ ]
393+
394+ [[package]]
395+ name = "signal-hook-registry"
396+ version = "1.4.2"
397+ source = "registry+https://github.com/rust-lang/crates.io-index"
398+ checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
399+ dependencies = [
400+ "libc",
401+ ]
402+
403+ [[package]]
404+ name = "slab"
405+ version = "0.4.9"
406+ source = "registry+https://github.com/rust-lang/crates.io-index"
407+ checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
408+ dependencies = [
409+ "autocfg",
410+ ]
411+
412+ [[package]]
413+ name = "smallvec"
414+ version = "1.13.2"
415+ source = "registry+https://github.com/rust-lang/crates.io-index"
416+ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
417+
418+ [[package]]
419 name = "smtp-proto"
420 version = "0.1.5"
421 source = "registry+https://github.com/rust-lang/crates.io-index"
422 @@ -57,6 +439,16 @@ dependencies = [
423 ]
424
425 [[package]]
426+ name = "socket2"
427+ version = "0.5.7"
428+ source = "registry+https://github.com/rust-lang/crates.io-index"
429+ checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
430+ dependencies = [
431+ "libc",
432+ "windows-sys",
433+ ]
434+
435+ [[package]]
436 name = "syn"
437 version = "2.0.72"
438 source = "registry+https://github.com/rust-lang/crates.io-index"
439 @@ -68,7 +460,286 @@ dependencies = [
440 ]
441
442 [[package]]
443+ name = "thiserror"
444+ version = "1.0.63"
445+ source = "registry+https://github.com/rust-lang/crates.io-index"
446+ checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
447+ dependencies = [
448+ "thiserror-impl",
449+ ]
450+
451+ [[package]]
452+ name = "thiserror-impl"
453+ version = "1.0.63"
454+ source = "registry+https://github.com/rust-lang/crates.io-index"
455+ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
456+ dependencies = [
457+ "proc-macro2",
458+ "quote",
459+ "syn",
460+ ]
461+
462+ [[package]]
463+ name = "thread_local"
464+ version = "1.1.8"
465+ source = "registry+https://github.com/rust-lang/crates.io-index"
466+ checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
467+ dependencies = [
468+ "cfg-if",
469+ "once_cell",
470+ ]
471+
472+ [[package]]
473+ name = "tokio"
474+ version = "1.39.2"
475+ source = "registry+https://github.com/rust-lang/crates.io-index"
476+ checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1"
477+ dependencies = [
478+ "backtrace",
479+ "bytes",
480+ "libc",
481+ "mio",
482+ "parking_lot",
483+ "pin-project-lite",
484+ "signal-hook-registry",
485+ "socket2",
486+ "tokio-macros",
487+ "windows-sys",
488+ ]
489+
490+ [[package]]
491+ name = "tokio-macros"
492+ version = "2.4.0"
493+ source = "registry+https://github.com/rust-lang/crates.io-index"
494+ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
495+ dependencies = [
496+ "proc-macro2",
497+ "quote",
498+ "syn",
499+ ]
500+
501+ [[package]]
502+ name = "tokio-stream"
503+ version = "0.1.15"
504+ source = "registry+https://github.com/rust-lang/crates.io-index"
505+ checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af"
506+ dependencies = [
507+ "futures-core",
508+ "pin-project-lite",
509+ "tokio",
510+ "tokio-util",
511+ ]
512+
513+ [[package]]
514+ name = "tokio-util"
515+ version = "0.7.11"
516+ source = "registry+https://github.com/rust-lang/crates.io-index"
517+ checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
518+ dependencies = [
519+ "bytes",
520+ "futures-core",
521+ "futures-io",
522+ "futures-sink",
523+ "futures-util",
524+ "hashbrown",
525+ "pin-project-lite",
526+ "slab",
527+ "tokio",
528+ ]
529+
530+ [[package]]
531+ name = "tracing"
532+ version = "0.1.40"
533+ source = "registry+https://github.com/rust-lang/crates.io-index"
534+ checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
535+ dependencies = [
536+ "log",
537+ "pin-project-lite",
538+ "tracing-attributes",
539+ "tracing-core",
540+ ]
541+
542+ [[package]]
543+ name = "tracing-attributes"
544+ version = "0.1.27"
545+ source = "registry+https://github.com/rust-lang/crates.io-index"
546+ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
547+ dependencies = [
548+ "proc-macro2",
549+ "quote",
550+ "syn",
551+ ]
552+
553+ [[package]]
554+ name = "tracing-core"
555+ version = "0.1.32"
556+ source = "registry+https://github.com/rust-lang/crates.io-index"
557+ checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
558+ dependencies = [
559+ "once_cell",
560+ "valuable",
561+ ]
562+
563+ [[package]]
564+ name = "tracing-log"
565+ version = "0.2.0"
566+ source = "registry+https://github.com/rust-lang/crates.io-index"
567+ checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
568+ dependencies = [
569+ "log",
570+ "once_cell",
571+ "tracing-core",
572+ ]
573+
574+ [[package]]
575+ name = "tracing-subscriber"
576+ version = "0.3.18"
577+ source = "registry+https://github.com/rust-lang/crates.io-index"
578+ checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
579+ dependencies = [
580+ "nu-ansi-term",
581+ "sharded-slab",
582+ "smallvec",
583+ "thread_local",
584+ "tracing-core",
585+ "tracing-log",
586+ ]
587+
588+ [[package]]
589 name = "unicode-ident"
590 version = "1.0.12"
591 source = "registry+https://github.com/rust-lang/crates.io-index"
592 checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
593+
594+ [[package]]
595+ name = "valuable"
596+ version = "0.1.0"
597+ source = "registry+https://github.com/rust-lang/crates.io-index"
598+ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
599+
600+ [[package]]
601+ name = "version_check"
602+ version = "0.9.5"
603+ source = "registry+https://github.com/rust-lang/crates.io-index"
604+ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
605+
606+ [[package]]
607+ name = "wasi"
608+ version = "0.11.0+wasi-snapshot-preview1"
609+ source = "registry+https://github.com/rust-lang/crates.io-index"
610+ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
611+
612+ [[package]]
613+ name = "winapi"
614+ version = "0.3.9"
615+ source = "registry+https://github.com/rust-lang/crates.io-index"
616+ checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
617+ dependencies = [
618+ "winapi-i686-pc-windows-gnu",
619+ "winapi-x86_64-pc-windows-gnu",
620+ ]
621+
622+ [[package]]
623+ name = "winapi-i686-pc-windows-gnu"
624+ version = "0.4.0"
625+ source = "registry+https://github.com/rust-lang/crates.io-index"
626+ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
627+
628+ [[package]]
629+ name = "winapi-x86_64-pc-windows-gnu"
630+ version = "0.4.0"
631+ source = "registry+https://github.com/rust-lang/crates.io-index"
632+ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
633+
634+ [[package]]
635+ name = "windows-sys"
636+ version = "0.52.0"
637+ source = "registry+https://github.com/rust-lang/crates.io-index"
638+ checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
639+ dependencies = [
640+ "windows-targets",
641+ ]
642+
643+ [[package]]
644+ name = "windows-targets"
645+ version = "0.52.6"
646+ source = "registry+https://github.com/rust-lang/crates.io-index"
647+ checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
648+ dependencies = [
649+ "windows_aarch64_gnullvm",
650+ "windows_aarch64_msvc",
651+ "windows_i686_gnu",
652+ "windows_i686_gnullvm",
653+ "windows_i686_msvc",
654+ "windows_x86_64_gnu",
655+ "windows_x86_64_gnullvm",
656+ "windows_x86_64_msvc",
657+ ]
658+
659+ [[package]]
660+ name = "windows_aarch64_gnullvm"
661+ version = "0.52.6"
662+ source = "registry+https://github.com/rust-lang/crates.io-index"
663+ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
664+
665+ [[package]]
666+ name = "windows_aarch64_msvc"
667+ version = "0.52.6"
668+ source = "registry+https://github.com/rust-lang/crates.io-index"
669+ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
670+
671+ [[package]]
672+ name = "windows_i686_gnu"
673+ version = "0.52.6"
674+ source = "registry+https://github.com/rust-lang/crates.io-index"
675+ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
676+
677+ [[package]]
678+ name = "windows_i686_gnullvm"
679+ version = "0.52.6"
680+ source = "registry+https://github.com/rust-lang/crates.io-index"
681+ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
682+
683+ [[package]]
684+ name = "windows_i686_msvc"
685+ version = "0.52.6"
686+ source = "registry+https://github.com/rust-lang/crates.io-index"
687+ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
688+
689+ [[package]]
690+ name = "windows_x86_64_gnu"
691+ version = "0.52.6"
692+ source = "registry+https://github.com/rust-lang/crates.io-index"
693+ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
694+
695+ [[package]]
696+ name = "windows_x86_64_gnullvm"
697+ version = "0.52.6"
698+ source = "registry+https://github.com/rust-lang/crates.io-index"
699+ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
700+
701+ [[package]]
702+ name = "windows_x86_64_msvc"
703+ version = "0.52.6"
704+ source = "registry+https://github.com/rust-lang/crates.io-index"
705+ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
706+
707+ [[package]]
708+ name = "zerocopy"
709+ version = "0.7.35"
710+ source = "registry+https://github.com/rust-lang/crates.io-index"
711+ checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
712+ dependencies = [
713+ "zerocopy-derive",
714+ ]
715+
716+ [[package]]
717+ name = "zerocopy-derive"
718+ version = "0.7.35"
719+ source = "registry+https://github.com/rust-lang/crates.io-index"
720+ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
721+ dependencies = [
722+ "proc-macro2",
723+ "quote",
724+ "syn",
725+ ]
726 diff --git a/Cargo.toml b/Cargo.toml
727index 44744d4..cb9d044 100644
728--- a/Cargo.toml
729+++ b/Cargo.toml
730 @@ -1,11 +1,7 @@
731- [package]
732- name = "maitred"
733- version = "0.1.0"
734- edition = "2021"
735+ [workspace]
736+ resolver = "2"
737
738- [dependencies]
739- smtp-proto = { version = "0.1.5", features = ["serde", "serde_support"] }
740-
741- [[bin]]
742- name = "maitred-debug"
743- path = "cmd/matrid-debug/src/main.rs"
744+ members = [
745+ "maitred",
746+ "cmd/maitred-debug"
747+ ]
748 diff --git a/cmd/maitred-debug/.gitignore b/cmd/maitred-debug/.gitignore
749new file mode 100644
750index 0000000..ea8c4bf
751--- /dev/null
752+++ b/cmd/maitred-debug/.gitignore
753 @@ -0,0 +1 @@
754+ /target
755 diff --git a/cmd/maitred-debug/Cargo.lock b/cmd/maitred-debug/Cargo.lock
756new file mode 100644
757index 0000000..661ff90
758--- /dev/null
759+++ b/cmd/maitred-debug/Cargo.lock
760 @@ -0,0 +1,531 @@
761+ # This file is automatically @generated by Cargo.
762+ # It is not intended for manual editing.
763+ version = 3
764+
765+ [[package]]
766+ name = "addr2line"
767+ version = "0.22.0"
768+ source = "registry+https://github.com/rust-lang/crates.io-index"
769+ checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
770+ dependencies = [
771+ "gimli",
772+ ]
773+
774+ [[package]]
775+ name = "adler"
776+ version = "1.0.2"
777+ source = "registry+https://github.com/rust-lang/crates.io-index"
778+ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
779+
780+ [[package]]
781+ name = "ahash"
782+ version = "0.8.11"
783+ source = "registry+https://github.com/rust-lang/crates.io-index"
784+ checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
785+ dependencies = [
786+ "cfg-if",
787+ "once_cell",
788+ "version_check",
789+ "zerocopy",
790+ ]
791+
792+ [[package]]
793+ name = "allocator-api2"
794+ version = "0.2.18"
795+ source = "registry+https://github.com/rust-lang/crates.io-index"
796+ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
797+
798+ [[package]]
799+ name = "autocfg"
800+ version = "1.3.0"
801+ source = "registry+https://github.com/rust-lang/crates.io-index"
802+ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
803+
804+ [[package]]
805+ name = "backtrace"
806+ version = "0.3.73"
807+ source = "registry+https://github.com/rust-lang/crates.io-index"
808+ checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
809+ dependencies = [
810+ "addr2line",
811+ "cc",
812+ "cfg-if",
813+ "libc",
814+ "miniz_oxide",
815+ "object",
816+ "rustc-demangle",
817+ ]
818+
819+ [[package]]
820+ name = "bitflags"
821+ version = "2.6.0"
822+ source = "registry+https://github.com/rust-lang/crates.io-index"
823+ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
824+
825+ [[package]]
826+ name = "bytes"
827+ version = "1.6.1"
828+ source = "registry+https://github.com/rust-lang/crates.io-index"
829+ checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952"
830+
831+ [[package]]
832+ name = "cc"
833+ version = "1.1.6"
834+ source = "registry+https://github.com/rust-lang/crates.io-index"
835+ checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f"
836+
837+ [[package]]
838+ name = "cfg-if"
839+ version = "1.0.0"
840+ source = "registry+https://github.com/rust-lang/crates.io-index"
841+ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
842+
843+ [[package]]
844+ name = "futures-core"
845+ version = "0.3.30"
846+ source = "registry+https://github.com/rust-lang/crates.io-index"
847+ checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
848+
849+ [[package]]
850+ name = "futures-io"
851+ version = "0.3.30"
852+ source = "registry+https://github.com/rust-lang/crates.io-index"
853+ checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
854+
855+ [[package]]
856+ name = "futures-macro"
857+ version = "0.3.30"
858+ source = "registry+https://github.com/rust-lang/crates.io-index"
859+ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
860+ dependencies = [
861+ "proc-macro2",
862+ "quote",
863+ "syn",
864+ ]
865+
866+ [[package]]
867+ name = "futures-sink"
868+ version = "0.3.30"
869+ source = "registry+https://github.com/rust-lang/crates.io-index"
870+ checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
871+
872+ [[package]]
873+ name = "futures-task"
874+ version = "0.3.30"
875+ source = "registry+https://github.com/rust-lang/crates.io-index"
876+ checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
877+
878+ [[package]]
879+ name = "futures-util"
880+ version = "0.3.30"
881+ source = "registry+https://github.com/rust-lang/crates.io-index"
882+ checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
883+ dependencies = [
884+ "futures-core",
885+ "futures-macro",
886+ "futures-task",
887+ "pin-project-lite",
888+ "pin-utils",
889+ "slab",
890+ ]
891+
892+ [[package]]
893+ name = "gimli"
894+ version = "0.29.0"
895+ source = "registry+https://github.com/rust-lang/crates.io-index"
896+ checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
897+
898+ [[package]]
899+ name = "hashbrown"
900+ version = "0.14.5"
901+ source = "registry+https://github.com/rust-lang/crates.io-index"
902+ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
903+ dependencies = [
904+ "ahash",
905+ "allocator-api2",
906+ ]
907+
908+ [[package]]
909+ name = "hermit-abi"
910+ version = "0.3.9"
911+ source = "registry+https://github.com/rust-lang/crates.io-index"
912+ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
913+
914+ [[package]]
915+ name = "libc"
916+ version = "0.2.155"
917+ source = "registry+https://github.com/rust-lang/crates.io-index"
918+ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
919+
920+ [[package]]
921+ name = "lock_api"
922+ version = "0.4.12"
923+ source = "registry+https://github.com/rust-lang/crates.io-index"
924+ checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
925+ dependencies = [
926+ "autocfg",
927+ "scopeguard",
928+ ]
929+
930+ [[package]]
931+ name = "maitred"
932+ version = "0.1.0"
933+ dependencies = [
934+ "smtp-proto",
935+ ]
936+
937+ [[package]]
938+ name = "maitred-debug"
939+ version = "0.1.0"
940+ dependencies = [
941+ "maitred",
942+ "tokio",
943+ "tokio-util",
944+ ]
945+
946+ [[package]]
947+ name = "memchr"
948+ version = "2.7.4"
949+ source = "registry+https://github.com/rust-lang/crates.io-index"
950+ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
951+
952+ [[package]]
953+ name = "miniz_oxide"
954+ version = "0.7.4"
955+ source = "registry+https://github.com/rust-lang/crates.io-index"
956+ checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
957+ dependencies = [
958+ "adler",
959+ ]
960+
961+ [[package]]
962+ name = "mio"
963+ version = "1.0.1"
964+ source = "registry+https://github.com/rust-lang/crates.io-index"
965+ checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
966+ dependencies = [
967+ "hermit-abi",
968+ "libc",
969+ "wasi",
970+ "windows-sys",
971+ ]
972+
973+ [[package]]
974+ name = "object"
975+ version = "0.36.2"
976+ source = "registry+https://github.com/rust-lang/crates.io-index"
977+ checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
978+ dependencies = [
979+ "memchr",
980+ ]
981+
982+ [[package]]
983+ name = "once_cell"
984+ version = "1.19.0"
985+ source = "registry+https://github.com/rust-lang/crates.io-index"
986+ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
987+
988+ [[package]]
989+ name = "parking_lot"
990+ version = "0.12.3"
991+ source = "registry+https://github.com/rust-lang/crates.io-index"
992+ checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
993+ dependencies = [
994+ "lock_api",
995+ "parking_lot_core",
996+ ]
997+
998+ [[package]]
999+ name = "parking_lot_core"
1000+ version = "0.9.10"
1001+ source = "registry+https://github.com/rust-lang/crates.io-index"
1002+ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
1003+ dependencies = [
1004+ "cfg-if",
1005+ "libc",
1006+ "redox_syscall",
1007+ "smallvec",
1008+ "windows-targets",
1009+ ]
1010+
1011+ [[package]]
1012+ name = "pin-project-lite"
1013+ version = "0.2.14"
1014+ source = "registry+https://github.com/rust-lang/crates.io-index"
1015+ checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
1016+
1017+ [[package]]
1018+ name = "pin-utils"
1019+ version = "0.1.0"
1020+ source = "registry+https://github.com/rust-lang/crates.io-index"
1021+ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
1022+
1023+ [[package]]
1024+ name = "proc-macro2"
1025+ version = "1.0.86"
1026+ source = "registry+https://github.com/rust-lang/crates.io-index"
1027+ checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
1028+ dependencies = [
1029+ "unicode-ident",
1030+ ]
1031+
1032+ [[package]]
1033+ name = "quote"
1034+ version = "1.0.36"
1035+ source = "registry+https://github.com/rust-lang/crates.io-index"
1036+ checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
1037+ dependencies = [
1038+ "proc-macro2",
1039+ ]
1040+
1041+ [[package]]
1042+ name = "redox_syscall"
1043+ version = "0.5.3"
1044+ source = "registry+https://github.com/rust-lang/crates.io-index"
1045+ checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
1046+ dependencies = [
1047+ "bitflags",
1048+ ]
1049+
1050+ [[package]]
1051+ name = "rustc-demangle"
1052+ version = "0.1.24"
1053+ source = "registry+https://github.com/rust-lang/crates.io-index"
1054+ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
1055+
1056+ [[package]]
1057+ name = "scopeguard"
1058+ version = "1.2.0"
1059+ source = "registry+https://github.com/rust-lang/crates.io-index"
1060+ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
1061+
1062+ [[package]]
1063+ name = "serde"
1064+ version = "1.0.204"
1065+ source = "registry+https://github.com/rust-lang/crates.io-index"
1066+ checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
1067+ dependencies = [
1068+ "serde_derive",
1069+ ]
1070+
1071+ [[package]]
1072+ name = "serde_derive"
1073+ version = "1.0.204"
1074+ source = "registry+https://github.com/rust-lang/crates.io-index"
1075+ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
1076+ dependencies = [
1077+ "proc-macro2",
1078+ "quote",
1079+ "syn",
1080+ ]
1081+
1082+ [[package]]
1083+ name = "signal-hook-registry"
1084+ version = "1.4.2"
1085+ source = "registry+https://github.com/rust-lang/crates.io-index"
1086+ checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
1087+ dependencies = [
1088+ "libc",
1089+ ]
1090+
1091+ [[package]]
1092+ name = "slab"
1093+ version = "0.4.9"
1094+ source = "registry+https://github.com/rust-lang/crates.io-index"
1095+ checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
1096+ dependencies = [
1097+ "autocfg",
1098+ ]
1099+
1100+ [[package]]
1101+ name = "smallvec"
1102+ version = "1.13.2"
1103+ source = "registry+https://github.com/rust-lang/crates.io-index"
1104+ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
1105+
1106+ [[package]]
1107+ name = "smtp-proto"
1108+ version = "0.1.5"
1109+ source = "registry+https://github.com/rust-lang/crates.io-index"
1110+ checksum = "51b8ad3dd187f0d4debab02ad65405a9919d6a4f7bce25bd64a258781063a53a"
1111+ dependencies = [
1112+ "serde",
1113+ ]
1114+
1115+ [[package]]
1116+ name = "socket2"
1117+ version = "0.5.7"
1118+ source = "registry+https://github.com/rust-lang/crates.io-index"
1119+ checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
1120+ dependencies = [
1121+ "libc",
1122+ "windows-sys",
1123+ ]
1124+
1125+ [[package]]
1126+ name = "syn"
1127+ version = "2.0.72"
1128+ source = "registry+https://github.com/rust-lang/crates.io-index"
1129+ checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
1130+ dependencies = [
1131+ "proc-macro2",
1132+ "quote",
1133+ "unicode-ident",
1134+ ]
1135+
1136+ [[package]]
1137+ name = "tokio"
1138+ version = "1.39.2"
1139+ source = "registry+https://github.com/rust-lang/crates.io-index"
1140+ checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1"
1141+ dependencies = [
1142+ "backtrace",
1143+ "bytes",
1144+ "libc",
1145+ "mio",
1146+ "parking_lot",
1147+ "pin-project-lite",
1148+ "signal-hook-registry",
1149+ "socket2",
1150+ "tokio-macros",
1151+ "windows-sys",
1152+ ]
1153+
1154+ [[package]]
1155+ name = "tokio-macros"
1156+ version = "2.4.0"
1157+ source = "registry+https://github.com/rust-lang/crates.io-index"
1158+ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
1159+ dependencies = [
1160+ "proc-macro2",
1161+ "quote",
1162+ "syn",
1163+ ]
1164+
1165+ [[package]]
1166+ name = "tokio-util"
1167+ version = "0.7.11"
1168+ source = "registry+https://github.com/rust-lang/crates.io-index"
1169+ checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1"
1170+ dependencies = [
1171+ "bytes",
1172+ "futures-core",
1173+ "futures-io",
1174+ "futures-sink",
1175+ "futures-util",
1176+ "hashbrown",
1177+ "pin-project-lite",
1178+ "slab",
1179+ "tokio",
1180+ ]
1181+
1182+ [[package]]
1183+ name = "unicode-ident"
1184+ version = "1.0.12"
1185+ source = "registry+https://github.com/rust-lang/crates.io-index"
1186+ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
1187+
1188+ [[package]]
1189+ name = "version_check"
1190+ version = "0.9.5"
1191+ source = "registry+https://github.com/rust-lang/crates.io-index"
1192+ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
1193+
1194+ [[package]]
1195+ name = "wasi"
1196+ version = "0.11.0+wasi-snapshot-preview1"
1197+ source = "registry+https://github.com/rust-lang/crates.io-index"
1198+ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
1199+
1200+ [[package]]
1201+ name = "windows-sys"
1202+ version = "0.52.0"
1203+ source = "registry+https://github.com/rust-lang/crates.io-index"
1204+ checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
1205+ dependencies = [
1206+ "windows-targets",
1207+ ]
1208+
1209+ [[package]]
1210+ name = "windows-targets"
1211+ version = "0.52.6"
1212+ source = "registry+https://github.com/rust-lang/crates.io-index"
1213+ checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
1214+ dependencies = [
1215+ "windows_aarch64_gnullvm",
1216+ "windows_aarch64_msvc",
1217+ "windows_i686_gnu",
1218+ "windows_i686_gnullvm",
1219+ "windows_i686_msvc",
1220+ "windows_x86_64_gnu",
1221+ "windows_x86_64_gnullvm",
1222+ "windows_x86_64_msvc",
1223+ ]
1224+
1225+ [[package]]
1226+ name = "windows_aarch64_gnullvm"
1227+ version = "0.52.6"
1228+ source = "registry+https://github.com/rust-lang/crates.io-index"
1229+ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
1230+
1231+ [[package]]
1232+ name = "windows_aarch64_msvc"
1233+ version = "0.52.6"
1234+ source = "registry+https://github.com/rust-lang/crates.io-index"
1235+ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
1236+
1237+ [[package]]
1238+ name = "windows_i686_gnu"
1239+ version = "0.52.6"
1240+ source = "registry+https://github.com/rust-lang/crates.io-index"
1241+ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
1242+
1243+ [[package]]
1244+ name = "windows_i686_gnullvm"
1245+ version = "0.52.6"
1246+ source = "registry+https://github.com/rust-lang/crates.io-index"
1247+ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
1248+
1249+ [[package]]
1250+ name = "windows_i686_msvc"
1251+ version = "0.52.6"
1252+ source = "registry+https://github.com/rust-lang/crates.io-index"
1253+ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
1254+
1255+ [[package]]
1256+ name = "windows_x86_64_gnu"
1257+ version = "0.52.6"
1258+ source = "registry+https://github.com/rust-lang/crates.io-index"
1259+ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
1260+
1261+ [[package]]
1262+ name = "windows_x86_64_gnullvm"
1263+ version = "0.52.6"
1264+ source = "registry+https://github.com/rust-lang/crates.io-index"
1265+ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
1266+
1267+ [[package]]
1268+ name = "windows_x86_64_msvc"
1269+ version = "0.52.6"
1270+ source = "registry+https://github.com/rust-lang/crates.io-index"
1271+ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
1272+
1273+ [[package]]
1274+ name = "zerocopy"
1275+ version = "0.7.35"
1276+ source = "registry+https://github.com/rust-lang/crates.io-index"
1277+ checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
1278+ dependencies = [
1279+ "zerocopy-derive",
1280+ ]
1281+
1282+ [[package]]
1283+ name = "zerocopy-derive"
1284+ version = "0.7.35"
1285+ source = "registry+https://github.com/rust-lang/crates.io-index"
1286+ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
1287+ dependencies = [
1288+ "proc-macro2",
1289+ "quote",
1290+ "syn",
1291+ ]
1292 diff --git a/cmd/maitred-debug/Cargo.toml b/cmd/maitred-debug/Cargo.toml
1293new file mode 100644
1294index 0000000..df1d532
1295--- /dev/null
1296+++ b/cmd/maitred-debug/Cargo.toml
1297 @@ -0,0 +1,16 @@
1298+ [package]
1299+ name = "maitred-debug"
1300+ version = "0.1.0"
1301+ edition = "2021"
1302+
1303+ [dependencies]
1304+ futures = "0.3.30"
1305+
1306+ maitred = {path = "../../maitred"}
1307+ tokio = { version = "1.39.2", features = ["full"] }
1308+ tracing = { version = "0.1.40", features = ["log"] }
1309+ tracing-subscriber = "0.3.18"
1310+
1311+ [[bin]]
1312+ name = "maitred-debug"
1313+ path = "src/main.rs"
1314 diff --git a/cmd/maitred-debug/src/main.rs b/cmd/maitred-debug/src/main.rs
1315new file mode 100644
1316index 0000000..b4db71a
1317--- /dev/null
1318+++ b/cmd/maitred-debug/src/main.rs
1319 @@ -0,0 +1,17 @@
1320+ use maitred::{Builder, Error};
1321+ use tracing::Level;
1322+
1323+ #[tokio::main]
1324+ async fn main() -> Result<(), Error> {
1325+ // Create a subscriber that logs events to the console
1326+ tracing_subscriber::fmt()
1327+ .compact()
1328+ .with_line_number(true)
1329+ .with_max_level(Level::DEBUG)
1330+ .init();
1331+
1332+ // Set the subscriber as the default subscriber
1333+ let mail_server = Builder::default().listen("127.0.0.1:2525").build();
1334+ mail_server.listen().await?;
1335+ Ok(())
1336+ }
1337 diff --git a/cmd/matrid-debug/.gitignore b/cmd/matrid-debug/.gitignore
1338deleted file mode 100644
1339index ea8c4bf..0000000
1340--- a/cmd/matrid-debug/.gitignore
1341+++ /dev/null
1342 @@ -1 +0,0 @@
1343- /target
1344 diff --git a/cmd/matrid-debug/Cargo.lock b/cmd/matrid-debug/Cargo.lock
1345deleted file mode 100644
1346index df8a777..0000000
1347--- a/cmd/matrid-debug/Cargo.lock
1348+++ /dev/null
1349 @@ -1,81 +0,0 @@
1350- # This file is automatically @generated by Cargo.
1351- # It is not intended for manual editing.
1352- version = 3
1353-
1354- [[package]]
1355- name = "maitred"
1356- version = "0.1.0"
1357- dependencies = [
1358- "smtp-proto",
1359- ]
1360-
1361- [[package]]
1362- name = "matrid-debug"
1363- version = "0.1.0"
1364- dependencies = [
1365- "maitred",
1366- ]
1367-
1368- [[package]]
1369- name = "proc-macro2"
1370- version = "1.0.86"
1371- source = "registry+https://github.com/rust-lang/crates.io-index"
1372- checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
1373- dependencies = [
1374- "unicode-ident",
1375- ]
1376-
1377- [[package]]
1378- name = "quote"
1379- version = "1.0.36"
1380- source = "registry+https://github.com/rust-lang/crates.io-index"
1381- checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
1382- dependencies = [
1383- "proc-macro2",
1384- ]
1385-
1386- [[package]]
1387- name = "serde"
1388- version = "1.0.204"
1389- source = "registry+https://github.com/rust-lang/crates.io-index"
1390- checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
1391- dependencies = [
1392- "serde_derive",
1393- ]
1394-
1395- [[package]]
1396- name = "serde_derive"
1397- version = "1.0.204"
1398- source = "registry+https://github.com/rust-lang/crates.io-index"
1399- checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
1400- dependencies = [
1401- "proc-macro2",
1402- "quote",
1403- "syn",
1404- ]
1405-
1406- [[package]]
1407- name = "smtp-proto"
1408- version = "0.1.5"
1409- source = "registry+https://github.com/rust-lang/crates.io-index"
1410- checksum = "51b8ad3dd187f0d4debab02ad65405a9919d6a4f7bce25bd64a258781063a53a"
1411- dependencies = [
1412- "serde",
1413- ]
1414-
1415- [[package]]
1416- name = "syn"
1417- version = "2.0.72"
1418- source = "registry+https://github.com/rust-lang/crates.io-index"
1419- checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
1420- dependencies = [
1421- "proc-macro2",
1422- "quote",
1423- "unicode-ident",
1424- ]
1425-
1426- [[package]]
1427- name = "unicode-ident"
1428- version = "1.0.12"
1429- source = "registry+https://github.com/rust-lang/crates.io-index"
1430- checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
1431 diff --git a/cmd/matrid-debug/Cargo.toml b/cmd/matrid-debug/Cargo.toml
1432deleted file mode 100644
1433index 3f093fa..0000000
1434--- a/cmd/matrid-debug/Cargo.toml
1435+++ /dev/null
1436 @@ -1,8 +0,0 @@
1437- [package]
1438- name = "matrid-debug"
1439- version = "0.1.0"
1440- edition = "2021"
1441-
1442- [dependencies]
1443-
1444- maitred = {path = "../../"}
1445 diff --git a/cmd/matrid-debug/src/main.rs b/cmd/matrid-debug/src/main.rs
1446deleted file mode 100644
1447index 2ad2084..0000000
1448--- a/cmd/matrid-debug/src/main.rs
1449+++ /dev/null
1450 @@ -1,5 +0,0 @@
1451- use maitred::serve;
1452-
1453- fn main() {
1454- serve()
1455- }
1456 diff --git a/maitred/Cargo.lock b/maitred/Cargo.lock
1457new file mode 100644
1458index 0000000..162e1b5
1459--- /dev/null
1460+++ b/maitred/Cargo.lock
1461 @@ -0,0 +1,74 @@
1462+ # This file is automatically @generated by Cargo.
1463+ # It is not intended for manual editing.
1464+ version = 3
1465+
1466+ [[package]]
1467+ name = "maitred"
1468+ version = "0.1.0"
1469+ dependencies = [
1470+ "smtp-proto",
1471+ ]
1472+
1473+ [[package]]
1474+ name = "proc-macro2"
1475+ version = "1.0.86"
1476+ source = "registry+https://github.com/rust-lang/crates.io-index"
1477+ checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
1478+ dependencies = [
1479+ "unicode-ident",
1480+ ]
1481+
1482+ [[package]]
1483+ name = "quote"
1484+ version = "1.0.36"
1485+ source = "registry+https://github.com/rust-lang/crates.io-index"
1486+ checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
1487+ dependencies = [
1488+ "proc-macro2",
1489+ ]
1490+
1491+ [[package]]
1492+ name = "serde"
1493+ version = "1.0.204"
1494+ source = "registry+https://github.com/rust-lang/crates.io-index"
1495+ checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
1496+ dependencies = [
1497+ "serde_derive",
1498+ ]
1499+
1500+ [[package]]
1501+ name = "serde_derive"
1502+ version = "1.0.204"
1503+ source = "registry+https://github.com/rust-lang/crates.io-index"
1504+ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
1505+ dependencies = [
1506+ "proc-macro2",
1507+ "quote",
1508+ "syn",
1509+ ]
1510+
1511+ [[package]]
1512+ name = "smtp-proto"
1513+ version = "0.1.5"
1514+ source = "registry+https://github.com/rust-lang/crates.io-index"
1515+ checksum = "51b8ad3dd187f0d4debab02ad65405a9919d6a4f7bce25bd64a258781063a53a"
1516+ dependencies = [
1517+ "serde",
1518+ ]
1519+
1520+ [[package]]
1521+ name = "syn"
1522+ version = "2.0.72"
1523+ source = "registry+https://github.com/rust-lang/crates.io-index"
1524+ checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
1525+ dependencies = [
1526+ "proc-macro2",
1527+ "quote",
1528+ "unicode-ident",
1529+ ]
1530+
1531+ [[package]]
1532+ name = "unicode-ident"
1533+ version = "1.0.12"
1534+ source = "registry+https://github.com/rust-lang/crates.io-index"
1535+ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
1536 diff --git a/maitred/Cargo.toml b/maitred/Cargo.toml
1537new file mode 100644
1538index 0000000..af22925
1539--- /dev/null
1540+++ b/maitred/Cargo.toml
1541 @@ -0,0 +1,14 @@
1542+ [package]
1543+ name = "maitred"
1544+ version = "0.1.0"
1545+ edition = "2021"
1546+
1547+ [dependencies]
1548+ bytes = "1.6.1"
1549+ futures = "0.3.30"
1550+ smtp-proto = { version = "0.1.5", features = ["serde", "serde_support"] }
1551+ thiserror = "1.0.63"
1552+ tokio = { version = "1.39.2", features = ["full"] }
1553+ tokio-stream = { version = "0.1.15", features = ["full"] }
1554+ tokio-util = { version = "0.7.11", features = ["full"] }
1555+ tracing = { version = "0.1.40", features = ["log"] }
1556 diff --git a/maitred/src/error.rs b/maitred/src/error.rs
1557new file mode 100644
1558index 0000000..05d6c21
1559--- /dev/null
1560+++ b/maitred/src/error.rs
1561 @@ -0,0 +1,11 @@
1562+ use smtp_proto::{Error as SmtpError};
1563+
1564+ #[derive(Debug, thiserror::Error)]
1565+ pub enum Error {
1566+ #[error("Unspecified internal error: {0}")]
1567+ Internal(String),
1568+ #[error("Io: {0}")]
1569+ Io(#[from] std::io::Error),
1570+ #[error("Smtp failure: {0}")]
1571+ Smtp(#[from] SmtpError),
1572+ }
1573 diff --git a/maitred/src/lib.rs b/maitred/src/lib.rs
1574new file mode 100644
1575index 0000000..0c51127
1576--- /dev/null
1577+++ b/maitred/src/lib.rs
1578 @@ -0,0 +1,6 @@
1579+ mod error;
1580+ mod server;
1581+ mod transport;
1582+
1583+ pub use error::Error;
1584+ pub use server::{Builder, Server};
1585 diff --git a/maitred/src/server.rs b/maitred/src/server.rs
1586new file mode 100644
1587index 0000000..d17e807
1588--- /dev/null
1589+++ b/maitred/src/server.rs
1590 @@ -0,0 +1,127 @@
1591+ use futures::SinkExt;
1592+ use smtp_proto::{Request, Response};
1593+ use tokio::net::{TcpListener, TcpStream};
1594+ use tokio_stream::StreamExt;
1595+ use tokio_util::codec::Framed;
1596+
1597+ use crate::error::Error;
1598+ use crate::transport::Transport;
1599+
1600+ /// State of an active SMTP session
1601+ #[derive(Default)]
1602+ struct Session {
1603+ // all previous commands excluding
1604+ pub history: Vec<Request<String>>,
1605+ // message body
1606+ pub body: Vec<u8>,
1607+ }
1608+
1609+ impl Session {
1610+ /// If the session is in data transfer mode
1611+ pub fn data_transfer(self) -> bool {
1612+ self.history
1613+ .last()
1614+ .is_some_and(|req| matches!(req, Request::Data))
1615+ }
1616+ }
1617+
1618+ pub struct Server {
1619+ addr: String,
1620+ }
1621+
1622+ #[derive(Default)]
1623+ pub struct Builder {
1624+ addr: String,
1625+ }
1626+
1627+ impl Builder {
1628+ pub fn listen(mut self, addr: &str) -> Builder {
1629+ self.addr = addr.to_string();
1630+ self
1631+ }
1632+
1633+ pub fn build(self) -> Server {
1634+ Server {
1635+ addr: self.addr.clone(),
1636+ }
1637+ }
1638+ }
1639+
1640+ impl Server {
1641+ async fn process(&self, stream: TcpStream) -> Result<(), Error> {
1642+ let peer = stream.peer_addr()?;
1643+ tracing::info!("Processing new TCP connection from {:?}", peer);
1644+ let transport = Transport::default();
1645+ let mut framed = Framed::new(stream, transport);
1646+ let mut session = Session::default();
1647+ 'outer: while let Some(request) = framed.next().await {
1648+ tracing::debug!("Processing SMTP request: {:?}", request);
1649+ match request {
1650+ Ok(req) => {
1651+ session.history.push(req.clone());
1652+ match req {
1653+ Request::Ehlo { host } => {
1654+ framed
1655+ .send(Response::new(250, 0, 0, 0, format!("Hello {}", host)))
1656+ .await?;
1657+ }
1658+ Request::Lhlo { host } => todo!(),
1659+ Request::Helo { host } => {
1660+ framed
1661+ .send(Response::new(250, 0, 0, 0, format!("Hello {}", host)))
1662+ .await?;
1663+ }
1664+ Request::Mail { from } => {}
1665+ Request::Rcpt { to } => {}
1666+ Request::Bdat {
1667+ chunk_size,
1668+ is_last,
1669+ } => todo!(),
1670+ Request::Auth {
1671+ mechanism,
1672+ initial_response,
1673+ } => todo!(),
1674+ Request::Noop { value } => todo!(),
1675+ Request::Vrfy { value } => todo!(),
1676+ Request::Expn { value } => todo!(),
1677+ Request::Help { value } => todo!(),
1678+ Request::Etrn { name } => todo!(),
1679+ Request::Atrn { domains } => todo!(),
1680+ Request::Burl { uri, is_last } => todo!(),
1681+ Request::StartTls => todo!(),
1682+ Request::Data => {
1683+ tracing::info!("Client starting transfer");
1684+ // FIXME: read messages here, likely need to wrap
1685+ // Request in another enum and implement in the
1686+ // decoder
1687+ unimplemented!("fixme")
1688+ }
1689+ Request::Rset => todo!(),
1690+ Request::Quit => {
1691+ framed
1692+ .send(Response::new(221, 0, 0, 0, "Ciao!".to_string()))
1693+ .await?;
1694+ break 'outer;
1695+ }
1696+ }
1697+ }
1698+ Err(err) => {
1699+ tracing::warn!("Socket closed with error: {:?}", err)
1700+ }
1701+ }
1702+ }
1703+ tracing::info!("Connection closed");
1704+ Ok(())
1705+ }
1706+
1707+ pub async fn listen(&self) -> Result<(), Error> {
1708+ let listener = TcpListener::bind(&self.addr).await?;
1709+ tracing::info!("Mail server listening @ {}", self.addr);
1710+ loop {
1711+ let (socket, _) = listener.accept().await.unwrap();
1712+ if let Err(err) = self.process(socket).await {
1713+ tracing::warn!("Client encountered an error: {:?}", err);
1714+ }
1715+ }
1716+ }
1717+ }
1718 diff --git a/maitred/src/transport.rs b/maitred/src/transport.rs
1719new file mode 100644
1720index 0000000..6001ac8
1721--- /dev/null
1722+++ b/maitred/src/transport.rs
1723 @@ -0,0 +1,50 @@
1724+ use std::io::Write;
1725+
1726+ use bytes::BytesMut;
1727+ use smtp_proto::request::receiver::RequestReceiver;
1728+ pub use smtp_proto::{Request, Response};
1729+ use tokio_util::codec::{Decoder, Encoder};
1730+
1731+ struct Wrapper<'a>(&'a mut BytesMut);
1732+
1733+ impl Write for Wrapper<'_> {
1734+ fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
1735+ self.0.extend_from_slice(buf);
1736+ Ok(buf.len())
1737+ }
1738+
1739+ fn flush(&mut self) -> std::io::Result<()> {
1740+ Ok(())
1741+ }
1742+ }
1743+
1744+ /// SMTP Transport
1745+ #[derive(Default)]
1746+ pub struct Transport {
1747+ prev: Option<Request<String>>,
1748+ }
1749+
1750+ impl Encoder<Response<String>> for Transport {
1751+ type Error = crate::Error;
1752+
1753+ fn encode(&mut self, item: Response<String>, dst: &mut BytesMut) -> Result<(), Self::Error> {
1754+ item.write(Wrapper(dst))?;
1755+ Ok(())
1756+ }
1757+ }
1758+
1759+ impl Decoder for Transport {
1760+ type Item = Request<String>;
1761+ type Error = crate::Error;
1762+
1763+ fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
1764+ if src.is_empty() {
1765+ return Ok(None);
1766+ }
1767+ let mut r = RequestReceiver::default();
1768+ let buf = src.split_to(src.len());
1769+ let request = r.ingest(&mut buf.iter(), buf.to_vec().as_slice())?;
1770+ self.prev = Some(request.clone());
1771+ Ok(Some(request))
1772+ }
1773+ }
1774 diff --git a/src/lib.rs b/src/lib.rs
1775deleted file mode 100644
1776index 41c3ef1..0000000
1777--- a/src/lib.rs
1778+++ /dev/null
1779 @@ -1,45 +0,0 @@
1780- use smtp_proto::{request::receiver::RequestReceiver, Request};
1781-
1782- pub fn serve() {
1783- let stdin = std::io::stdin();
1784- let mut r = RequestReceiver::default();
1785- let mut requests: Vec<Request<String>> = Vec::new();
1786- let mut is_data_req = false;
1787- let mut data: Vec<u8> = Vec::new();
1788- for line in stdin.lines() {
1789- if is_data_req {
1790- let line = line.unwrap();
1791- data.extend(line.bytes());
1792- if line == "." {
1793- break;
1794- }
1795- continue;
1796- }
1797- let line = line.unwrap();
1798- let line = line + "\n";
1799- let mut bytes = line.as_bytes().iter();
1800- match r.ingest(&mut bytes, line.as_bytes()) {
1801- Ok(request) => {
1802- println!("Request: {:?}", request);
1803- match request {
1804- Request::Data => {
1805- println!("Enter .<CR> to end the transaction");
1806- is_data_req = true;
1807- continue;
1808- }
1809- Request::Quit => {
1810- println!("quit");
1811- break;
1812- }
1813- _ => {}
1814- }
1815- requests.push(request);
1816- }
1817- Err(err) => {
1818- println!("cannot process request: {}", err);
1819- break;
1820- }
1821- }
1822- }
1823- println!("shutting down");
1824- }