server: pretty print raw TLSRPT and DMARC data
This commit is contained in:
parent
4d888fbea3
commit
5c42d04598
476
Cargo.lock
generated
476
Cargo.lock
generated
@ -1131,6 +1131,12 @@ version = "0.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
|
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "convert_case"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
@ -1355,6 +1361,23 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cssparser"
|
||||||
|
version = "0.28.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1db8599a9761b371751fbf13e076fa03c6e1a78f8c5288e6ab9467f10a2322c1"
|
||||||
|
dependencies = [
|
||||||
|
"cssparser-macros",
|
||||||
|
"dtoa-short",
|
||||||
|
"itoa 0.4.8",
|
||||||
|
"matches",
|
||||||
|
"phf 0.8.0",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"smallvec 1.15.1",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cssparser"
|
name = "cssparser"
|
||||||
version = "0.34.0"
|
version = "0.34.0"
|
||||||
@ -1364,7 +1387,7 @@ dependencies = [
|
|||||||
"cssparser-macros",
|
"cssparser-macros",
|
||||||
"dtoa-short",
|
"dtoa-short",
|
||||||
"itoa 1.0.15",
|
"itoa 1.0.15",
|
||||||
"phf",
|
"phf 0.11.3",
|
||||||
"smallvec 1.15.1",
|
"smallvec 1.15.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1377,7 +1400,7 @@ dependencies = [
|
|||||||
"cssparser-macros",
|
"cssparser-macros",
|
||||||
"dtoa-short",
|
"dtoa-short",
|
||||||
"itoa 1.0.15",
|
"itoa 1.0.15",
|
||||||
"phf",
|
"phf 0.11.3",
|
||||||
"smallvec 1.15.1",
|
"smallvec 1.15.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1546,8 +1569,10 @@ version = "0.99.20"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f"
|
checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"convert_case",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
"rustc_version 0.4.1",
|
||||||
"syn 2.0.104",
|
"syn 2.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1751,7 +1776,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
|
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3226,7 +3251,7 @@ dependencies = [
|
|||||||
"mailparse",
|
"mailparse",
|
||||||
"maplit",
|
"maplit",
|
||||||
"memmap",
|
"memmap",
|
||||||
"quick-xml",
|
"quick-xml 0.38.1",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"scraper",
|
"scraper",
|
||||||
@ -3240,6 +3265,7 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
"url",
|
"url",
|
||||||
"urlencoding",
|
"urlencoding",
|
||||||
|
"xmlem",
|
||||||
"xtracing",
|
"xtracing",
|
||||||
"zip",
|
"zip",
|
||||||
]
|
]
|
||||||
@ -3528,8 +3554,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18"
|
checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"phf",
|
"phf 0.11.3",
|
||||||
"phf_codegen",
|
"phf_codegen 0.11.3",
|
||||||
"string_cache",
|
"string_cache",
|
||||||
"string_cache_codegen",
|
"string_cache_codegen",
|
||||||
"tendril",
|
"tendril",
|
||||||
@ -3577,6 +3603,12 @@ dependencies = [
|
|||||||
"regex-automata 0.1.10",
|
"regex-automata 0.1.10",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matches"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchit"
|
name = "matchit"
|
||||||
version = "0.7.3"
|
version = "0.7.3"
|
||||||
@ -3849,6 +3881,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nodrop"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "7.1.3"
|
version = "7.1.3"
|
||||||
@ -4302,14 +4340,35 @@ dependencies = [
|
|||||||
"sha2 0.10.9",
|
"sha2 0.10.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
|
||||||
|
dependencies = [
|
||||||
|
"phf_macros 0.8.0",
|
||||||
|
"phf_shared 0.8.0",
|
||||||
|
"proc-macro-hack",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf"
|
name = "phf"
|
||||||
version = "0.11.3"
|
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_macros 0.11.3",
|
||||||
"phf_shared",
|
"phf_shared 0.11.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_codegen"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815"
|
||||||
|
dependencies = [
|
||||||
|
"phf_generator 0.8.0",
|
||||||
|
"phf_shared 0.8.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4318,8 +4377,18 @@ 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 = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
|
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf_generator",
|
"phf_generator 0.11.3",
|
||||||
"phf_shared",
|
"phf_shared 0.11.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_generator"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
|
||||||
|
dependencies = [
|
||||||
|
"phf_shared 0.8.0",
|
||||||
|
"rand 0.7.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4328,30 +4397,53 @@ 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 = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf_shared",
|
"phf_shared 0.11.3",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_macros"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c"
|
||||||
|
dependencies = [
|
||||||
|
"phf_generator 0.8.0",
|
||||||
|
"phf_shared 0.8.0",
|
||||||
|
"proc-macro-hack",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf_macros"
|
name = "phf_macros"
|
||||||
version = "0.11.3"
|
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 = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
|
checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf_generator",
|
"phf_generator 0.11.3",
|
||||||
"phf_shared",
|
"phf_shared 0.11.3",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.104",
|
"syn 2.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_shared"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
|
||||||
|
dependencies = [
|
||||||
|
"siphasher 0.3.11",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf_shared"
|
name = "phf_shared"
|
||||||
version = "0.11.3"
|
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 = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
|
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"siphasher",
|
"siphasher 1.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4524,6 +4616,12 @@ dependencies = [
|
|||||||
"syn 2.0.104",
|
"syn 2.0.104",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-hack"
|
||||||
|
version = "0.5.20+deprecated"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.96"
|
version = "1.0.96"
|
||||||
@ -4565,6 +4663,48 @@ dependencies = [
|
|||||||
"prost",
|
"prost",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "qname"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fac552bc5de28a2d8ebb5d93d157b1eb3d1ca58f88ba2d1e2b931951cb52b29"
|
||||||
|
dependencies = [
|
||||||
|
"qname-impl",
|
||||||
|
"qname-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "qname-impl"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c28cd0334d1ed0cb075cde40d45b9ee648fe79e69a18c3e2891f79c3ec788304"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "qname-macro"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e673fdaa2dcfd19fac443c4a361cc2635b2304592cdc5352ef76bb8dd38333c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"qname-impl",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-xml"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-xml"
|
name = "quick-xml"
|
||||||
version = "0.38.1"
|
version = "0.38.1"
|
||||||
@ -4662,6 +4802,20 @@ dependencies = [
|
|||||||
"scheduled-thread-pool",
|
"scheduled-thread-pool",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.1.16",
|
||||||
|
"libc",
|
||||||
|
"rand_chacha 0.2.2",
|
||||||
|
"rand_core 0.5.1",
|
||||||
|
"rand_hc",
|
||||||
|
"rand_pcg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
@ -4683,6 +4837,16 @@ dependencies = [
|
|||||||
"rand_core 0.9.3",
|
"rand_core 0.9.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core 0.5.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_chacha"
|
name = "rand_chacha"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@ -4703,6 +4867,15 @@ dependencies = [
|
|||||||
"rand_core 0.9.3",
|
"rand_core 0.9.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.1.16",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.6.4"
|
version = "0.6.4"
|
||||||
@ -4731,6 +4904,24 @@ dependencies = [
|
|||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_hc"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.5.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_pcg"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.5.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon"
|
name = "rayon"
|
||||||
version = "1.10.0"
|
version = "1.10.0"
|
||||||
@ -5178,7 +5369,7 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.9.4",
|
"linux-raw-sys 0.9.4",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5371,6 +5562,24 @@ dependencies = [
|
|||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "selectors"
|
||||||
|
version = "0.23.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fdea87c686be721aab36607728047801ee21561bfdbd6bf0da7ace2536d5879f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"cssparser 0.28.1",
|
||||||
|
"derive_more 0.99.20",
|
||||||
|
"fxhash",
|
||||||
|
"log",
|
||||||
|
"phf 0.8.0",
|
||||||
|
"phf_codegen 0.8.0",
|
||||||
|
"precomputed-hash",
|
||||||
|
"servo_arc 0.1.1",
|
||||||
|
"smallvec 1.15.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "selectors"
|
name = "selectors"
|
||||||
version = "0.26.0"
|
version = "0.26.0"
|
||||||
@ -5383,10 +5592,10 @@ dependencies = [
|
|||||||
"fxhash",
|
"fxhash",
|
||||||
"log",
|
"log",
|
||||||
"new_debug_unreachable",
|
"new_debug_unreachable",
|
||||||
"phf",
|
"phf 0.11.3",
|
||||||
"phf_codegen",
|
"phf_codegen 0.11.3",
|
||||||
"precomputed-hash",
|
"precomputed-hash",
|
||||||
"servo_arc",
|
"servo_arc 0.4.1",
|
||||||
"smallvec 1.15.1",
|
"smallvec 1.15.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -5402,10 +5611,10 @@ dependencies = [
|
|||||||
"fxhash",
|
"fxhash",
|
||||||
"log",
|
"log",
|
||||||
"new_debug_unreachable",
|
"new_debug_unreachable",
|
||||||
"phf",
|
"phf 0.11.3",
|
||||||
"phf_codegen",
|
"phf_codegen 0.11.3",
|
||||||
"precomputed-hash",
|
"precomputed-hash",
|
||||||
"servo_arc",
|
"servo_arc 0.4.1",
|
||||||
"smallvec 1.15.1",
|
"smallvec 1.15.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -5528,6 +5737,16 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "servo_arc"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432"
|
||||||
|
dependencies = [
|
||||||
|
"nodrop",
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "servo_arc"
|
name = "servo_arc"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@ -5636,6 +5855,12 @@ version = "0.3.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "siphasher"
|
||||||
|
version = "0.3.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "siphasher"
|
name = "siphasher"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -5944,7 +6169,7 @@ checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"new_debug_unreachable",
|
"new_debug_unreachable",
|
||||||
"parking_lot 0.12.4",
|
"parking_lot 0.12.4",
|
||||||
"phf_shared",
|
"phf_shared 0.11.3",
|
||||||
"precomputed-hash",
|
"precomputed-hash",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@ -5955,8 +6180,8 @@ version = "0.5.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0"
|
checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf_generator",
|
"phf_generator 0.11.3",
|
||||||
"phf_shared",
|
"phf_shared 0.11.3",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
]
|
]
|
||||||
@ -6993,6 +7218,189 @@ version = "0.1.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
|
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-char-property"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"
|
||||||
|
dependencies = [
|
||||||
|
"unic-char-range",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-char-range"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-common"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "625b18f7601e1127504a20ae731dc3c7826d0e86d5f7fe3434f8137669240efd"
|
||||||
|
dependencies = [
|
||||||
|
"unic-ucd-age",
|
||||||
|
"unic-ucd-bidi",
|
||||||
|
"unic-ucd-block",
|
||||||
|
"unic-ucd-case",
|
||||||
|
"unic-ucd-category",
|
||||||
|
"unic-ucd-common",
|
||||||
|
"unic-ucd-hangul",
|
||||||
|
"unic-ucd-ident",
|
||||||
|
"unic-ucd-name",
|
||||||
|
"unic-ucd-name_aliases",
|
||||||
|
"unic-ucd-normal",
|
||||||
|
"unic-ucd-segment",
|
||||||
|
"unic-ucd-version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd-age"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c8cfdfe71af46b871dc6af2c24fcd360e2f3392ee4c5111877f2947f311671c"
|
||||||
|
dependencies = [
|
||||||
|
"unic-char-property",
|
||||||
|
"unic-char-range",
|
||||||
|
"unic-ucd-version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd-bidi"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d1d568b51222484e1f8209ce48caa6b430bf352962b877d592c29ab31fb53d8c"
|
||||||
|
dependencies = [
|
||||||
|
"unic-char-property",
|
||||||
|
"unic-char-range",
|
||||||
|
"unic-ucd-version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd-block"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b2a16f2d7ecd25325a1053ca5a66e7fa1b68911a65c5e97f8d2e1b236b6f1d7"
|
||||||
|
dependencies = [
|
||||||
|
"unic-char-property",
|
||||||
|
"unic-char-range",
|
||||||
|
"unic-ucd-version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd-case"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d98d6246a79bac6cf66beee01422bda7c882e11d837fa4969bfaaba5fdea6d3"
|
||||||
|
dependencies = [
|
||||||
|
"unic-char-property",
|
||||||
|
"unic-char-range",
|
||||||
|
"unic-ucd-version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd-category"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b8d4591f5fcfe1bd4453baaf803c40e1b1e69ff8455c47620440b46efef91c0"
|
||||||
|
dependencies = [
|
||||||
|
"matches",
|
||||||
|
"unic-char-property",
|
||||||
|
"unic-char-range",
|
||||||
|
"unic-ucd-version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd-common"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e9b78b910beafa1aae5c59bf00877c6cece1c5db28a1241ad801e86cecdff4ad"
|
||||||
|
dependencies = [
|
||||||
|
"unic-char-property",
|
||||||
|
"unic-char-range",
|
||||||
|
"unic-ucd-version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd-hangul"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb1dc690e19010e1523edb9713224cba5ef55b54894fe33424439ec9a40c0054"
|
||||||
|
dependencies = [
|
||||||
|
"unic-ucd-version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd-ident"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e230a37c0381caa9219d67cf063aa3a375ffed5bf541a452db16e744bdab6987"
|
||||||
|
dependencies = [
|
||||||
|
"unic-char-property",
|
||||||
|
"unic-char-range",
|
||||||
|
"unic-ucd-version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd-name"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8fc55a45b2531089dc1773bf60c1f104b38e434b774ffc37b9c29a9b0f492e"
|
||||||
|
dependencies = [
|
||||||
|
"unic-char-property",
|
||||||
|
"unic-ucd-hangul",
|
||||||
|
"unic-ucd-version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd-name_aliases"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b7674212643087699ba247a63dd05f1204c7e4880ec9342e545a7cffcc6a46f"
|
||||||
|
dependencies = [
|
||||||
|
"unic-char-property",
|
||||||
|
"unic-ucd-version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd-normal"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "86aed873b8202d22b13859dda5fe7c001d271412c31d411fd9b827e030569410"
|
||||||
|
dependencies = [
|
||||||
|
"unic-char-property",
|
||||||
|
"unic-char-range",
|
||||||
|
"unic-ucd-category",
|
||||||
|
"unic-ucd-hangul",
|
||||||
|
"unic-ucd-version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd-segment"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700"
|
||||||
|
dependencies = [
|
||||||
|
"unic-char-property",
|
||||||
|
"unic-char-range",
|
||||||
|
"unic-ucd-version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unic-ucd-version"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"
|
||||||
|
dependencies = [
|
||||||
|
"unic-common",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicase"
|
name = "unicase"
|
||||||
version = "2.8.1"
|
version = "2.8.1"
|
||||||
@ -7330,8 +7738,8 @@ 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 = "57ffde1dc01240bdf9992e3205668b235e59421fd085e8a317ed98da0178d414"
|
checksum = "57ffde1dc01240bdf9992e3205668b235e59421fd085e8a317ed98da0178d414"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf",
|
"phf 0.11.3",
|
||||||
"phf_codegen",
|
"phf_codegen 0.11.3",
|
||||||
"string_cache",
|
"string_cache",
|
||||||
"string_cache_codegen",
|
"string_cache_codegen",
|
||||||
]
|
]
|
||||||
@ -7731,6 +8139,22 @@ version = "0.8.27"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7"
|
checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xmlem"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15d7eadd176b9e994da5c27acd46001a82256afa9e49b1b56b37e117e63a0aee"
|
||||||
|
dependencies = [
|
||||||
|
"cssparser 0.28.1",
|
||||||
|
"indexmap 1.9.3",
|
||||||
|
"once_cell",
|
||||||
|
"qname",
|
||||||
|
"quick-xml 0.22.0",
|
||||||
|
"selectors 0.23.0",
|
||||||
|
"slotmap",
|
||||||
|
"unic-ucd",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xtracing"
|
name = "xtracing"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
|||||||
@ -54,6 +54,7 @@ urlencoding = "2.1.3"
|
|||||||
#xtracing = { path = "../../xtracing" }
|
#xtracing = { path = "../../xtracing" }
|
||||||
xtracing = { version = "0.3.2", registry = "xinu" }
|
xtracing = { version = "0.3.2", registry = "xinu" }
|
||||||
zip = "4.3.0"
|
zip = "4.3.0"
|
||||||
|
xmlem = "0.1.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
build-info-build = "0.0.41"
|
build-info-build = "0.0.41"
|
||||||
|
|||||||
@ -41,4 +41,6 @@ pub enum ServerError {
|
|||||||
InfaillibleError(#[from] Infallible),
|
InfaillibleError(#[from] Infallible),
|
||||||
#[error("askama error: {0}")]
|
#[error("askama error: {0}")]
|
||||||
AskamaError(#[from] askama::Error),
|
AskamaError(#[from] askama::Error),
|
||||||
|
#[error("xml error: {0}")]
|
||||||
|
XmlError(#[from] quick_xml::Error),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -237,6 +237,22 @@ impl Body {
|
|||||||
content_tree: "".to_string(),
|
content_tree: "".to_string(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_html(&self) -> Option<String> {
|
||||||
|
match self {
|
||||||
|
Body::Html(h) => Some(h.html.clone()),
|
||||||
|
Body::PlainText(p) => Some(format!("<pre>{}</pre>", html_escape::encode_text(&p.text))),
|
||||||
|
Body::UnhandledContentType(u) => Some(format!("<pre>{}</pre>", html_escape::encode_text(&u.text))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_html_content_tree(&self) -> Option<String> {
|
||||||
|
match self {
|
||||||
|
Body::Html(h) => Some(h.content_tree.clone()),
|
||||||
|
Body::PlainText(p) => Some(p.content_tree.clone()),
|
||||||
|
Body::UnhandledContentType(u) => Some(u.content_tree.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, SimpleObject)]
|
#[derive(Debug, SimpleObject)]
|
||||||
|
|||||||
256
server/src/nm.rs
256
server/src/nm.rs
@ -2,6 +2,7 @@ use std::{
|
|||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
fs::File,
|
fs::File,
|
||||||
io::{Cursor, Read},
|
io::{Cursor, Read},
|
||||||
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
@ -13,6 +14,7 @@ use memmap::MmapOptions;
|
|||||||
use quick_xml::de::from_str as xml_from_str;
|
use quick_xml::de::from_str as xml_from_str;
|
||||||
use sqlx::{types::Json, PgPool};
|
use sqlx::{types::Json, PgPool};
|
||||||
use tracing::{error, info, info_span, instrument, warn};
|
use tracing::{error, info, info_span, instrument, warn};
|
||||||
|
use xmlem::{display, Document};
|
||||||
use zip::ZipArchive;
|
use zip::ZipArchive;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -176,7 +178,7 @@ pub async fn thread(
|
|||||||
// display names (that default to the most commonly seen name).
|
// display names (that default to the most commonly seen name).
|
||||||
let mut messages = Vec::new();
|
let mut messages = Vec::new();
|
||||||
for (path, id) in std::iter::zip(nm.files(&thread_id)?, nm.message_ids(&thread_id)?) {
|
for (path, id) in std::iter::zip(nm.files(&thread_id)?, nm.message_ids(&thread_id)?) {
|
||||||
let tags = nm.tags_for_query(&format!("id:{id}"))?;
|
let tags = nm.tags_for_query(&format!("id:{}", id))?;
|
||||||
let file = File::open(&path)?;
|
let file = File::open(&path)?;
|
||||||
let mmap = unsafe { MmapOptions::new().map(&file)? };
|
let mmap = unsafe { MmapOptions::new().map(&file)? };
|
||||||
let m = parse_mail(&mmap)?;
|
let m = parse_mail(&mmap)?;
|
||||||
@ -314,8 +316,105 @@ pub async fn thread(
|
|||||||
.collect();
|
.collect();
|
||||||
// TODO(wathiede): parse message and fill out attachments
|
// TODO(wathiede): parse message and fill out attachments
|
||||||
let attachments = extract_attachments(&m, &id)?;
|
let attachments = extract_attachments(&m, &id)?;
|
||||||
|
|
||||||
|
let mut final_body = body;
|
||||||
|
let mut raw_report_content: Option<String> = None;
|
||||||
|
|
||||||
|
// Append TLS report if available
|
||||||
|
if m.ctype.mimetype.as_str() == MULTIPART_REPORT {
|
||||||
|
if let Ok(Body::Html(_html_body)) = extract_report(&m, &mut part_addr) {
|
||||||
|
// Extract raw JSON for pretty printing
|
||||||
|
if let Some(sp) = m
|
||||||
|
.subparts
|
||||||
|
.iter()
|
||||||
|
.find(|sp| sp.ctype.mimetype.as_str() == "application/tlsrpt+gzip")
|
||||||
|
{
|
||||||
|
if let Ok(gz_bytes) = sp.get_body_raw() {
|
||||||
|
let mut decoder = flate2::read::GzDecoder::new(&gz_bytes[..]);
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
if decoder.read_to_end(&mut buffer).is_ok() {
|
||||||
|
if let Ok(json_str) = String::from_utf8(buffer) {
|
||||||
|
raw_report_content = Some(json_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append DMARC report if available
|
||||||
|
if m.ctype.mimetype.as_str() == APPLICATION_ZIP {
|
||||||
|
if let Ok(Body::Html(_html_body)) = extract_zip(&m) {
|
||||||
|
// Extract raw XML for pretty printing
|
||||||
|
if let Ok(zip_bytes) = m.get_body_raw() {
|
||||||
|
if let Ok(mut archive) = ZipArchive::new(Cursor::new(&zip_bytes)) {
|
||||||
|
for i in 0..archive.len() {
|
||||||
|
if let Ok(mut file) = archive.by_index(i) {
|
||||||
|
let name = file.name().to_lowercase();
|
||||||
|
if name.ends_with(".xml")
|
||||||
|
&& (name.contains("dmarc") || name.starts_with("google.com!"))
|
||||||
|
{
|
||||||
|
let mut xml = String::new();
|
||||||
|
use std::io::Read;
|
||||||
|
if file.read_to_string(&mut xml).is_ok() {
|
||||||
|
raw_report_content = Some(xml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.ctype.mimetype.as_str() == APPLICATION_GZIP {
|
||||||
|
if let Ok(Body::Html(_html_body)) = extract_gzip(&m) {
|
||||||
|
// Extract raw XML for pretty printing
|
||||||
|
if let Ok(gz_bytes) = m.get_body_raw() {
|
||||||
|
let mut decoder = flate2::read::GzDecoder::new(&gz_bytes[..]);
|
||||||
|
let mut xml = String::new();
|
||||||
|
use std::io::Read;
|
||||||
|
if decoder.read_to_string(&mut xml).is_ok() {
|
||||||
|
raw_report_content = Some(xml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(raw_content) = raw_report_content {
|
||||||
|
let pretty_printed_content = if m.ctype.mimetype.as_str() == MULTIPART_REPORT {
|
||||||
|
// Pretty print JSON
|
||||||
|
if let Ok(parsed_json) = serde_json::from_str::<serde_json::Value>(&raw_content) {
|
||||||
|
serde_json::to_string_pretty(&parsed_json).unwrap_or(raw_content)
|
||||||
|
} else {
|
||||||
|
raw_content
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// DMARC reports are XML
|
||||||
|
// Pretty print XML
|
||||||
|
let doc_result = Document::from_str(&raw_content);
|
||||||
|
if let Ok(doc) = doc_result {
|
||||||
|
doc.to_string_pretty_with_config(&display::Config::default_pretty())
|
||||||
|
} else {
|
||||||
|
error!(
|
||||||
|
"Failed to parse XML for pretty printing: {:?}",
|
||||||
|
doc_result.unwrap_err()
|
||||||
|
);
|
||||||
|
raw_content
|
||||||
|
}
|
||||||
|
};
|
||||||
|
final_body = Body::Html(Html {
|
||||||
|
html: format!(
|
||||||
|
"{}\n<pre>{}</pre>",
|
||||||
|
final_body.to_html().unwrap_or_default(),
|
||||||
|
html_escape::encode_text(&pretty_printed_content)
|
||||||
|
),
|
||||||
|
content_tree: final_body.to_html_content_tree().unwrap_or_default(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
messages.push(Message {
|
messages.push(Message {
|
||||||
id: format!("id:{id}"),
|
id: format!("id:{}", id),
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
cc,
|
cc,
|
||||||
@ -323,7 +422,7 @@ pub async fn thread(
|
|||||||
tags,
|
tags,
|
||||||
timestamp,
|
timestamp,
|
||||||
headers,
|
headers,
|
||||||
body,
|
body: final_body,
|
||||||
path,
|
path,
|
||||||
attachments,
|
attachments,
|
||||||
delivered_to,
|
delivered_to,
|
||||||
@ -397,14 +496,14 @@ fn email_addresses(
|
|||||||
pub fn cid_attachment_bytes(nm: &Notmuch, id: &str, cid: &str) -> Result<Attachment, ServerError> {
|
pub fn cid_attachment_bytes(nm: &Notmuch, id: &str, cid: &str) -> Result<Attachment, ServerError> {
|
||||||
let files = nm.files(id)?;
|
let files = nm.files(id)?;
|
||||||
let Some(path) = files.first() else {
|
let Some(path) = files.first() else {
|
||||||
warn!("failed to find files for message {id}");
|
warn!("failed to find files for message {}", id);
|
||||||
return Err(ServerError::PartNotFound);
|
return Err(ServerError::PartNotFound);
|
||||||
};
|
};
|
||||||
let file = File::open(&path)?;
|
let file = File::open(&path)?;
|
||||||
let mmap = unsafe { MmapOptions::new().map(&file)? };
|
let mmap = unsafe { MmapOptions::new().map(&file)? };
|
||||||
let m = parse_mail(&mmap)?;
|
let m = parse_mail(&mmap)?;
|
||||||
if let Some(attachment) = walk_attachments(&m, |sp, _cur_idx| {
|
if let Some(attachment) = walk_attachments(&m, |sp, _cur_idx| {
|
||||||
info!("{cid} {:?}", get_content_id(&sp.headers));
|
info!("{} {:?}", cid, get_content_id(&sp.headers));
|
||||||
if let Some(h_cid) = get_content_id(&sp.headers) {
|
if let Some(h_cid) = get_content_id(&sp.headers) {
|
||||||
let h_cid = &h_cid[1..h_cid.len() - 1];
|
let h_cid = &h_cid[1..h_cid.len() - 1];
|
||||||
if h_cid == cid {
|
if h_cid == cid {
|
||||||
@ -425,7 +524,7 @@ pub fn cid_attachment_bytes(nm: &Notmuch, id: &str, cid: &str) -> Result<Attachm
|
|||||||
pub fn attachment_bytes(nm: &Notmuch, id: &str, idx: &[usize]) -> Result<Attachment, ServerError> {
|
pub fn attachment_bytes(nm: &Notmuch, id: &str, idx: &[usize]) -> Result<Attachment, ServerError> {
|
||||||
let files = nm.files(id)?;
|
let files = nm.files(id)?;
|
||||||
let Some(path) = files.first() else {
|
let Some(path) = files.first() else {
|
||||||
warn!("failed to find files for message {id}");
|
warn!("failed to find files for message {}", id);
|
||||||
return Err(ServerError::PartNotFound);
|
return Err(ServerError::PartNotFound);
|
||||||
};
|
};
|
||||||
let file = File::open(&path)?;
|
let file = File::open(&path)?;
|
||||||
@ -459,7 +558,7 @@ fn extract_body(m: &ParsedMail, part_addr: &mut Vec<String>) -> Result<Body, Ser
|
|||||||
_ => extract_unhandled(m),
|
_ => extract_unhandled(m),
|
||||||
};
|
};
|
||||||
if let Err(err) = ret {
|
if let Err(err) = ret {
|
||||||
error!("Failed to extract body: {err:?}");
|
error!("Failed to extract body: {:?}", err);
|
||||||
return Ok(extract_unhandled(m)?);
|
return Ok(extract_unhandled(m)?);
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
@ -557,14 +656,20 @@ fn extract_report(m: &ParsedMail, _part_addr: &mut Vec<String>) -> Result<Body,
|
|||||||
},
|
},
|
||||||
contact_info: tlsrpt.contact_info.unwrap_or_else(|| "".to_string()),
|
contact_info: tlsrpt.contact_info.unwrap_or_else(|| "".to_string()),
|
||||||
report_id: tlsrpt.report_id,
|
report_id: tlsrpt.report_id,
|
||||||
policies: tlsrpt.policies.into_iter().map(|policy| {
|
policies: tlsrpt
|
||||||
FormattedTlsRptPolicy {
|
.policies
|
||||||
|
.into_iter()
|
||||||
|
.map(|policy| FormattedTlsRptPolicy {
|
||||||
policy: FormattedTlsRptPolicyDetails {
|
policy: FormattedTlsRptPolicyDetails {
|
||||||
policy_type: policy.policy.policy_type,
|
policy_type: policy.policy.policy_type,
|
||||||
policy_string: policy.policy.policy_string,
|
policy_string: policy.policy.policy_string,
|
||||||
policy_domain: policy.policy.policy_domain,
|
policy_domain: policy.policy.policy_domain,
|
||||||
mx_host: policy.policy.mx_host.unwrap_or_else(|| Vec::new()).into_iter().map(|mx| {
|
mx_host: policy
|
||||||
match mx {
|
.policy
|
||||||
|
.mx_host
|
||||||
|
.unwrap_or_else(|| Vec::new())
|
||||||
|
.into_iter()
|
||||||
|
.map(|mx| match mx {
|
||||||
MxHost::String(s) => FormattedTlsRptMxHost {
|
MxHost::String(s) => FormattedTlsRptMxHost {
|
||||||
hostname: s,
|
hostname: s,
|
||||||
failure_count: 0,
|
failure_count: 0,
|
||||||
@ -575,26 +680,42 @@ fn extract_report(m: &ParsedMail, _part_addr: &mut Vec<String>) -> Result<Body,
|
|||||||
failure_count: o.failure_count,
|
failure_count: o.failure_count,
|
||||||
result_type: o.result_type,
|
result_type: o.result_type,
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}).collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
summary: policy.summary,
|
summary: policy.summary,
|
||||||
failure_details: policy.failure_details.unwrap_or_else(|| Vec::new()).into_iter().map(|detail| {
|
failure_details: policy
|
||||||
FormattedTlsRptFailureDetails {
|
.failure_details
|
||||||
|
.unwrap_or_else(|| Vec::new())
|
||||||
|
.into_iter()
|
||||||
|
.map(|detail| FormattedTlsRptFailureDetails {
|
||||||
result_type: detail.result_type,
|
result_type: detail.result_type,
|
||||||
sending_mta_ip: detail.sending_mta_ip.unwrap_or_else(|| "".to_string()),
|
sending_mta_ip: detail
|
||||||
receiving_ip: detail.receiving_ip.unwrap_or_else(|| "".to_string()),
|
.sending_mta_ip
|
||||||
receiving_mx_hostname: detail.receiving_mx_hostname.unwrap_or_else(|| "".to_string()),
|
.unwrap_or_else(|| "".to_string()),
|
||||||
|
receiving_ip: detail
|
||||||
|
.receiving_ip
|
||||||
|
.unwrap_or_else(|| "".to_string()),
|
||||||
|
receiving_mx_hostname: detail
|
||||||
|
.receiving_mx_hostname
|
||||||
|
.unwrap_or_else(|| "".to_string()),
|
||||||
failed_session_count: detail.failed_session_count,
|
failed_session_count: detail.failed_session_count,
|
||||||
additional_info: detail.additional_info.unwrap_or_else(|| "".to_string()),
|
additional_info: detail
|
||||||
failure_reason_code: detail.failure_reason_code.unwrap_or_else(|| "".to_string()),
|
.additional_info
|
||||||
}
|
.unwrap_or_else(|| "".to_string()),
|
||||||
}).collect(),
|
failure_reason_code: detail
|
||||||
}
|
.failure_reason_code
|
||||||
}).collect(),
|
.unwrap_or_else(|| "".to_string()),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
};
|
};
|
||||||
let template = TlsReportTemplate { report: &formatted_tlsrpt };
|
let template = TlsReportTemplate {
|
||||||
template.render().unwrap_or_else(|e| format!("<div class=\"tlsrpt-error\">Failed to render TLS report template: {}</div>", e)) }
|
report: &formatted_tlsrpt,
|
||||||
|
};
|
||||||
|
template.render().unwrap_or_else(|e| format!("<div class=\"tlsrpt-error\">Failed to render TLS report template: {}</div>", e))
|
||||||
|
}
|
||||||
Err(e) => format!(
|
Err(e) => format!(
|
||||||
"<div class=\"tlsrpt-error\">Failed to parse TLS report JSON: {}</div>",
|
"<div class=\"tlsrpt-error\">Failed to parse TLS report JSON: {}</div>",
|
||||||
e
|
e
|
||||||
@ -603,12 +724,10 @@ fn extract_report(m: &ParsedMail, _part_addr: &mut Vec<String>) -> Result<Body,
|
|||||||
} else {
|
} else {
|
||||||
format!("<div class=\"tlsrpt-error\">Failed to convert decompressed data to UTF-8.</div>")
|
format!("<div class=\"tlsrpt-error\">Failed to convert decompressed data to UTF-8.</div>")
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
format!("<div class=\"tlsrpt-error\">Failed to decompressed data.</div>")
|
format!("<div class=\"tlsrpt-error\">Failed to decompressed data.</div>")
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
"".to_string()
|
"".to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -700,7 +819,10 @@ fn extract_mixed(m: &ParsedMail, part_addr: &mut Vec<String>) -> Result<Body, Se
|
|||||||
.collect();
|
.collect();
|
||||||
unhandled_types.sort();
|
unhandled_types.sort();
|
||||||
if !unhandled_types.is_empty() {
|
if !unhandled_types.is_empty() {
|
||||||
warn!("{MULTIPART_MIXED} contains the following unhandled mimetypes {unhandled_types:?}");
|
warn!(
|
||||||
|
"{} contains the following unhandled mimetypes {:?}",
|
||||||
|
MULTIPART_MIXED, unhandled_types
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let mut parts = Vec::new();
|
let mut parts = Vec::new();
|
||||||
for (idx, sp) in m.subparts.iter().enumerate() {
|
for (idx, sp) in m.subparts.iter().enumerate() {
|
||||||
@ -751,8 +873,7 @@ fn unhandled_html(parent_type: &str, child_type: &str) -> Body {
|
|||||||
Unhandled mimetype {} in a {} message
|
Unhandled mimetype {} in a {} message
|
||||||
</div>
|
</div>
|
||||||
"#,
|
"#,
|
||||||
child_type,
|
child_type, parent_type
|
||||||
parent_type
|
|
||||||
),
|
),
|
||||||
content_tree: String::new(),
|
content_tree: String::new(),
|
||||||
})
|
})
|
||||||
@ -807,7 +928,10 @@ fn extract_related(m: &ParsedMail, part_addr: &mut Vec<String>) -> Result<Body,
|
|||||||
.collect();
|
.collect();
|
||||||
unhandled_types.sort();
|
unhandled_types.sort();
|
||||||
if !unhandled_types.is_empty() {
|
if !unhandled_types.is_empty() {
|
||||||
warn!("{MULTIPART_RELATED} contains the following unhandled mimetypes {unhandled_types:?}");
|
warn!(
|
||||||
|
"{} contains the following unhandled mimetypes {:?}",
|
||||||
|
MULTIPART_RELATED, unhandled_types
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, sp) in m.subparts.iter().enumerate() {
|
for (i, sp) in m.subparts.iter().enumerate() {
|
||||||
@ -820,7 +944,7 @@ fn extract_related(m: &ParsedMail, part_addr: &mut Vec<String>) -> Result<Body,
|
|||||||
if let Some(cid) = sp.headers.get_first_value("Content-Id") {
|
if let Some(cid) = sp.headers.get_first_value("Content-Id") {
|
||||||
let mut part_id = part_addr.clone();
|
let mut part_id = part_addr.clone();
|
||||||
part_id.push(i.to_string());
|
part_id.push(i.to_string());
|
||||||
info!("cid: {cid} part_id {part_id:?}");
|
info!("cid: {} part_id {:?}", cid, part_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -908,7 +1032,7 @@ fn extract_attachment(m: &ParsedMail, id: &str, idx: &[usize]) -> Option<Attachm
|
|||||||
// No known filename, assume it's not an attachment
|
// No known filename, assume it's not an attachment
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
info!("filename {filename}");
|
info!("filename {}", filename);
|
||||||
|
|
||||||
// TODO: grab this from somewhere
|
// TODO: grab this from somewhere
|
||||||
let content_id = None;
|
let content_id = None;
|
||||||
@ -940,7 +1064,7 @@ fn email_address_strings(emails: &[Email]) -> Vec<String> {
|
|||||||
emails
|
emails
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| e.to_string())
|
.map(|e| e.to_string())
|
||||||
.inspect(|e| info!("e {e}"))
|
.inspect(|e| info!("e {}", e))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -964,11 +1088,7 @@ CC: {}
|
|||||||
Date: {}
|
Date: {}
|
||||||
Subject: {}
|
Subject: {}
|
||||||
"#,
|
"#,
|
||||||
from,
|
from, to, cc, date, subject
|
||||||
to,
|
|
||||||
cc,
|
|
||||||
date,
|
|
||||||
subject
|
|
||||||
);
|
);
|
||||||
Ok(Body::text(text))
|
Ok(Body::text(text))
|
||||||
}
|
}
|
||||||
@ -981,7 +1101,7 @@ Subject: {}
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_attachment_filename(header_value: &str) -> &str {
|
pub fn get_attachment_filename(header_value: &str) -> &str {
|
||||||
info!("get_attachment_filename {header_value}");
|
info!("get_attachment_filename {}", header_value);
|
||||||
// Strip last "
|
// Strip last "
|
||||||
let v = &header_value[..header_value.len() - 1];
|
let v = &header_value[..header_value.len() - 1];
|
||||||
if let Some(idx) = v.rfind('"') {
|
if let Some(idx) = v.rfind('"') {
|
||||||
@ -1071,7 +1191,7 @@ pub async fn set_read_status<'ctx>(
|
|||||||
.iter()
|
.iter()
|
||||||
.filter(|uid| is_notmuch_thread_or_id(uid))
|
.filter(|uid| is_notmuch_thread_or_id(uid))
|
||||||
.collect();
|
.collect();
|
||||||
info!("set_read_status({unread} {uids:?})");
|
info!("set_read_status({} {:?})", unread, uids);
|
||||||
for uid in uids {
|
for uid in uids {
|
||||||
if unread {
|
if unread {
|
||||||
nm.tag_add("unread", uid)?;
|
nm.tag_add("unread", uid)?;
|
||||||
@ -1086,7 +1206,8 @@ async fn photo_url_for_email_address(
|
|||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
addr: &str,
|
addr: &str,
|
||||||
) -> Result<Option<String>, ServerError> {
|
) -> Result<Option<String>, ServerError> {
|
||||||
let row = sqlx::query_as::<_, (String,)>(include_str!("../sql/photo_url_for_email_address.sql"))
|
let row =
|
||||||
|
sqlx::query_as::<_, (String,)>(include_str!("../sql/photo_url_for_email_address.sql"))
|
||||||
.bind(addr)
|
.bind(addr)
|
||||||
.fetch_optional(pool)
|
.fetch_optional(pool)
|
||||||
.await?;
|
.await?;
|
||||||
@ -1114,10 +1235,13 @@ pub async fn label_unprocessed(
|
|||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
let ids = nm.message_ids(query)?;
|
let ids = nm.message_ids(query)?;
|
||||||
info!(
|
info!(
|
||||||
"Processing {limit:?} of {} messages with '{query}'",
|
"Processing {:?} of {} messages with '{}'",
|
||||||
ids.len()
|
limit,
|
||||||
|
ids.len(),
|
||||||
|
query
|
||||||
);
|
);
|
||||||
let rules: Vec<_> = sqlx::query_as::<_, (Json<Rule>,)>(include_str!("../sql/label_unprocessed.sql"))
|
let rules: Vec<_> =
|
||||||
|
sqlx::query_as::<_, (Json<Rule>,)>(include_str!("../sql/label_unprocessed.sql"))
|
||||||
.fetch(pool)
|
.fetch(pool)
|
||||||
.map(|r| r.unwrap().0 .0)
|
.map(|r| r.unwrap().0 .0)
|
||||||
.collect()
|
.collect()
|
||||||
@ -1146,7 +1270,7 @@ pub async fn label_unprocessed(
|
|||||||
let files = nm.files(&id)?;
|
let files = nm.files(&id)?;
|
||||||
// Only process the first file path is multiple files have the same id
|
// Only process the first file path is multiple files have the same id
|
||||||
let Some(path) = files.iter().next() else {
|
let Some(path) = files.iter().next() else {
|
||||||
error!("No files for message-ID {id}");
|
error!("No files for message-ID {}", id);
|
||||||
let t = "Letterbox/Bad";
|
let t = "Letterbox/Bad";
|
||||||
nm.tag_add(t, &id)?;
|
nm.tag_add(t, &id)?;
|
||||||
let t = "unprocessed";
|
let t = "unprocessed";
|
||||||
@ -1154,12 +1278,12 @@ pub async fn label_unprocessed(
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let file = File::open(&path)?;
|
let file = File::open(&path)?;
|
||||||
info!("parsing {path}");
|
info!("parsing {}", path);
|
||||||
let mmap = unsafe { MmapOptions::new().map(&file)? };
|
let mmap = unsafe { MmapOptions::new().map(&file)? };
|
||||||
let m = match info_span!("parse_mail", path = path).in_scope(|| parse_mail(&mmap)) {
|
let m = match info_span!("parse_mail", path = path).in_scope(|| parse_mail(&mmap)) {
|
||||||
Ok(m) => m,
|
Ok(m) => m,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!("Failed to parse {path}: {err}");
|
error!("Failed to parse {}: {}", path, err);
|
||||||
let t = "Letterbox/Bad";
|
let t = "Letterbox/Bad";
|
||||||
nm.tag_add(t, &id)?;
|
nm.tag_add(t, &id)?;
|
||||||
let t = "unprocessed";
|
let t = "unprocessed";
|
||||||
@ -1171,7 +1295,8 @@ pub async fn label_unprocessed(
|
|||||||
if matched_rule {
|
if matched_rule {
|
||||||
if dryrun {
|
if dryrun {
|
||||||
info!(
|
info!(
|
||||||
"\nAdd tags: {add_tags:?}\nTo: {} From: {} Subject: {}\n",
|
"\nAdd tags: {:?}\nTo: {} From: {} Subject: {}\n",
|
||||||
|
add_tags,
|
||||||
m.headers.get_first_value("to").expect("no from header"),
|
m.headers.get_first_value("to").expect("no from header"),
|
||||||
m.headers.get_first_value("from").expect("no from header"),
|
m.headers.get_first_value("from").expect("no from header"),
|
||||||
m.headers
|
m.headers
|
||||||
@ -1203,8 +1328,7 @@ pub async fn label_unprocessed(
|
|||||||
.push(id.clone());
|
.push(id.clone());
|
||||||
}
|
}
|
||||||
//nm.tag_remove("unprocessed", &id)?;
|
//nm.tag_remove("unprocessed", &id)?;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if add_tags.is_empty() {
|
if add_tags.is_empty() {
|
||||||
let t = "Grey".to_string();
|
let t = "Grey".to_string();
|
||||||
add_mutations
|
add_mutations
|
||||||
@ -1227,7 +1351,7 @@ pub async fn label_unprocessed(
|
|||||||
}
|
}
|
||||||
info!("Adding {} distinct labels", add_mutations.len());
|
info!("Adding {} distinct labels", add_mutations.len());
|
||||||
for (tag, ids) in add_mutations.iter() {
|
for (tag, ids) in add_mutations.iter() {
|
||||||
info!(" {tag}: {}", ids.len());
|
info!(" {}: {}", tag, ids.len());
|
||||||
if !dryrun {
|
if !dryrun {
|
||||||
let ids: Vec<_> = ids.iter().map(|s| s.as_str()).collect();
|
let ids: Vec<_> = ids.iter().map(|s| s.as_str()).collect();
|
||||||
info_span!("tags_add", tag = tag, count = ids.len())
|
info_span!("tags_add", tag = tag, count = ids.len())
|
||||||
@ -1236,7 +1360,7 @@ pub async fn label_unprocessed(
|
|||||||
}
|
}
|
||||||
info!("Removing {} distinct labels", rm_mutations.len());
|
info!("Removing {} distinct labels", rm_mutations.len());
|
||||||
for (tag, ids) in rm_mutations.iter() {
|
for (tag, ids) in rm_mutations.iter() {
|
||||||
info!(" {tag}: {}", ids.len());
|
info!(" {}: {}", tag, ids.len());
|
||||||
if !dryrun {
|
if !dryrun {
|
||||||
let ids: Vec<_> = ids.iter().map(|s| s.as_str()).collect();
|
let ids: Vec<_> = ids.iter().map(|s| s.as_str()).collect();
|
||||||
info_span!("tags_remove", tag = tag, count = ids.len())
|
info_span!("tags_remove", tag = tag, count = ids.len())
|
||||||
@ -1252,7 +1376,7 @@ fn find_tags<'a, 'b>(rules: &'a [Rule], headers: &'b [MailHeader]) -> (bool, Has
|
|||||||
for rule in rules {
|
for rule in rules {
|
||||||
for hdr in headers {
|
for hdr in headers {
|
||||||
if rule.is_match(&hdr.get_key(), &hdr.get_value()) {
|
if rule.is_match(&hdr.get_key(), &hdr.get_value()) {
|
||||||
//info!("Matched {rule:?}");
|
//info!("Matched {:?}", rule);
|
||||||
matched_rule = true;
|
matched_rule = true;
|
||||||
add_tags.insert(rule.tag.as_str());
|
add_tags.insert(rule.tag.as_str());
|
||||||
if rule.stop_on_match {
|
if rule.stop_on_match {
|
||||||
@ -1804,7 +1928,13 @@ mod tests {
|
|||||||
let report: TlsRpt = serde_json::from_str(REPORT_V2).unwrap();
|
let report: TlsRpt = serde_json::from_str(REPORT_V2).unwrap();
|
||||||
assert_eq!(report.organization_name, "Google Inc.");
|
assert_eq!(report.organization_name, "Google Inc.");
|
||||||
assert_eq!(report.policies.len(), 1);
|
assert_eq!(report.policies.len(), 1);
|
||||||
let mx_host = report.policies[0].policy.mx_host.as_ref().unwrap().get(0).unwrap();
|
let mx_host = report.policies[0]
|
||||||
|
.policy
|
||||||
|
.mx_host
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.get(0)
|
||||||
|
.unwrap();
|
||||||
match mx_host {
|
match mx_host {
|
||||||
MxHost::String(s) => assert_eq!(s, "mail.xinu.tv"),
|
MxHost::String(s) => assert_eq!(s, "mail.xinu.tv"),
|
||||||
MxHost::Object(_) => panic!("Expected a string"),
|
MxHost::Object(_) => panic!("Expected a string"),
|
||||||
@ -1816,13 +1946,19 @@ mod tests {
|
|||||||
let report: TlsRpt = serde_json::from_str(REPORT_V3).unwrap();
|
let report: TlsRpt = serde_json::from_str(REPORT_V3).unwrap();
|
||||||
assert_eq!(report.organization_name, "Google Inc.");
|
assert_eq!(report.organization_name, "Google Inc.");
|
||||||
assert_eq!(report.policies.len(), 1);
|
assert_eq!(report.policies.len(), 1);
|
||||||
let mx_host = report.policies[0].policy.mx_host.as_ref().unwrap().get(0).unwrap();
|
let mx_host = report.policies[0]
|
||||||
|
.policy
|
||||||
|
.mx_host
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.get(0)
|
||||||
|
.unwrap();
|
||||||
match mx_host {
|
match mx_host {
|
||||||
MxHost::Object(o) => {
|
MxHost::Object(o) => {
|
||||||
assert_eq!(o.hostname, "mail.xinu.tv");
|
assert_eq!(o.hostname, "mail.xinu.tv");
|
||||||
assert_eq!(o.failure_count, 0);
|
assert_eq!(o.failure_count, 0);
|
||||||
assert_eq!(o.result_type, "success");
|
assert_eq!(o.result_type, "success");
|
||||||
},
|
}
|
||||||
MxHost::String(_) => panic!("Expected an object"),
|
MxHost::String(_) => panic!("Expected an object"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user