bump to v1.6.2

This commit is contained in:
rustmailer
2026-07-08 23:55:05 +08:00
parent 166ac21549
commit 7dee5a7874
4 changed files with 380 additions and 148 deletions
Generated
+223 -104
View File
@@ -225,7 +225,7 @@ dependencies = [
"async-channel 2.5.0", "async-channel 2.5.0",
"async-compression", "async-compression",
"base64 0.22.1", "base64 0.22.1",
"bytes 1.11.1", "bytes 1.12.0",
"chrono", "chrono",
"futures", "futures",
"imap-proto", "imap-proto",
@@ -299,7 +299,7 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]] [[package]]
name = "bichon-admin" name = "bichon-admin"
version = "1.6.1" version = "1.6.2"
dependencies = [ dependencies = [
"bichon-core", "bichon-core",
"bichon-memdb", "bichon-memdb",
@@ -323,7 +323,7 @@ dependencies = [
"crc32fast", "crc32fast",
"criterion", "criterion",
"lz4_flex", "lz4_flex",
"rand 0.10.1", "rand 0.10.2",
"serde", "serde",
"serde_json", "serde_json",
"tempfile", "tempfile",
@@ -334,7 +334,7 @@ dependencies = [
[[package]] [[package]]
name = "bichon-cli" name = "bichon-cli"
version = "1.6.1" version = "1.6.2"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bichon-core", "bichon-core",
@@ -356,13 +356,13 @@ dependencies = [
[[package]] [[package]]
name = "bichon-core" name = "bichon-core"
version = "1.6.1" version = "1.6.2"
dependencies = [ dependencies = [
"async-imap", "async-imap",
"base64 0.22.1", "base64 0.22.1",
"bichon-memdb", "bichon-memdb",
"blake3", "blake3",
"bytes 1.11.1", "bytes 1.12.0",
"chrono", "chrono",
"clap", "clap",
"codepage-strings", "codepage-strings",
@@ -389,8 +389,8 @@ dependencies = [
"oauth2", "oauth2",
"outlook-pst", "outlook-pst",
"poem-openapi", "poem-openapi",
"quick-xml 0.40.0", "quick-xml 0.41.0",
"rand 0.10.1", "rand 0.10.2",
"regex", "regex",
"reqwest", "reqwest",
"ring", "ring",
@@ -432,7 +432,7 @@ dependencies = [
[[package]] [[package]]
name = "bichon-server" name = "bichon-server"
version = "1.6.1" version = "1.6.2"
dependencies = [ dependencies = [
"bichon-core", "bichon-core",
"bichon-smtp", "bichon-smtp",
@@ -457,7 +457,7 @@ dependencies = [
[[package]] [[package]]
name = "bichon-smtp" name = "bichon-smtp"
version = "1.6.1" version = "1.6.2"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bichon-core", "bichon-core",
@@ -577,6 +577,16 @@ dependencies = [
"alloc-stdlib", "alloc-stdlib",
] ]
[[package]]
name = "bstr"
version = "1.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cee35f73844aa3014bb606320a6c1f010249dbdf43342fe54b5a4f6a8ed4b79"
dependencies = [
"memchr",
"serde_core",
]
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.20.2" version = "3.20.2"
@@ -609,9 +619,9 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.11.1" version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593"
[[package]] [[package]]
name = "byteview" name = "byteview"
@@ -819,7 +829,7 @@ version = "4.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
dependencies = [ dependencies = [
"bytes 1.11.1", "bytes 1.12.0",
"memchr", "memchr",
] ]
@@ -870,9 +880,9 @@ dependencies = [
[[package]] [[package]]
name = "console" name = "console"
version = "0.16.3" version = "0.16.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c"
dependencies = [ dependencies = [
"encode_unicode", "encode_unicode",
"libc", "libc",
@@ -895,6 +905,16 @@ dependencies = [
"unicode-segmentation", "unicode-segmentation",
] ]
[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.10.1" version = "0.10.1"
@@ -979,13 +999,14 @@ checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[package]] [[package]]
name = "cron" name = "cron"
version = "0.15.0" version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5877d3fbf742507b66bc2a1945106bd30dd8504019d596901ddd012a4dd01740" checksum = "a5dcd6f69605c2956916ce24e8af637b754964c9a83f4662d3a2361654cdba09"
dependencies = [ dependencies = [
"chrono", "chrono",
"once_cell", "once_cell",
"winnow 0.6.26", "phf 0.11.3",
"winnow 0.7.15",
] ]
[[package]] [[package]]
@@ -1290,18 +1311,6 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "enum-as-inner"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]] [[package]]
name = "enum_dispatch" name = "enum_dispatch"
version = "0.3.13" version = "0.3.13"
@@ -1397,9 +1406,9 @@ checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]] [[package]]
name = "fjall" name = "fjall"
version = "3.1.5" version = "3.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "038acd422d607e0eca09e093f299f9eccf9bd097554343d93746afff81a45113" checksum = "9fcdc69609906151dff9b534e30eaf8515082055d36f628e382bd0b5d6a1d362"
dependencies = [ dependencies = [
"byteorder-lite", "byteorder-lite",
"byteview", "byteview",
@@ -1649,11 +1658,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"js-sys",
"libc", "libc",
"r-efi 6.0.0", "r-efi 6.0.0",
"rand_core 0.10.1", "rand_core 0.10.1",
"wasip2", "wasip2",
"wasip3", "wasip3",
"wasm-bindgen",
] ]
[[package]] [[package]]
@@ -1692,7 +1703,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54"
dependencies = [ dependencies = [
"atomic-waker", "atomic-waker",
"bytes 1.11.1", "bytes 1.12.0",
"fnv", "fnv",
"futures-core", "futures-core",
"futures-sink", "futures-sink",
@@ -1771,7 +1782,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bytes 1.11.1", "bytes 1.12.0",
"headers-core", "headers-core",
"http", "http",
"httpdate", "httpdate",
@@ -1807,28 +1818,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]] [[package]]
name = "hickory-proto" name = "hickory-net"
version = "0.26.0-alpha.1" version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a62d7684f766b0f96344be88c023f9b6650039aea09d526b4974cce302eb61b1" checksum = "e2295ed2f9c31e471e1428a8f88a3f0e1f4b27c15049592138d1eebe9c35b183"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"aws-lc-rs", "aws-lc-rs",
"bitflags", "bitflags",
"bytes 1.11.1", "bytes 1.12.0",
"cfg-if", "cfg-if",
"data-encoding", "data-encoding",
"enum-as-inner",
"futures-channel", "futures-channel",
"futures-io", "futures-io",
"futures-util", "futures-util",
"hickory-proto",
"idna", "idna",
"ipnet", "ipnet",
"once_cell", "jni",
"rand 0.9.2", "lru-cache",
"ring", "parking_lot",
"rand 0.10.2",
"rustls", "rustls",
"rustls-pki-types", "rustls-pki-types",
"rustls-platform-verifier",
"thiserror 2.0.18", "thiserror 2.0.18",
"time", "time",
"tinyvec", "tinyvec",
@@ -1839,22 +1852,51 @@ dependencies = [
] ]
[[package]] [[package]]
name = "hickory-resolver" name = "hickory-proto"
version = "0.26.0-alpha.1" version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbab5e26a7f82341145ba1fbd1f1858d0490624fcc46270db2d3c4a101f763f4" checksum = "0bab31817bfb44672a252e97fe81cd0c18d1b2cf892108922f6818820df8c643"
dependencies = [
"aws-lc-rs",
"bitflags",
"data-encoding",
"idna",
"ipnet",
"jni",
"once_cell",
"prefix-trie",
"rand 0.10.2",
"ring",
"rustls-pki-types",
"thiserror 2.0.18",
"time",
"tinyvec",
"tracing",
"url",
]
[[package]]
name = "hickory-resolver"
version = "0.26.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d58d28879ceecde6607729660c2667a081ccdc082e082675042793960f178c"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"futures-util", "futures-util",
"hickory-net",
"hickory-proto", "hickory-proto",
"ipconfig", "ipconfig",
"ipnet",
"jni",
"moka", "moka",
"ndk-context",
"once_cell", "once_cell",
"parking_lot", "parking_lot",
"rand 0.9.2", "rand 0.10.2",
"resolv-conf", "resolv-conf",
"rustls", "rustls",
"smallvec", "smallvec",
"system-configuration",
"thiserror 2.0.18", "thiserror 2.0.18",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls",
@@ -1906,7 +1948,7 @@ version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425"
dependencies = [ dependencies = [
"bytes 1.11.1", "bytes 1.12.0",
"itoa", "itoa",
] ]
@@ -1916,7 +1958,7 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [ dependencies = [
"bytes 1.11.1", "bytes 1.12.0",
"http", "http",
] ]
@@ -1926,7 +1968,7 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
dependencies = [ dependencies = [
"bytes 1.11.1", "bytes 1.12.0",
"futures-core", "futures-core",
"http", "http",
"http-body", "http-body",
@@ -1952,7 +1994,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca"
dependencies = [ dependencies = [
"atomic-waker", "atomic-waker",
"bytes 1.11.1", "bytes 1.12.0",
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"h2", "h2",
@@ -1990,7 +2032,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bytes 1.11.1", "bytes 1.12.0",
"futures-channel", "futures-channel",
"futures-util", "futures-util",
"http", "http",
@@ -2168,9 +2210,9 @@ dependencies = [
[[package]] [[package]]
name = "indicatif" name = "indicatif"
version = "0.18.4" version = "0.18.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c"
dependencies = [ dependencies = [
"console", "console",
"portable-atomic", "portable-atomic",
@@ -2215,6 +2257,9 @@ name = "ipnet"
version = "2.12.0" version = "2.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "iri-string" name = "iri-string"
@@ -2402,6 +2447,12 @@ version = "0.2.185"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.12.1" version = "0.12.1"
@@ -2447,6 +2498,15 @@ dependencies = [
"hashbrown 0.17.0", "hashbrown 0.17.0",
] ]
[[package]]
name = "lru-cache"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
dependencies = [
"linked-hash-map",
]
[[package]] [[package]]
name = "lru-slab" name = "lru-slab"
version = "0.1.2" version = "0.1.2"
@@ -2455,12 +2515,12 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
[[package]] [[package]]
name = "lsm-tree" name = "lsm-tree"
version = "3.1.5" version = "3.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ef86c3c797c10eefcc73407c43ae48c19d4df686131a8334b2895a513e91df4" checksum = "39ca67401338b98d58447387dd5230552d2241bc388206e491d137b18dfea9d6"
dependencies = [ dependencies = [
"byteorder-lite", "byteorder-lite",
"bytes 1.11.1", "bytes 1.12.0",
"byteview", "byteview",
"crossbeam-skiplist", "crossbeam-skiplist",
"enum_dispatch", "enum_dispatch",
@@ -2487,20 +2547,23 @@ dependencies = [
[[package]] [[package]]
name = "mail-auth" name = "mail-auth"
version = "0.8.0" version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f026538d37471da028cd5c6a907777c3de2d84e2c71b2b47ae301a10977c5e6" checksum = "a88908ddf3a07fa2e76873f84d28476d3c802173fee0a44f6c5e5472523e6986"
dependencies = [ dependencies = [
"aws-lc-rs", "aws-lc-rs",
"flate2", "flate2",
"getrandom 0.2.17",
"getrandom 0.4.2",
"hashify", "hashify",
"hickory-resolver", "hickory-resolver",
"mail-builder", "mail-builder",
"mail-parser", "mail-parser",
"quick-xml 0.39.2", "quick-xml 0.41.0",
"rustls-pki-types", "rustls-pki-types",
"serde", "serde",
"serde_json", "serde_json",
"similar",
"zip", "zip",
] ]
@@ -2526,9 +2589,9 @@ dependencies = [
[[package]] [[package]]
name = "mail-send" name = "mail-send"
version = "0.6.0" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d06f18f6ad15354b83645a05466570ced7bf770a17b138742e705d54407d83ba" checksum = "dc851b8321041a68cc3b017135b6b8d2789a8b6e455aaebe60594bd6a39b2268"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"gethostname", "gethostname",
@@ -2660,7 +2723,7 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b"
dependencies = [ dependencies = [
"bytes 1.11.1", "bytes 1.12.0",
"encoding_rs", "encoding_rs",
"futures-util", "futures-util",
"http", "http",
@@ -2754,6 +2817,12 @@ dependencies = [
"syn 2.0.117", "syn 2.0.117",
] ]
[[package]]
name = "ndk-context"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
[[package]] [[package]]
name = "new_debug_unreachable" name = "new_debug_unreachable"
version = "1.0.6" version = "1.0.6"
@@ -3115,6 +3184,7 @@ version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
dependencies = [ dependencies = [
"phf_macros",
"phf_shared 0.11.3", "phf_shared 0.11.3",
] ]
@@ -3134,10 +3204,20 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1"
dependencies = [ dependencies = [
"phf_generator", "phf_generator 0.13.1",
"phf_shared 0.13.1", "phf_shared 0.13.1",
] ]
[[package]]
name = "phf_generator"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
dependencies = [
"phf_shared 0.11.3",
"rand 0.8.6",
]
[[package]] [[package]]
name = "phf_generator" name = "phf_generator"
version = "0.13.1" version = "0.13.1"
@@ -3148,6 +3228,19 @@ dependencies = [
"phf_shared 0.13.1", "phf_shared 0.13.1",
] ]
[[package]]
name = "phf_macros"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
dependencies = [
"phf_generator 0.11.3",
"phf_shared 0.11.3",
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]] [[package]]
name = "phf_shared" name = "phf_shared"
version = "0.11.3" version = "0.11.3"
@@ -3259,7 +3352,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f977080932c87287147dca052951c3e2696f8759863f6b4e4c0c9ffe7a4cc8b" checksum = "9f977080932c87287147dca052951c3e2696f8759863f6b4e4c0c9ffe7a4cc8b"
dependencies = [ dependencies = [
"async-compression", "async-compression",
"bytes 1.11.1", "bytes 1.12.0",
"futures-util", "futures-util",
"headers", "headers",
"hex", "hex",
@@ -3316,7 +3409,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ccbcc395bf4dd03df1da32da351b6b6732e4074ce27ddec315650e52a2be44c" checksum = "1ccbcc395bf4dd03df1da32da351b6b6732e4074ce27ddec315650e52a2be44c"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bytes 1.11.1", "bytes 1.12.0",
"derive_more", "derive_more",
"email_address", "email_address",
"futures-util", "futures-util",
@@ -3390,6 +3483,17 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "prefix-trie"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cf6e3177f0684016a5c209b00882e15f8bdd3f3bb48f0491df10cd102d0c6e7"
dependencies = [
"either",
"ipnet",
"num-traits",
]
[[package]] [[package]]
name = "prettyplease" name = "prettyplease"
version = "0.2.37" version = "0.2.37"
@@ -3456,18 +3560,9 @@ dependencies = [
[[package]] [[package]]
name = "quick-xml" name = "quick-xml"
version = "0.39.2" version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d" checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1"
dependencies = [
"memchr",
]
[[package]]
name = "quick-xml"
version = "0.40.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7315c86b26aaef0321fba33c9dcc160da659c6a9d278f0f6a5656d6561c03b"
dependencies = [ dependencies = [
"memchr", "memchr",
"serde", "serde",
@@ -3489,7 +3584,7 @@ version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20"
dependencies = [ dependencies = [
"bytes 1.11.1", "bytes 1.12.0",
"cfg_aliases", "cfg_aliases",
"pin-project-lite", "pin-project-lite",
"quinn-proto", "quinn-proto",
@@ -3509,7 +3604,7 @@ version = "0.11.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098"
dependencies = [ dependencies = [
"bytes 1.11.1", "bytes 1.12.0",
"getrandom 0.3.4", "getrandom 0.3.4",
"lru-slab", "lru-slab",
"rand 0.9.2", "rand 0.9.2",
@@ -3588,9 +3683,9 @@ dependencies = [
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.10.1" version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
dependencies = [ dependencies = [
"chacha20", "chacha20",
"getrandom 0.4.2", "getrandom 0.4.2",
@@ -3747,7 +3842,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bytes 1.11.1", "bytes 1.12.0",
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-util", "futures-util",
@@ -3931,9 +4026,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls-pki-types" name = "rustls-pki-types"
version = "1.14.1" version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" checksum = "764899a24af3980067ee14bc143654f297b22eaebfe3c7b6b211920a5a59b046"
dependencies = [ dependencies = [
"web-time", "web-time",
"zeroize", "zeroize",
@@ -3945,7 +4040,7 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0"
dependencies = [ dependencies = [
"core-foundation", "core-foundation 0.10.1",
"core-foundation-sys", "core-foundation-sys",
"jni", "jni",
"log", "log",
@@ -4021,7 +4116,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"core-foundation", "core-foundation 0.10.1",
"core-foundation-sys", "core-foundation-sys",
"libc", "libc",
"security-framework-sys", "security-framework-sys",
@@ -4227,6 +4322,15 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]]
name = "similar"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6505efef05804732ed8a3f2d4f279429eb485bd69d5b0cc6b19cc02005cda16"
dependencies = [
"bstr",
]
[[package]] [[package]]
name = "siphasher" name = "siphasher"
version = "1.0.2" version = "1.0.2"
@@ -4372,7 +4476,7 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69"
dependencies = [ dependencies = [
"phf_generator", "phf_generator 0.13.1",
"phf_shared 0.13.1", "phf_shared 0.13.1",
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -4453,6 +4557,27 @@ dependencies = [
"windows", "windows",
] ]
[[package]]
name = "system-configuration"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b"
dependencies = [
"bitflags",
"core-foundation 0.9.4",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]] [[package]]
name = "tagptr" name = "tagptr"
version = "0.2.0" version = "0.2.0"
@@ -4685,9 +4810,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.51" version = "0.3.53"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85c17d80feb7334b40c484e45ed1a5273dfd8bfda537c3be2e74a06a6686f327" checksum = "18dfaaeddcb932337b5e7866ee7d0ce9b76d2fd092997146f187ec09b4558a50"
dependencies = [ dependencies = [
"deranged", "deranged",
"libc", "libc",
@@ -4707,9 +4832,9 @@ checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
[[package]] [[package]]
name = "time-macros" name = "time-macros"
version = "0.2.30" version = "0.2.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcef1a61bdb119096e153208ec5cbec23944ce8bca13be5c7f60c634f7403935" checksum = "c431b87111666e491a90baa837f914fb45cd5dc3c268591b0220ff5057f2085f"
dependencies = [ dependencies = [
"num-conv", "num-conv",
"time-core", "time-core",
@@ -4717,9 +4842,9 @@ dependencies = [
[[package]] [[package]]
name = "timeago" name = "timeago"
version = "0.6.0" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e86660b0935ca5912eb155f5b3794e2f8f1a09d8c00c9efd5c1075ca26403638" checksum = "46c29b13d230e9cd58513d38701a661fc06e1215398937532a2d938ecca6f219"
dependencies = [ dependencies = [
"chrono", "chrono",
"isolang", "isolang",
@@ -4766,7 +4891,7 @@ version = "1.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
dependencies = [ dependencies = [
"bytes 1.11.1", "bytes 1.12.0",
"libc", "libc",
"mio", "mio",
"parking_lot", "parking_lot",
@@ -4837,7 +4962,7 @@ version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098"
dependencies = [ dependencies = [
"bytes 1.11.1", "bytes 1.12.0",
"futures-core", "futures-core",
"futures-io", "futures-io",
"futures-sink", "futures-sink",
@@ -4927,7 +5052,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"bytes 1.11.1", "bytes 1.12.0",
"futures-util", "futures-util",
"http", "http",
"http-body", "http-body",
@@ -5774,20 +5899,14 @@ version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
name = "winnow"
version = "0.6.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e90edd2ac1aa278a5c4599b1d89cf03074b610800f866d4026dc199d7929a28"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.7.15" version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "winnow" name = "winnow"
+11 -11
View File
@@ -13,7 +13,7 @@ members = [
resolver = "2" resolver = "2"
[workspace.package] [workspace.package]
version = "1.6.1" version = "1.6.2"
edition = "2021" edition = "2021"
[workspace.dependencies] [workspace.dependencies]
@@ -51,46 +51,46 @@ tokio-rustls = { version = "0.26.4", default-features = false, features = [
"ring", "ring",
"tls12", "tls12",
] } ] }
timeago = "0.6.0" timeago = "0.6.1"
oauth2 = { version = "5.0.0", features = ["reqwest-blocking"] } oauth2 = { version = "5.0.0", features = ["reqwest-blocking"] }
url = { version = "2.5.8", features = ["serde"] } url = { version = "2.5.8", features = ["serde"] }
sysinfo = "0.39.4" sysinfo = "0.39.4"
num_cpus = "1.17.0" num_cpus = "1.17.0"
rand = "0.10.1" rand = "0.10.2"
encoding_rs = "0.8.35" encoding_rs = "0.8.35"
webpki-roots = "1.0.8" webpki-roots = "1.0.8"
rustls = { version = "0.23.41", default-features = false, features = ["ring"] } rustls = { version = "0.23.41", default-features = false, features = ["ring"] }
rustls-pki-types = "1.14.1" rustls-pki-types = "1.15.0"
tokio-io-timeout = "1.2.1" tokio-io-timeout = "1.2.1"
semver = "1.0.28" semver = "1.0.28"
governor = "0.10.4" governor = "0.10.4"
lru = "0.18.0" lru = "0.18.0"
mime_guess = "2.0.5" mime_guess = "2.0.5"
hex = "0.4.3" hex = "0.4.3"
time = { version = "0.3.51", features = [ time = { version = "0.3.53", features = [
"formatting", "formatting",
"parsing", "parsing",
"local-offset", "local-offset",
] } ] }
rust-embed = "8.11.0" rust-embed = "8.12.0"
murmur3 = "0.5.2" murmur3 = "0.5.2"
urlencoding = "2.1.3" urlencoding = "2.1.3"
dashmap = "6.2.1" dashmap = "6.2.1"
gethostname = "1.1.0" gethostname = "1.1.0"
itoa = "1.0.18" itoa = "1.0.18"
html2text = "0.17.1" html2text = "0.17.1"
bytes = "1.11.1" bytes = "1.12.0"
dialoguer = "0.12.0" dialoguer = "0.12.0"
console = "0.16.3" console = "0.16.4"
mail-send = "0.6.0" mail-send = "0.6.1"
rcgen = "0.14.8" rcgen = "0.14.8"
rustls-pemfile = "2.2.0" rustls-pemfile = "2.2.0"
blake3 = "1.8.5" blake3 = "1.8.5"
uuid = { version = "1.23.4", features = ["v4", "serde"] } uuid = { version = "1.23.4", features = ["v4", "serde"] }
fjall = { version = "3.1.5", features = ["lz4", "metrics", "bytes_1"] } fjall = { version = "3.1.6", features = ["lz4", "metrics", "bytes_1"] }
tracing-log = "0.2.0" tracing-log = "0.2.0"
tokio-util = "0.7.18" tokio-util = "0.7.18"
indicatif = "0.18.4" indicatif = "0.18.6"
[profile.release] [profile.release]
strip = true strip = true
+3 -3
View File
@@ -69,9 +69,9 @@ tokio-util.workspace = true
whichlang = "0.1.1" whichlang = "0.1.1"
deunicode = "1.6.2" deunicode = "1.6.2"
scopeguard = "1.2.0" scopeguard = "1.2.0"
cron = "0.15" cron = "0.17"
quick-xml = { version = "0.40.0", features = ["serialize"] } quick-xml = { version = "0.41.0", features = ["serialize"] }
hickory-resolver = "0.26.0-alpha.1" hickory-resolver = "0.26.1"
memmap2 = "0.9.10" memmap2 = "0.9.10"
outlook-pst = { git = "https://github.com/rustmailer/outlook-pst-rs.git", branch = "main" } outlook-pst = { git = "https://github.com/rustmailer/outlook-pst-rs.git", branch = "main" }
compressed-rtf = "1.0.1" compressed-rtf = "1.0.1"
+143 -30
View File
@@ -16,9 +16,8 @@
// You should have received a copy of the GNU Affero General Public License // You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
use hickory_resolver::name_server::TokioConnectionProvider; use hickory_resolver::net::runtime::TokioRuntimeProvider;
use hickory_resolver::proto::rr::RData; use hickory_resolver::proto::rr::RData;
use hickory_resolver::proto::rr::RecordType;
use hickory_resolver::TokioResolver; use hickory_resolver::TokioResolver;
use quick_xml::de::from_str; use quick_xml::de::from_str;
use reqwest::Client; use reqwest::Client;
@@ -108,28 +107,29 @@ async fn fetch_xml(client: &Client, url: &str) -> Option<MailConfig> {
} }
async fn lookup_srv(domain: &str) -> Option<MailConfig> { async fn lookup_srv(domain: &str) -> Option<MailConfig> {
let resolver = TokioResolver::builder(TokioConnectionProvider::default()) let resolver = TokioResolver::builder(TokioRuntimeProvider::default())
.ok()? .ok()?
.build(); .build()
.ok()?;
let imap_srv = format!("_imaps._tcp.{}.", domain); let imap_srv = format!("_imaps._tcp.{}.", domain);
let imap_lookup = resolver.lookup(imap_srv, RecordType::SRV).await.ok()?; let imap_lookup = resolver.srv_lookup(imap_srv).await.ok()?;
let imap_record = imap_lookup.iter().next()?; let imap_record = imap_lookup.answers().first()?;
let (imap_host, imap_port) = match imap_record { let (imap_host, imap_port) = match &imap_record.data {
RData::SRV(srv) => { RData::SRV(srv) => {
let host = srv.target().to_string().trim_end_matches('.').to_string(); let host = srv.target.to_string().trim_end_matches('.').to_string();
(host, srv.port()) (host, srv.port)
} }
_ => return None, _ => return None,
}; };
let smtp_srv = format!("_submission._tcp.{}.", domain); let smtp_srv = format!("_submission._tcp.{}.", domain);
let smtp_lookup = resolver.lookup(smtp_srv, RecordType::SRV).await.ok()?; let smtp_lookup = resolver.srv_lookup(smtp_srv).await.ok()?;
let smtp_record = smtp_lookup.iter().next()?; let smtp_record = smtp_lookup.answers().first()?;
let (smtp_host, smtp_port) = match smtp_record { let (smtp_host, smtp_port) = match &smtp_record.data {
RData::SRV(srv) => { RData::SRV(srv) => {
let host = srv.target().to_string().trim_end_matches('.').to_string(); let host = srv.target.to_string().trim_end_matches('.').to_string();
(host, srv.port()) (host, srv.port)
} }
_ => return None, _ => return None,
}; };
@@ -177,13 +177,19 @@ pub async fn fetch(domain: &str) -> BichonResult<MailConfig> {
.map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::InternalError))?; .map_err(|e| raise_error!(format!("{:#?}", e), ErrorCode::InternalError))?;
// ── ISP autoconfig (HTTPS, then HTTP) ────────────────────────── // ── ISP autoconfig (HTTPS, then HTTP) ──────────────────────────
if let Some(config) = if let Some(config) = fetch_xml(
fetch_xml(&client, &format!("https://autoconfig.{domain}/mail/config-v1.1.xml")).await &client,
&format!("https://autoconfig.{domain}/mail/config-v1.1.xml"),
)
.await
{ {
return Ok(config); return Ok(config);
} }
if let Some(config) = if let Some(config) = fetch_xml(
fetch_xml(&client, &format!("http://autoconfig.{domain}/mail/config-v1.1.xml")).await &client,
&format!("http://autoconfig.{domain}/mail/config-v1.1.xml"),
)
.await
{ {
return Ok(config); return Ok(config);
} }
@@ -212,8 +218,11 @@ pub async fn fetch(domain: &str) -> BichonResult<MailConfig> {
} }
// ── Thunderbird central ISPDB ────────────────────────────────── // ── Thunderbird central ISPDB ──────────────────────────────────
if let Some(config) = if let Some(config) = fetch_xml(
fetch_xml(&client, &format!("https://autoconfig.thunderbird.net/v1.1/{domain}")).await &client,
&format!("https://autoconfig.thunderbird.net/v1.1/{domain}"),
)
.await
{ {
return Ok(config); return Ok(config);
} }
@@ -245,20 +254,29 @@ async fn fetch_for_mx(client: &Client, domain: &str) -> Option<MailConfig> {
} }
// Try ISPDB for the MX domain // Try ISPDB for the MX domain
if let Some(config) = if let Some(config) = fetch_xml(
fetch_xml(client, &format!("https://autoconfig.thunderbird.net/v1.1/{mx_domain}")).await client,
&format!("https://autoconfig.thunderbird.net/v1.1/{mx_domain}"),
)
.await
{ {
return Some(config); return Some(config);
} }
// Try ISP autoconfig for the MX domain (HTTPS then HTTP) // Try ISP autoconfig for the MX domain (HTTPS then HTTP)
if let Some(config) = if let Some(config) = fetch_xml(
fetch_xml(client, &format!("https://autoconfig.{mx_domain}/mail/config-v1.1.xml")).await client,
&format!("https://autoconfig.{mx_domain}/mail/config-v1.1.xml"),
)
.await
{ {
return Some(config); return Some(config);
} }
if let Some(config) = if let Some(config) = fetch_xml(
fetch_xml(client, &format!("http://autoconfig.{mx_domain}/mail/config-v1.1.xml")).await client,
&format!("http://autoconfig.{mx_domain}/mail/config-v1.1.xml"),
)
.await
{ {
return Some(config); return Some(config);
} }
@@ -268,12 +286,16 @@ async fn fetch_for_mx(client: &Client, domain: &str) -> Option<MailConfig> {
/// DNS MX lookup → extract the second-level domain of the first MX hostname. /// DNS MX lookup → extract the second-level domain of the first MX hostname.
async fn lookup_mx_domain(domain: &str) -> Option<String> { async fn lookup_mx_domain(domain: &str) -> Option<String> {
let resolver = TokioResolver::builder(TokioConnectionProvider::default()) let resolver = TokioResolver::builder(TokioRuntimeProvider::default())
.ok()? .ok()?
.build(); .build()
.ok()?;
let lookup = resolver.mx_lookup(domain).await.ok()?; let lookup = resolver.mx_lookup(domain).await.ok()?;
let record = lookup.iter().next()?; let record = lookup.answers().first()?;
let mx_host = record.to_string().trim_end_matches('.').to_string(); let mx_host = match &record.data {
RData::MX(mx) => mx.exchange.to_string().trim_end_matches('.').to_string(),
_ => return None,
};
// Extract a reasonable base domain from the MX hostname. // Extract a reasonable base domain from the MX hostname.
// E.g., "aspmx.l.google.com" → "google.com" // E.g., "aspmx.l.google.com" → "google.com"
@@ -336,4 +358,95 @@ mod tests {
} }
} }
} }
#[test]
fn test_parse_autoconfig_xml() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<clientConfig version="1.1">
<emailProvider id="example.com">
<domain>example.com</domain>
<incomingServer type="imap">
<hostname>imap.example.com</hostname>
<port>993</port>
<socketType>SSL</socketType>
<username>%EMAILADDRESS%</username>
<authentication>password-cleartext</authentication>
</incomingServer>
<outgoingServer type="smtp">
<hostname>smtp.example.com</hostname>
<port>587</port>
<socketType>STARTTLS</socketType>
<username>%EMAILADDRESS%</username>
</outgoingServer>
</emailProvider>
</clientConfig>"#;
let config = parse_autoconfig_xml(xml).expect("should parse valid XML");
assert_eq!(config.incoming.len(), 1);
assert_eq!(config.incoming[0].protocol, "imap");
assert_eq!(config.incoming[0].hostname, "imap.example.com");
assert_eq!(config.incoming[0].port, 993);
assert_eq!(config.incoming[0].socket_type, "SSL");
assert_eq!(config.incoming[0].username, "%EMAILADDRESS%");
assert_eq!(config.incoming[0].authentication, "password-cleartext");
assert_eq!(config.outgoing.len(), 1);
assert_eq!(config.outgoing[0].protocol, "smtp");
assert_eq!(config.outgoing[0].hostname, "smtp.example.com");
assert_eq!(config.outgoing[0].port, 587);
assert_eq!(config.outgoing[0].socket_type, "STARTTLS");
assert_eq!(config.outgoing[0].username, "%EMAILADDRESS%");
}
#[test]
fn test_parse_autoconfig_xml_invalid() {
assert!(parse_autoconfig_xml("not xml").is_none());
assert!(parse_autoconfig_xml("<clientConfig></clientConfig>").is_none());
}
#[test]
fn test_extract_base_domain() {
assert_eq!(
extract_base_domain("aspmx.l.google.com"),
Some("google.com".to_string())
);
assert_eq!(
extract_base_domain("company.mail.protection.outlook.com"),
Some("outlook.com".to_string())
);
assert_eq!(
extract_base_domain("mx.example.com"),
Some("example.com".to_string())
);
assert_eq!(
extract_base_domain("example.com"),
Some("example.com".to_string())
);
assert_eq!(extract_base_domain("localhost"), None);
}
#[tokio::test]
async fn test_lookup_srv_gmail() {
// Gmail should have SRV records for IMAPS and SMTP submission
let config = lookup_srv("gmail.com").await;
assert!(config.is_some(), "Gmail should have SRV records");
let config = config.unwrap();
assert_eq!(config.incoming.len(), 1);
assert_eq!(config.incoming[0].protocol, "imap");
assert_eq!(config.incoming[0].socket_type, "SSL");
assert!(!config.incoming[0].hostname.is_empty());
assert!(config.incoming[0].port > 0);
assert_eq!(config.outgoing.len(), 1);
assert_eq!(config.outgoing[0].protocol, "smtp");
assert_eq!(config.outgoing[0].socket_type, "STARTTLS");
assert!(!config.outgoing[0].hostname.is_empty());
assert!(config.outgoing[0].port > 0);
}
#[tokio::test]
async fn test_lookup_srv_nonexistent() {
// A domain without SRV records should return None
let config = lookup_srv("this-domain-definitely-does-not-exist-12345.com").await;
assert!(config.is_none());
}
} }