Compare commits

...

19 Commits

Author SHA1 Message Date
34bda32e30 chore: Release
Some checks failed
Continuous integration / Check (push) Successful in 49s
Continuous integration / Test Suite (push) Failing after 1m5s
Continuous integration / Trunk (push) Successful in 7m19s
Continuous integration / Rustfmt (push) Failing after 40s
Continuous integration / build (push) Successful in 1m28s
Continuous integration / Disallow unused dependencies (push) Failing after 27m34s
2025-08-13 16:07:44 -07:00
501ee417c9 server: address lint 2025-08-13 16:07:35 -07:00
ecc0a88341 chore: Release 2025-08-13 16:05:02 -07:00
d36d508df0 server: move email extraction code into separate mod 2025-08-13 10:36:50 -07:00
b9b12dd717 chore: Release
Some checks failed
Continuous integration / Check (push) Successful in 57s
Continuous integration / Test Suite (push) Successful in 1m14s
Continuous integration / Trunk (push) Successful in 1m55s
Continuous integration / Rustfmt (push) Failing after 42s
Continuous integration / build (push) Successful in 1m42s
Continuous integration / Disallow unused dependencies (push) Failing after 27m35s
2025-08-12 17:04:27 -07:00
633e055472 cargo sqlx prepare 2025-08-12 17:04:25 -07:00
951ee70279 server: don't duplicate dmarc table for google 2025-08-12 17:04:03 -07:00
3a41ab1767 server: much improved xmls pretty printer 2025-08-12 17:04:03 -07:00
5c9955a89e server: fix raw dmarc extraction for non-Google domains 2025-08-12 17:04:03 -07:00
1f75627fd2 server: fix is_dmarc check 2025-08-12 17:04:03 -07:00
5c42d04598 server: pretty print raw TLSRPT and DMARC data 2025-08-12 17:04:03 -07:00
4d888fbea3 server: more TLS report support and minor refactoring 2025-08-12 17:04:03 -07:00
8f53678e53 server: TLS report support 2025-08-12 17:04:03 -07:00
8218fca2ef server: include reason in dmarc report 2025-08-12 17:04:03 -07:00
01164d6afa Merge pull request 'fix(deps): update all non-major dependencies' (#148) from renovate/all-minor-patch into master
Some checks failed
Continuous integration / Check (push) Successful in 56s
Continuous integration / Test Suite (push) Successful in 1m14s
Continuous integration / Trunk (push) Successful in 7m29s
Continuous integration / Rustfmt (push) Successful in 40s
Continuous integration / build (push) Successful in 1m23s
Continuous integration / Disallow unused dependencies (push) Failing after 27m44s
2025-08-11 18:15:48 -07:00
2f06ae93ae fix(deps): update all non-major dependencies
All checks were successful
Continuous integration / Check (push) Successful in 1m9s
Continuous integration / Test Suite (push) Successful in 1m49s
Continuous integration / Trunk (push) Successful in 1m0s
Continuous integration / Rustfmt (push) Successful in 40s
Continuous integration / build (push) Successful in 2m6s
Continuous integration / Disallow unused dependencies (push) Successful in 2m12s
2025-08-11 23:32:19 +00:00
75d4fe49e2 chore: Release
All checks were successful
Continuous integration / Check (push) Successful in 47s
Continuous integration / Test Suite (push) Successful in 1m3s
Continuous integration / Trunk (push) Successful in 59s
Continuous integration / Rustfmt (push) Successful in 39s
Continuous integration / build (push) Successful in 1m22s
Continuous integration / Disallow unused dependencies (push) Successful in 2m14s
2025-08-11 16:20:48 -07:00
9f2016940b Merge pull request 'fix(deps): update all non-major dependencies' (#147) from renovate/all-minor-patch into master
Some checks failed
Continuous integration / Check (push) Has been cancelled
Continuous integration / Test Suite (push) Has been cancelled
Continuous integration / Trunk (push) Has been cancelled
Continuous integration / Rustfmt (push) Has been cancelled
Continuous integration / build (push) Has been cancelled
Continuous integration / Disallow unused dependencies (push) Has been cancelled
2025-08-11 16:00:57 -07:00
ba9cc0127b fix(deps): update all non-major dependencies
All checks were successful
Continuous integration / Check (push) Successful in 1m3s
Continuous integration / Test Suite (push) Successful in 1m27s
Continuous integration / Trunk (push) Successful in 1m3s
Continuous integration / Rustfmt (push) Successful in 40s
Continuous integration / build (push) Successful in 1m55s
Continuous integration / Disallow unused dependencies (push) Successful in 2m9s
2025-08-11 22:17:25 +00:00
16 changed files with 1586 additions and 967 deletions

80
Cargo.lock generated
View File

@@ -144,9 +144,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.98"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
[[package]]
name = "anymap"
@@ -854,7 +854,7 @@ dependencies = [
"rusoto_s3 0.48.0",
"serde",
"sqlx",
"thiserror 2.0.12",
"thiserror 2.0.14",
"tokio 1.47.1",
"tracing",
"urlencoding",
@@ -906,7 +906,7 @@ dependencies = [
"semver 1.0.26",
"serde",
"serde_json",
"thiserror 2.0.12",
"thiserror 2.0.14",
]
[[package]]
@@ -981,9 +981,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.43"
version = "4.5.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50fd97c9dc2399518aa331917ac6f274280ec5eb34e555dd291899745c48ec6f"
checksum = "1c1f056bae57e3e54c3375c41ff79619ddd13460a17d7438712bd0d83fda4ff8"
dependencies = [
"clap_builder",
"clap_derive",
@@ -991,9 +991,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.43"
version = "4.5.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c35b5830294e1fa0462034af85cc95225a4cb07092c088c55bda3147cfcd8f65"
checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8"
dependencies = [
"anstream",
"anstyle",
@@ -3165,13 +3165,13 @@ dependencies = [
"mailparse",
"serde",
"serde_json",
"thiserror 2.0.12",
"thiserror 2.0.14",
"tracing",
]
[[package]]
name = "letterbox-notmuch"
version = "0.17.28"
version = "0.17.32"
dependencies = [
"itertools",
"log",
@@ -3180,13 +3180,13 @@ dependencies = [
"rayon",
"serde",
"serde_json",
"thiserror 2.0.12",
"thiserror 2.0.14",
"tracing",
]
[[package]]
name = "letterbox-procmail2notmuch"
version = "0.17.28"
version = "0.17.32"
dependencies = [
"anyhow",
"clap",
@@ -3199,7 +3199,7 @@ dependencies = [
[[package]]
name = "letterbox-server"
version = "0.17.28"
version = "0.17.32"
dependencies = [
"ammonia",
"anyhow",
@@ -3219,8 +3219,8 @@ dependencies = [
"futures 0.3.31",
"headers",
"html-escape",
"letterbox-notmuch 0.17.28",
"letterbox-shared 0.17.28",
"letterbox-notmuch 0.17.32",
"letterbox-shared 0.17.32",
"linkify",
"lol_html",
"mailparse",
@@ -3234,7 +3234,7 @@ dependencies = [
"serde_json",
"sqlx",
"tantivy",
"thiserror 2.0.12",
"thiserror 2.0.14",
"tokio 1.47.1",
"tower-http",
"tracing",
@@ -3261,10 +3261,10 @@ dependencies = [
[[package]]
name = "letterbox-shared"
version = "0.17.28"
version = "0.17.32"
dependencies = [
"build-info",
"letterbox-notmuch 0.17.28",
"letterbox-notmuch 0.17.32",
"regex",
"serde",
"sqlx",
@@ -3274,7 +3274,7 @@ dependencies = [
[[package]]
name = "letterbox-web"
version = "0.17.28"
version = "0.17.32"
dependencies = [
"build-info",
"build-info-build",
@@ -3286,14 +3286,14 @@ dependencies = [
"graphql_client",
"human_format",
"itertools",
"letterbox-shared 0.17.28",
"letterbox-shared 0.17.32",
"log",
"seed",
"seed_hooks",
"serde",
"serde_json",
"strum_macros 0.27.2",
"thiserror 2.0.12",
"thiserror 2.0.14",
"uuid",
"wasm-bindgen",
"wasm-bindgen-test",
@@ -3465,7 +3465,7 @@ dependencies = [
"mime",
"precomputed-hash",
"selectors 0.30.0",
"thiserror 2.0.12",
"thiserror 2.0.14",
]
[[package]]
@@ -4044,7 +4044,7 @@ dependencies = [
"futures-sink",
"js-sys",
"pin-project-lite",
"thiserror 2.0.12",
"thiserror 2.0.14",
"tracing",
]
@@ -4076,7 +4076,7 @@ dependencies = [
"opentelemetry_sdk",
"prost",
"reqwest",
"thiserror 2.0.12",
"thiserror 2.0.14",
"tokio 1.47.1",
"tonic",
"tracing",
@@ -4108,7 +4108,7 @@ dependencies = [
"percent-encoding",
"rand 0.9.2",
"serde_json",
"thiserror 2.0.12",
"thiserror 2.0.14",
"tokio 1.47.1",
"tokio-stream",
"tracing",
@@ -4265,7 +4265,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323"
dependencies = [
"memchr",
"thiserror 2.0.12",
"thiserror 2.0.14",
"ucd-trie",
]
@@ -4589,7 +4589,7 @@ dependencies = [
"rustc-hash",
"rustls",
"socket2 0.5.10",
"thiserror 2.0.12",
"thiserror 2.0.14",
"tokio 1.47.1",
"tracing",
"web-time",
@@ -4610,7 +4610,7 @@ dependencies = [
"rustls",
"rustls-pki-types",
"slab",
"thiserror 2.0.12",
"thiserror 2.0.14",
"tinyvec",
"tracing",
"web-time",
@@ -5763,7 +5763,7 @@ dependencies = [
"serde_json",
"sha2 0.10.9",
"smallvec 1.15.1",
"thiserror 2.0.12",
"thiserror 2.0.14",
"time 0.3.41",
"tokio 1.47.1",
"tokio-stream",
@@ -5846,7 +5846,7 @@ dependencies = [
"smallvec 1.15.1",
"sqlx-core",
"stringprep",
"thiserror 2.0.12",
"thiserror 2.0.14",
"time 0.3.41",
"tracing",
"whoami",
@@ -5884,7 +5884,7 @@ dependencies = [
"smallvec 1.15.1",
"sqlx-core",
"stringprep",
"thiserror 2.0.12",
"thiserror 2.0.14",
"time 0.3.41",
"tracing",
"whoami",
@@ -5909,7 +5909,7 @@ dependencies = [
"serde",
"serde_urlencoded",
"sqlx-core",
"thiserror 2.0.12",
"thiserror 2.0.14",
"time 0.3.41",
"tracing",
"url",
@@ -6139,7 +6139,7 @@ dependencies = [
"tantivy-stacker",
"tantivy-tokenizer-api",
"tempfile",
"thiserror 2.0.12",
"thiserror 2.0.14",
"time 0.3.41",
"uuid",
"winapi 0.3.9",
@@ -6274,11 +6274,11 @@ dependencies = [
[[package]]
name = "thiserror"
version = "2.0.12"
version = "2.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
checksum = "0b0949c3a6c842cbde3f1686d6eea5a010516deb7085f79db747562d4102f41e"
dependencies = [
"thiserror-impl 2.0.12",
"thiserror-impl 2.0.14",
]
[[package]]
@@ -6294,9 +6294,9 @@ dependencies = [
[[package]]
name = "thiserror-impl"
version = "2.0.12"
version = "2.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
checksum = "cc5b44b4ab9c2fdd0e0512e6bece8388e214c0749f5862b114cc5b7a25daf227"
dependencies = [
"proc-macro2",
"quote",
@@ -6971,7 +6971,7 @@ dependencies = [
"log",
"rand 0.9.2",
"sha1",
"thiserror 2.0.12",
"thiserror 2.0.14",
"utf-8",
]
@@ -7745,7 +7745,7 @@ dependencies = [
"opentelemetry",
"opentelemetry-otlp",
"opentelemetry_sdk",
"thiserror 2.0.12",
"thiserror 2.0.14",
"tokio 1.47.1",
"tracing",
"tracing-appender",

View File

@@ -8,7 +8,7 @@ authors = ["Bill Thiede <git@xinu.tv>"]
edition = "2021"
license = "UNLICENSED"
publish = ["xinu"]
version = "0.17.28"
version = "0.17.32"
repository = "https://git.z.xinu.tv/wathiede/letterbox"
[profile.dev]

View File

@@ -1,22 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\nSELECT\n url\nFROM email_photo ep\nJOIN email_address ea\nON ep.id = ea.email_photo_id\nWHERE\n address = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "url",
"type_info": "Text"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false
]
},
"hash": "126e16a4675e8d79f330b235f9e1b8614ab1e1526e4e69691c5ebc70d54a42ef"
}

View File

@@ -1,20 +0,0 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT rule as \"rule: Json<Rule>\"\n FROM email_rule\n ORDER BY sort_order\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "rule: Json<Rule>",
"type_info": "Jsonb"
}
],
"parameters": {
"Left": []
},
"nullable": [
false
]
},
"hash": "6c5b0a96f45f78795732ea428cc01b4eab28b7150aa37387e7439a6b0b58e88c"
}

View File

@@ -29,8 +29,8 @@ flate2 = "1.1.2"
futures = "0.3.31"
headers = "0.4.0"
html-escape = "0.2.13"
letterbox-notmuch = { path = "../notmuch", version = "0.17.28", registry = "xinu" }
letterbox-shared = { path = "../shared", version = "0.17.28", registry = "xinu" }
letterbox-notmuch = { path = "../notmuch", version = "0.17.32", registry = "xinu" }
letterbox-shared = { path = "../shared", version = "0.17.32", registry = "xinu" }
linkify = "0.10.0"
lol_html = "2.3.0"
mailparse = "0.16.1"
@@ -55,6 +55,7 @@ urlencoding = "2.1.3"
xtracing = { version = "0.3.2", registry = "xinu" }
zip = "4.3.0"
[build-dependencies]
build-info-build = "0.0.41"

View File

@@ -0,0 +1 @@
SELECT rule as "rule: Json<Rule>" FROM email_rule ORDER BY sort_order

View File

@@ -0,0 +1 @@
SELECT url FROM email_photo ep JOIN email_address ea ON ep.id = ea.email_photo_id WHERE address = $1

1220
server/src/email_extract.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -41,4 +41,8 @@ pub enum ServerError {
InfaillibleError(#[from] Infallible),
#[error("askama error: {0}")]
AskamaError(#[from] askama::Error),
#[error("xml error: {0}")]
XmlError(#[from] quick_xml::Error),
#[error("xml encoding error: {0}")]
XmlEncodingError(#[from] quick_xml::encoding::EncodingError),
}

View File

@@ -237,6 +237,22 @@ impl Body {
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)]

View File

@@ -1,4 +1,5 @@
pub mod config;
pub mod email_extract;
pub mod error;
pub mod graphql;
pub mod newsreader;

File diff suppressed because it is too large Load Diff

View File

@@ -74,6 +74,10 @@
</span><br>
{% endfor %}
{% for reason in rec.reason %}
<span style="white-space:nowrap;">Reason: {{ reason }}</span><br>
{% endfor %}
{% endif %}
</td>
</tr>

View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<title>TLS Report</title>
</head>
<body>
<h3>TLS Report Summary:</h3>
<p>Organization: {{ report.organization_name }}</p>
<p>Date Range: {{ report.date_range.start_datetime }} to {{ report.date_range.end_datetime }}</p>
<p>Contact: {{ report.contact_info }}</p>
<p>Report ID: {{ report.report_id }}</p>
<h4>Policies:</h4>
{% for policy in report.policies %}
<h5>Policy Domain: {{ policy.policy.policy_domain }}</h5>
<ul>
<li>Policy Type: {{ policy.policy.policy_type }}</li>
<li>Policy String: {{ policy.policy.policy_string | join(", ") }}</li>
<li>Successful Sessions: {{ policy.summary.total_successful_session_count }}</li>
<li>Failed Sessions: {{ policy.summary.total_failure_session_count }}</li>
</ul>
<ul>
{% for mx_host in policy.policy.mx_host %}
<li>Hostname: {{ mx_host.hostname }}, Failures: {{ mx_host.failure_count }}, Result: {{ mx_host.result_type }}</li>
{% endfor %}
</ul>
<ul>
{% for detail in policy.failure_details %}
<li>Result: {{ detail.result_type }}, Sending IP: {{ detail.sending_mta_ip }}, Failed Sessions: {{ detail.failed_session_count }}
{% if detail.failure_reason_code != "" %}
(Reason: {{ detail.failure_reason_code }})
{% endif %}
</li>
(Receiving IP: {{ detail.receiving_ip }})
(Receiving MX: {{ detail.receiving_mx_hostname }})
(Additional Info: {{ detail.additional_info }})
{% endfor %}
</ul>
{% endfor %}
</body>
</html>

View File

@@ -12,7 +12,7 @@ version.workspace = true
[dependencies]
build-info = "0.0.41"
letterbox-notmuch = { path = "../notmuch", version = "0.17.28", registry = "xinu" }
letterbox-notmuch = { path = "../notmuch", version = "0.17.32", registry = "xinu" }
regex = "1.11.1"
serde = { version = "1.0.219", features = ["derive"] }
sqlx = "0.8.5"

View File

@@ -33,7 +33,7 @@ wasm-bindgen = "=0.2.100"
uuid = { version = "1.16.0", features = [
"js",
] } # direct dep to set js feature, prevents Rng issues
letterbox-shared = { path = "../shared/", version = "0.17.28", registry = "xinu" }
letterbox-shared = { path = "../shared/", version = "0.17.32", registry = "xinu" }
seed_hooks = { version = "0.4.1", registry = "xinu" }
strum_macros = "0.27.1"
gloo-console = "0.3.0"