Index: Cargo.lock ================================================================== --- Cargo.lock +++ Cargo.lock @@ -257,13 +257,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "cc" -version = "1.2.51" +version = "1.2.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" +checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3" dependencies = [ "find-msvc-tools", "jobserver", "libc", "shlex", @@ -346,10 +346,33 @@ [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "cssparser" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn", +] [[package]] name = "darling" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -413,17 +436,38 @@ dependencies = [ "proc-macro2", "quote", "syn", ] + +[[package]] +name = "dtoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] [[package]] name = "dunce" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +[[package]] +name = "ego-tree" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2972feb8dffe7bc8c5463b1dacda1b0dfbed3710e50f977d965429692d74cd8" + [[package]] name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" @@ -474,13 +518,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "find-msvc-tools" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" +checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41" [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -498,10 +542,20 @@ [[package]] name = "fs_extra" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] [[package]] name = "futures-channel" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -572,16 +626,25 @@ "memchr", "pin-project-lite", "pin-utils", "slab", ] + +[[package]] +name = "getopts" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" +dependencies = [ + "unicode-width", +] [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", "wasi", @@ -627,10 +690,20 @@ dependencies = [ "cfg-if", "libc", "windows-link", ] + +[[package]] +name = "html5ever" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6452c4751a24e1b99c3260d505eaeee76a050573e61f30ac2c924ddc7236f01e" +dependencies = [ + "log", + "markup5ever", +] [[package]] name = "http" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -914,13 +987,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.179" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "linux-raw-sys" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -929,10 +1002,19 @@ [[package]] name = "litemap" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] [[package]] name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -942,10 +1024,16 @@ name = "lru-slab" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + [[package]] name = "mail-parser" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf4390741c4e6fa330bdeccdfb580815dbb462952de91838b723357985119a3" @@ -980,10 +1068,21 @@ "mailin", "rustls", "rustls-pemfile", "scoped_threadpool", ] + +[[package]] +name = "markup5ever" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c3294c4d74d0742910f8c7b466f44dda9eb2d5742c1e430138df290a1e8451c" +dependencies = [ + "log", + "tendril", + "web_atoms", +] [[package]] name = "memchr" version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1020,10 +1119,16 @@ "libc", "wasi", "windows-sys 0.61.2", ] +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" @@ -1053,10 +1158,33 @@ [[package]] name = "parking" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] [[package]] name = "pathdiff" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1065,10 +1193,63 @@ [[package]] name = "percent-encoding" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros", + "phf_shared", + "serde", +] + +[[package]] +name = "phf_codegen" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] [[package]] name = "pin-project-lite" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1121,10 +1302,16 @@ checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ "zerocopy", ] +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "proc-macro2" version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" @@ -1229,10 +1416,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom 0.3.4", ] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] [[package]] name = "regex" version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1308,11 +1504,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", ] @@ -1456,10 +1652,31 @@ [[package]] name = "scoped_threadpool" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scraper" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93cecd86d6259499c844440546d02f55f3e17bd286e529e48d1f9f67e92315cb" +dependencies = [ + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "precomputed-hash", + "selectors", + "tendril", +] [[package]] name = "security-framework" version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1479,10 +1696,29 @@ checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", ] + +[[package]] +name = "selectors" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feef350c36147532e1b79ea5c1f3791373e61cbd9a6a2615413b3807bb164fb7" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "log", + "new_debug_unreachable", + "phf", + "phf_codegen", + "precomputed-hash", + "rustc-hash", + "servo_arc", + "smallvec", +] [[package]] name = "semver" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1518,13 +1754,13 @@ "syn", ] [[package]] name = "serde_json" -version = "1.0.148" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", "serde", "serde_core", @@ -1559,10 +1795,19 @@ "darling", "proc-macro2", "quote", "syn", ] + +[[package]] +name = "servo_arc" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930" +dependencies = [ + "stable_deref_trait", +] [[package]] name = "shellwords" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1586,10 +1831,16 @@ dependencies = [ "errno", "libc", ] +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" @@ -1633,10 +1884,11 @@ "just-getopt", "lazy_static", "mail-parser", "mailin-embedded", "regex", + "scraper", "smol", "stacked_errors", "tgbot", ] @@ -1665,10 +1917,34 @@ "owo-colors", "smallbox", "thin-vec", "thiserror 2.0.17", ] + +[[package]] +name = "string_cache" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", +] + +[[package]] +name = "string_cache_codegen" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", +] [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1680,13 +1956,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.113" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678faa00651c9eb72dd2020cbdf275d92eccb2400d568e419efdd64838145cb4" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] @@ -1708,10 +1984,21 @@ dependencies = [ "proc-macro2", "quote", "syn", ] + +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] [[package]] name = "ternop" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1847,13 +2134,13 @@ "tokio", ] [[package]] name = "toml" -version = "0.9.10+spec-1.1.0" +version = "0.9.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48" +checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" dependencies = [ "serde_core", "serde_spanned", "toml_datetime", "toml_parser", @@ -1948,20 +2235,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "unicase" -version = "2.8.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-ident" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" @@ -1976,10 +2269,16 @@ "idna", "percent-encoding", "serde", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8_iter" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" @@ -2106,10 +2405,22 @@ checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", ] + +[[package]] +name = "web_atoms" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30e588f10c7bc3465f5fc1ab087fc97877ec1064a7ec89fb685ac4ee998dac4a" +dependencies = [ + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", +] [[package]] name = "webpki-root-certs" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2399,22 +2710,22 @@ "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.31" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.31" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" dependencies = [ "proc-macro2", "quote", "syn", ] @@ -2479,8 +2790,8 @@ "syn", ] [[package]] name = "zmij" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc5a66a20078bf1251bde995aa2fdcc4b800c70b5d92dd2c62abc5c60f679f8" +checksum = "ac93432f5b761b22864c774aac244fa5c0fd877678a4c37ebf6cf42208f9c9ec" Index: Cargo.toml ================================================================== --- Cargo.toml +++ Cargo.toml @@ -1,10 +1,12 @@ [package] name = "smtp2tg" version = "0.5.3" -authors = [ "arcade" ] -edition = "2021" +authors = [ "arcade@b1t.name" ] +edition = "2024" +license = "0BSD" +repository = "http://fs.b1t.name/smtp2tg" [dependencies] async-compat = "0.2.5" config = { version = "0.15", default-features = false, features = [ "toml" ] } hostname = "0.4.1" @@ -11,12 +13,13 @@ just-getopt = "2.0.0" lazy_static = "1.5.0" mail-parser = { version = "0.11", features = ["serde"] } mailin-embedded = "^0" regex = "1.11.1" +scraper = "0.25.0" smol = "2.0.2" stacked_errors = "0.7.1" tgbot = "0.41" [profile.release] lto = true codegen-units = 1 Index: LICENSE.0BSD ================================================================== --- LICENSE.0BSD +++ LICENSE.0BSD @@ -1,6 +1,6 @@ -Copyright (C) 2024 by Volodymyr Kostyrko +Copyright (C) 2024-2026 by Volodymyr Kostyrko Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH Index: src/mail.rs ================================================================== --- src/mail.rs +++ src/mail.rs @@ -1,14 +1,12 @@ use crate::{ Cursor, - telegram::{ - encode, - TelegramTransport, - }, + telegram::TelegramTransport, utils::{ Attachment, RE_DOMAIN, + validate, }, }; use std::{ borrow::Cow, @@ -143,29 +141,34 @@ if rcpt.is_empty() { self.tg.debug("No recipient or envelope address.").await?; rcpt.insert(&self.tg.default); }; - // prepating message header - let mut reply: Vec = vec![]; + // preparing message header + let mut reply: Vec = vec!["
".into()]; if self.fields.contains("subject") { if let Some(subject) = mail.subject() { - reply.push(format!("__*Subject:*__ `{}`", encode(subject))); + reply.push(format!("Subject:{}", validate(subject).stack()?)); } else if let Some(thread) = mail.thread_name() { - reply.push(format!("__*Thread:*__ `{}`", encode(thread))); + reply.push(format!("Thread:{}", validate(thread).stack()?)); } } // do we need to replace spaces here? if self.fields.contains("from") { - reply.push(format!("__*From:*__ `{}`", encode(&headers.from))); - } - if self.fields.contains("date") { - if let Some(date) = mail.date() { - reply.push(format!("__*Date:*__ `{date}`")); - } - } - let header_size = reply.join(" ").len() + 1; + reply.push(format!("From:{}", validate(&headers.from).stack()?)); + } + if self.fields.contains("date") + && let Some(date) = mail.date() + { + reply.push(format!("Date:{date}")); + } + reply.push("
".into());
+			//let header_size = reply.join(" ").len();
+			let mut header_size = 0;
+			for i in reply.iter() {
+				header_size += i.len() + 1;
+			}
 
 			let html_parts = mail.html_body_count();
 			let text_parts = mail.text_body_count();
 			let attachments = mail.attachment_count();
 			if html_parts != text_parts {
@@ -187,18 +190,21 @@
 			};
 			*/
 			if body.is_empty() && text_parts > 0 {
 				let text = mail.body_text(0)
 					.context("Failed to extract text from message")?;
-				if text.len() < 4096 - header_size {
+				// 7:
+				// - (mail text)
+				// - 1 trailing newline
+				// - 6: 
+ if text.len() < 4096 - ( header_size + 7 ) { body = text; text_num = 1; } }; - reply.push("```".into()); reply.extend(body.lines().map(|x| x.into())); - reply.push("```".into()); + reply.push("".into()); // and let's collect all other attachment parts let mut files_to_send = vec![]; /* * let's just skip html parts for now, they just duplicate text? Index: src/main.rs ================================================================== --- src/main.rs +++ src/main.rs @@ -4,13 +4,10 @@ mod mail; mod telegram; mod utils; -#[cfg(test)] -mod tests; - use crate::mail::MailServer; use async_compat::Compat; use just_getopt::{ OptFlags, @@ -38,10 +35,11 @@ })); Ok(()) } +/// Actual main function running async with Error propagation support async fn async_main () -> Result<()> { let specs = OptSpecs::new() .option("help", "h", OptValue::None) .option("help", "help", OptValue::None) .option("config", "c", OptValue::Required) Index: src/telegram.rs ================================================================== --- src/telegram.rs +++ src/telegram.rs @@ -1,12 +1,8 @@ -use crate::utils::{ - Attachment, - RE_SPECIAL, -}; +use crate::utils::Attachment; use std::{ - borrow::Cow, collections::HashMap, fmt::Debug, }; use stacked_errors::{ @@ -21,36 +17,32 @@ InputFileReader, InputMediaDocument, MediaGroup, MediaGroupItem, Message, - ParseMode::MarkdownV2, + ParseMode::Html, SendMediaGroup, SendMessage, SendDocument, }, }; -/// Encodes special HTML entities to prevent them interfering with Telegram HTML -pub fn encode (text: &str) -> Cow<'_, str> { - RE_SPECIAL.replace_all(text, "\\$1") -} - #[derive(Debug)] pub struct TelegramTransport { tg: Client, recipients: HashMap, pub default: ChatPeerId, } impl TelegramTransport { - + /// Creates new TelegramTransport object. pub fn new (api_key: String, recipients: HashMap, settings: &config::Config) -> Result { let default = settings.get_int("default") .context("[smtp2tg.toml] missing \"default\" recipient.\n")?; let api_gateway = settings.get_string("api_gateway") .context("[smtp2tg.toml] missing \"api_gateway\" destination.\n")?; + let tg = Client::new(api_key) .context("Failed to create API.\n")? .with_host(api_gateway); let recipients = recipients.into_iter() .map(|(a, b)| (a, ChatPeerId::from(b))).collect(); @@ -63,11 +55,11 @@ }) } /// Send message to default user, used for debug/log/info purposes pub async fn debug (&self, msg: &str) -> Result { - self.send(&self.default, encode(msg)).await + self.send(&self.default, format!("
{msg}
")).await } /// Get recipient by address pub fn get (&self, name: &str) -> Result<&ChatPeerId> { self.recipients.get(name) @@ -77,11 +69,11 @@ /// Send message to specified user pub async fn send (&self, to: &ChatPeerId, msg: S) -> Result where S: Into + Debug{ self.tg.execute( SendMessage::new(*to, msg) - .with_parse_mode(MarkdownV2) + .with_parse_mode(Html) ).await.stack() } /// Send media to specified user pub async fn sendgroup (&self, to: &ChatPeerId, media: Vec, msg: &str) -> Result<()> { @@ -90,11 +82,11 @@ let mut pos = media.len(); for file in media { let mut caption = InputMediaDocument::default(); if pos == 1 { caption = caption.with_caption(msg) - .with_caption_parse_mode(MarkdownV2); + .with_caption_parse_mode(Html); } pos -= 1; attach.push( MediaGroupItem::for_document( InputFile::from( @@ -111,11 +103,11 @@ SendDocument::new( *to, InputFileReader::from(media[0].data.clone()) .with_file_name(media[0].name.clone()) ).with_caption(msg) - .with_caption_parse_mode(MarkdownV2) + .with_caption_parse_mode(Html) ).await.stack()?; } Ok(()) } } DELETED src/tests.rs Index: src/tests.rs ================================================================== --- src/tests.rs +++ /dev/null @@ -1,7 +0,0 @@ -use crate::telegram::encode; - -#[test] -fn check_regex () { - let res = encode("-_*[]()~`>#+|{}.!"); - assert_eq!(res, "\\-\\_\\*\\[\\]\\(\\)\\~\\`\\>\\#\\+\\|\\{\\}\\.\\!"); -} Index: src/utils.rs ================================================================== --- src/utils.rs +++ src/utils.rs @@ -1,9 +1,14 @@ use crate::Cursor; use lazy_static::lazy_static; use regex::Regex; +use scraper::Html; +use stacked_errors::{ + bail, + Result, +}; lazy_static! { pub static ref RE_SPECIAL: Regex = Regex::new(r"([\-_*\[\]()~`>#+|{}\.!])").unwrap(); pub static ref RE_DOMAIN: Regex = Regex::new(r"^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$").unwrap(); } @@ -12,5 +17,15 @@ #[derive(Debug)] pub struct Attachment { pub data: Cursor>, pub name: String, } + +/// Pass any text here to be validated as HTML, breaks on validation errors +pub fn validate (text: &str) -> Result<&str> { + let fragment = Html::parse_fragment(text); + if !fragment.errors.is_empty() { + bail!(fragment.errors.join("\n")); + } else { + Ok(text) + } +}