Compare commits

..

44 Commits

Author SHA1 Message Date
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
ce17c4a7d8 chore: Release
All checks were successful
Continuous integration / Check (push) Successful in 54s
Continuous integration / Test Suite (push) Successful in 1m24s
Continuous integration / Trunk (push) Successful in 58s
Continuous integration / Rustfmt (push) Successful in 41s
Continuous integration / build (push) Successful in 1m22s
Continuous integration / Disallow unused dependencies (push) Successful in 2m12s
2025-08-11 14:54:16 -07:00
c8850404b8 server: rework dmarc parsing to use askama 2025-08-11 14:53:12 -07:00
638e94b4ae web: create seperate email overrides CSS file 2025-08-11 12:42:45 -07:00
d0f4716d83 server: add gzip dmarc email support
Some checks failed
Continuous integration / Check (push) Failing after 59s
Continuous integration / Test Suite (push) Failing after 1m32s
Continuous integration / Trunk (push) Failing after 47s
Continuous integration / Rustfmt (push) Failing after 35s
Continuous integration / build (push) Failing after 1m39s
Continuous integration / Disallow unused dependencies (push) Failing after 2m5s
2025-08-11 12:41:25 -07:00
59e35062e7 server: handle application/zip for google dmarc 2025-08-11 12:41:03 -07:00
43827b4d87 Merge pull request 'fix(deps): update rust crate uuid to v1.18.0' (#145) from renovate/all-minor-patch into master
All checks were successful
Continuous integration / Check (push) Successful in 54s
Continuous integration / Test Suite (push) Successful in 1m2s
Continuous integration / Trunk (push) Successful in 56s
Continuous integration / Rustfmt (push) Successful in 40s
Continuous integration / build (push) Successful in 1m21s
Continuous integration / Disallow unused dependencies (push) Successful in 2m3s
2025-08-11 03:45:52 -07:00
b29e92cd9c fix(deps): update rust crate uuid to v1.18.0
All checks were successful
Continuous integration / Check (push) Successful in 56s
Continuous integration / Test Suite (push) Successful in 1m4s
Continuous integration / Trunk (push) Successful in 54s
Continuous integration / Rustfmt (push) Successful in 38s
Continuous integration / build (push) Successful in 1m23s
Continuous integration / Disallow unused dependencies (push) Successful in 2m4s
2025-08-11 10:31:27 +00:00
42bea43de9 Merge pull request 'chore(deps): lock file maintenance' (#144) from renovate/lock-file-maintenance into master
All checks were successful
Continuous integration / Check (push) Successful in 54s
Continuous integration / Test Suite (push) Successful in 1m1s
Continuous integration / Trunk (push) Successful in 7m34s
Continuous integration / Rustfmt (push) Successful in 39s
Continuous integration / build (push) Successful in 1m19s
Continuous integration / Disallow unused dependencies (push) Successful in 2m2s
2025-08-10 18:01:35 -07:00
4048edde11 chore(deps): lock file maintenance
All checks were successful
Continuous integration / Check (push) Successful in 2m9s
Continuous integration / Test Suite (push) Successful in 4m15s
Continuous integration / Trunk (push) Successful in 7m9s
Continuous integration / Rustfmt (push) Successful in 44s
Continuous integration / build (push) Successful in 4m30s
Continuous integration / Disallow unused dependencies (push) Successful in 2m7s
2025-08-11 00:01:53 +00:00
90768d0d1b Merge pull request 'fix(deps): update rust crate clap to v4.5.43' (#143) from renovate/all-minor-patch into master
All checks were successful
Continuous integration / Check (push) Successful in 1m4s
Continuous integration / Test Suite (push) Successful in 2m18s
Continuous integration / Trunk (push) Successful in 1m3s
Continuous integration / Rustfmt (push) Successful in 51s
Continuous integration / build (push) Successful in 2m10s
Continuous integration / Disallow unused dependencies (push) Successful in 2m3s
2025-08-06 10:15:44 -07:00
70e6271ca3 fix(deps): update rust crate clap to v4.5.43
All checks were successful
Continuous integration / Check (push) Successful in 1m30s
Continuous integration / Test Suite (push) Successful in 1m49s
Continuous integration / Trunk (push) Successful in 7m31s
Continuous integration / Rustfmt (push) Successful in 38s
Continuous integration / build (push) Successful in 3m21s
Continuous integration / Disallow unused dependencies (push) Successful in 2m14s
2025-08-06 16:46:18 +00:00
0bda21e5e9 Merge pull request 'chore(deps): lock file maintenance' (#142) from renovate/lock-file-maintenance into master
All checks were successful
Continuous integration / Check (push) Successful in 1m26s
Continuous integration / Test Suite (push) Successful in 1m57s
Continuous integration / Trunk (push) Successful in 7m55s
Continuous integration / Rustfmt (push) Successful in 38s
Continuous integration / build (push) Successful in 2m17s
Continuous integration / Disallow unused dependencies (push) Successful in 2m14s
2025-08-03 18:01:42 -07:00
f987b4e4b4 chore(deps): lock file maintenance
All checks were successful
Continuous integration / Check (push) Successful in 1m33s
Continuous integration / Test Suite (push) Successful in 3m31s
Continuous integration / Trunk (push) Successful in 7m29s
Continuous integration / Rustfmt (push) Successful in 40s
Continuous integration / build (push) Successful in 3m25s
Continuous integration / Disallow unused dependencies (push) Successful in 2m16s
2025-08-04 00:01:42 +00:00
a873ec9208 Merge pull request 'fix(deps): update rust crate tokio to v1.47.1' (#141) from renovate/all-minor-patch into master
All checks were successful
Continuous integration / Check (push) Successful in 1m29s
Continuous integration / Test Suite (push) Successful in 2m22s
Continuous integration / Trunk (push) Successful in 1m18s
Continuous integration / Rustfmt (push) Successful in 55s
Continuous integration / build (push) Successful in 2m2s
Continuous integration / Disallow unused dependencies (push) Successful in 2m15s
2025-08-01 05:16:00 -07:00
d8d26e1f59 fix(deps): update rust crate tokio to v1.47.1
All checks were successful
Continuous integration / Check (push) Successful in 1m17s
Continuous integration / Test Suite (push) Successful in 2m34s
Continuous integration / Trunk (push) Successful in 7m13s
Continuous integration / Rustfmt (push) Successful in 42s
Continuous integration / build (push) Successful in 2m40s
Continuous integration / Disallow unused dependencies (push) Successful in 2m18s
2025-08-01 11:46:16 +00:00
1322dde5c5 Merge pull request 'fix(deps): update rust crate serde_json to v1.0.142' (#140) from renovate/all-minor-patch into master
All checks were successful
Continuous integration / Check (push) Successful in 1m6s
Continuous integration / Test Suite (push) Successful in 3m3s
Continuous integration / Trunk (push) Successful in 55s
Continuous integration / Rustfmt (push) Successful in 41s
Continuous integration / build (push) Successful in 2m12s
Continuous integration / Disallow unused dependencies (push) Successful in 2m2s
2025-07-31 17:45:58 -07:00
a2147081e8 fix(deps): update rust crate serde_json to v1.0.142
All checks were successful
Continuous integration / Check (push) Successful in 1m14s
Continuous integration / Test Suite (push) Successful in 2m26s
Continuous integration / Trunk (push) Successful in 7m15s
Continuous integration / Rustfmt (push) Successful in 45s
Continuous integration / build (push) Successful in 3m34s
Continuous integration / Disallow unused dependencies (push) Successful in 2m3s
2025-08-01 00:01:45 +00:00
8c6a24e400 Merge pull request 'fix(deps): update rust crate clap to v4.5.42' (#139) from renovate/all-minor-patch into master
All checks were successful
Continuous integration / Check (push) Successful in 1m7s
Continuous integration / Test Suite (push) Successful in 1m55s
Continuous integration / Trunk (push) Successful in 53s
Continuous integration / Rustfmt (push) Successful in 38s
Continuous integration / build (push) Successful in 1m58s
Continuous integration / Disallow unused dependencies (push) Successful in 2m4s
2025-07-29 20:30:48 -07:00
8a08d97930 fix(deps): update rust crate clap to v4.5.42
All checks were successful
Continuous integration / Check (push) Successful in 1m6s
Continuous integration / Test Suite (push) Successful in 1m39s
Continuous integration / Trunk (push) Successful in 7m17s
Continuous integration / Rustfmt (push) Successful in 46s
Continuous integration / build (push) Successful in 2m1s
Continuous integration / Disallow unused dependencies (push) Successful in 2m12s
2025-07-30 03:01:20 +00:00
d24a851cd7 Merge pull request 'chore(deps): lock file maintenance' (#138) from renovate/lock-file-maintenance into master
All checks were successful
Continuous integration / Check (push) Successful in 1m27s
Continuous integration / Test Suite (push) Successful in 2m8s
Continuous integration / Trunk (push) Successful in 7m13s
Continuous integration / Rustfmt (push) Successful in 38s
Continuous integration / build (push) Successful in 2m23s
Continuous integration / Disallow unused dependencies (push) Successful in 2m38s
2025-07-27 17:31:34 -07:00
f6ff597f66 chore(deps): lock file maintenance
All checks were successful
Continuous integration / Check (push) Successful in 1m1s
Continuous integration / Test Suite (push) Successful in 3m28s
Continuous integration / Trunk (push) Successful in 7m21s
Continuous integration / Rustfmt (push) Successful in 45s
Continuous integration / build (push) Successful in 2m29s
Continuous integration / Disallow unused dependencies (push) Successful in 2m14s
2025-07-28 00:01:34 +00:00
387d133f09 Merge pull request 'fix(deps): update rust crate css-inline to 0.17.0' (#137) from renovate/all-minor-patch into master
All checks were successful
Continuous integration / Check (push) Successful in 1m0s
Continuous integration / Test Suite (push) Successful in 1m31s
Continuous integration / Trunk (push) Successful in 1m23s
Continuous integration / Rustfmt (push) Successful in 39s
Continuous integration / build (push) Successful in 1m56s
Continuous integration / Disallow unused dependencies (push) Successful in 2m17s
2025-07-26 13:15:52 -07:00
a9674e8b7b fix(deps): update rust crate css-inline to 0.17.0
All checks were successful
Continuous integration / Check (push) Successful in 58s
Continuous integration / Test Suite (push) Successful in 1m26s
Continuous integration / Trunk (push) Successful in 1m10s
Continuous integration / Rustfmt (push) Successful in 45s
Continuous integration / build (push) Successful in 2m58s
Continuous integration / Disallow unused dependencies (push) Successful in 2m8s
2025-07-26 20:01:22 +00:00
457f9ac1c2 Merge pull request 'fix(deps): update rust crate tokio to v1.47.0' (#136) from renovate/all-minor-patch into master
All checks were successful
Continuous integration / Check (push) Successful in 1m43s
Continuous integration / Test Suite (push) Successful in 1m35s
Continuous integration / Trunk (push) Successful in 1m0s
Continuous integration / Rustfmt (push) Successful in 1m8s
Continuous integration / build (push) Successful in 2m36s
Continuous integration / Disallow unused dependencies (push) Successful in 2m21s
2025-07-26 09:31:17 -07:00
d62759565f fix(deps): update rust crate tokio to v1.47.0
All checks were successful
Continuous integration / Check (push) Successful in 1m11s
Continuous integration / Test Suite (push) Successful in 2m48s
Continuous integration / Trunk (push) Successful in 7m20s
Continuous integration / Rustfmt (push) Successful in 40s
Continuous integration / build (push) Successful in 2m46s
Continuous integration / Disallow unused dependencies (push) Successful in 2m13s
2025-07-26 15:32:00 +00:00
4fd97700f7 Merge pull request 'chore(deps): lock file maintenance' (#134) from renovate/lock-file-maintenance into master
All checks were successful
Continuous integration / Check (push) Successful in 1m31s
Continuous integration / Test Suite (push) Successful in 2m15s
Continuous integration / Trunk (push) Successful in 7m55s
Continuous integration / Rustfmt (push) Successful in 40s
Continuous integration / build (push) Successful in 2m27s
Continuous integration / Disallow unused dependencies (push) Successful in 2m9s
2025-07-20 17:31:41 -07:00
99b9a88663 chore(deps): lock file maintenance
All checks were successful
Continuous integration / Check (push) Successful in 1m24s
Continuous integration / Test Suite (push) Successful in 2m26s
Continuous integration / Trunk (push) Successful in 1m4s
Continuous integration / Rustfmt (push) Successful in 38s
Continuous integration / build (push) Successful in 3m2s
Continuous integration / Disallow unused dependencies (push) Successful in 2m3s
2025-07-21 00:01:49 +00:00
56e6036892 Merge pull request 'fix(deps): update rust crate strum_macros to v0.27.2' (#133) from renovate/strum-monorepo into master
All checks were successful
Continuous integration / Check (push) Successful in 57s
Continuous integration / Test Suite (push) Successful in 1m14s
Continuous integration / Trunk (push) Successful in 51s
Continuous integration / Rustfmt (push) Successful in 39s
Continuous integration / build (push) Successful in 1m39s
Continuous integration / Disallow unused dependencies (push) Successful in 2m7s
2025-07-20 10:45:48 -07:00
232e436378 fix(deps): update rust crate strum_macros to v0.27.2
All checks were successful
Continuous integration / Check (push) Successful in 57s
Continuous integration / Test Suite (push) Successful in 1m28s
Continuous integration / Trunk (push) Successful in 51s
Continuous integration / Rustfmt (push) Successful in 39s
Continuous integration / build (push) Successful in 1m49s
Continuous integration / Disallow unused dependencies (push) Successful in 2m4s
2025-07-20 16:46:45 +00:00
20 changed files with 1696 additions and 377 deletions

751
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ authors = ["Bill Thiede <git@xinu.tv>"]
edition = "2021"
license = "UNLICENSED"
publish = ["xinu"]
version = "0.17.27"
version = "0.17.30"
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

@@ -14,6 +14,7 @@ version.workspace = true
[dependencies]
ammonia = "4.1.0"
anyhow = "1.0.98"
askama = { version = "0.14.0", features = ["derive"] }
async-graphql = { version = "7", features = ["log"] }
async-graphql-axum = "7.0.16"
async-trait = "0.1.88"
@@ -23,17 +24,19 @@ build-info = "0.0.41"
cacher = { version = "0.2.0", registry = "xinu" }
chrono = "0.4.40"
clap = { version = "4.5.37", features = ["derive"] }
css-inline = "0.16.0"
css-inline = "0.17.0"
flate2 = "1.1.2"
futures = "0.3.31"
headers = "0.4.0"
html-escape = "0.2.13"
letterbox-notmuch = { path = "../notmuch", version = "0.17.27", registry = "xinu" }
letterbox-shared = { path = "../shared", version = "0.17.27", registry = "xinu" }
letterbox-notmuch = { path = "../notmuch", version = "0.17.30", registry = "xinu" }
letterbox-shared = { path = "../shared", version = "0.17.30", registry = "xinu" }
linkify = "0.10.0"
lol_html = "2.3.0"
mailparse = "0.16.1"
maplit = "1.0.2"
memmap = "0.7.0"
quick-xml = { version = "0.38.1", features = ["serialize"] }
regex = "1.11.1"
reqwest = { version = "0.12.15", features = ["blocking"] }
scraper = "0.23.1"
@@ -50,6 +53,8 @@ urlencoding = "2.1.3"
#xtracing = { git = "http://git-private.h.xinu.tv/wathiede/xtracing.git" }
#xtracing = { path = "../../xtracing" }
xtracing = { version = "0.3.2", registry = "xinu" }
zip = "4.3.0"
[build-dependencies]
build-info-build = "0.0.41"

View File

@@ -2,4 +2,5 @@ fn main() {
// Calling `build_info_build::build_script` collects all data and makes it available to `build_info::build_info!`
// and `build_info::format!` in the main program.
build_info_build::build_script();
println!("cargo:rerun-if-changed=templates");
}

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

View File

@@ -39,4 +39,10 @@ pub enum ServerError {
QueryParseError(#[from] QueryParserError),
#[error("impossible: {0}")]
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)]

File diff suppressed because it is too large Load Diff

7
server/src/templates.rs Normal file
View File

@@ -0,0 +1,7 @@
use askama::Template;
#[derive(Template)]
#[template(path = "dmarc_report.html")]
pub struct DmarcReportTemplate<'a> {
pub feedback: &'a crate::nm::Feedback,
}

View File

@@ -0,0 +1,93 @@
<!DOCTYPE html>
<html>
<head>
<title>DMARC Report</title>
</head>
<body>
{% if report.report_metadata.is_some() %}
{% let meta = report.report_metadata.as_ref().unwrap() %}
<b>Reporter:</b> {{ meta.org_name }}<br>
<b>Contact:</b> {{ meta.email }}<br>
<b>Report ID:</b> {{ meta.report_id }}<br>
{% if meta.date_range.is_some() %}
{% let dr = meta.date_range.as_ref().unwrap() %}
<b>Date range:</b>
{{ dr.begin }}
to
{{ dr.end }}
<br>
{% endif %}
{% endif %}
{% if report.policy_published.is_some() %}
{% let pol = report.policy_published.as_ref().unwrap() %}
<b>Policy Published:</b>
<ul>
<li>Domain: {{ pol.domain }}</li>
<li>ADKIM: {{ pol.adkim }}</li>
<li>ASPF: {{ pol.aspf }}</li>
<li>Policy: {{ pol.p }}</li>
<li>Subdomain Policy: {{ pol.sp }}</li>
<li>Percent: {{ pol.pct }}</li>
</ul>
{% endif %}
{% if report.record.is_some() %}
<b>Records:</b>
<table style="border-collapse:collapse;width:100%;font-size:0.95em;">
<thead>
<tr style="background:#f0f0f0;">
<th style="border:1px solid #bbb;padding:4px 8px;">Source IP</th>
<th style="border:1px solid #bbb;padding:4px 8px;">Count</th>
<th style="border:1px solid #bbb;padding:4px 8px;">Header From</th>
<th style="border:1px solid #bbb;padding:4px 8px;">Disposition</th>
<th style="border:1px solid #bbb;padding:4px 8px;">DKIM</th>
<th style="border:1px solid #bbb;padding:4px 8px;">SPF</th>
<th style="border:1px solid #bbb;padding:4px 8px;">Auth Results</th>
</tr>
</thead>
<tbody>
{% for rec in report.record.as_ref().unwrap() %}
<tr>
<td style="border:1px solid #bbb;padding:4px 8px;">{{ rec.source_ip }}</td>
<td style="border:1px solid #bbb;padding:4px 8px;">{{ rec.count }}</td>
<td style="border:1px solid #bbb;padding:4px 8px;">{{ rec.header_from }}</td>
<td style="border:1px solid #bbb;padding:4px 8px;">{{ rec.disposition }}</td>
<td style="border:1px solid #bbb;padding:4px 8px;">{{ rec.dkim }}</td>
<td style="border:1px solid #bbb;padding:4px 8px;">{{ rec.spf }}</td>
<td style="border:1px solid #bbb;padding:4px 8px;">
{% if rec.auth_results.is_some() %}
{% let auth = rec.auth_results.as_ref().unwrap() %}
{% for dkimres in auth.dkim %}
<span style="white-space:nowrap;">
DKIM: domain=<b>{{ dkimres.domain }}</b>
selector=<b>{{ dkimres.selector }}</b>
result=<b>{{ dkimres.result }}</b>
</span><br>
{% endfor %}
{% for spfres in auth.spf %}
<span style="white-space:nowrap;">
SPF: domain=<b>{{ spfres.domain }}</b>
scope=<b>{{ spfres.scope }}</b>
result=<b>{{ spfres.result }}</b>
</span><br>
{% endfor %}
{% for reason in rec.reason %}
<span style="white-space:nowrap;">Reason: {{ reason }}</span><br>
{% endfor %}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% if report.report_metadata.is_none() && report.policy_published.is_none() && report.record.is_none() %}
<p>No DMARC summary found.</p>
{% endif %}
</body>
</html>

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.27", registry = "xinu" }
letterbox-notmuch = { path = "../notmuch", version = "0.17.30", 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.27", registry = "xinu" }
letterbox-shared = { path = "../shared/", version = "0.17.30", registry = "xinu" }
seed_hooks = { version = "0.4.1", registry = "xinu" }
strum_macros = "0.27.1"
gloo-console = "0.3.0"

View File

@@ -16,10 +16,11 @@
<link data-trunk rel="css" href="static/vars.css" />
<link data-trunk rel="tailwind-css" href="./src/tailwind.css" />
<link data-trunk rel="css" href="static/overrides.css" />
<link data-trunk rel="css" href="static/email-specific.css" />
</head>
<body>
<section id="app"></section>
</body>
</html>
</html>

View File

@@ -1025,7 +1025,7 @@ fn message_render(msg: &ShowThreadQueryThreadOnEmailThreadMessages, open: bool)
],
IF!(open =>
div![
C!["content", "bg-white", "text-black", "p-4", "min-w-full", "w-0","overflow-x-auto", from],
C!["content", "bg-white", "text-black", "p-4", "min-w-full", "w-0","overflow-x-auto", from.map(|f|format!("from-{f}"))],
match &msg.body {
ShowThreadQueryThreadOnEmailThreadMessagesBody::UnhandledContentType(
ShowThreadQueryThreadOnEmailThreadMessagesBodyOnUnhandledContentType { contents ,content_tree},

View File

@@ -0,0 +1,11 @@
.mail-thread .content.from-noreply-news-bloomberg-com a {
background-color: initial !important;
}
.mail-thread .content.from-noreply-news-bloomberg-com h2 {
margin: 0 !important;
padding: 0 !important;
}
.mail-thread .content.from-dmarcreport-microsoft-com div {
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !important;
}

View File

@@ -57,15 +57,6 @@ html {
margin-left: 2em;
}
.mail-thread .content .noreply-news-bloomberg-com a {
background-color: initial !important;
}
.mail-thread .content .noreply-news-bloomberg-com h2 {
margin: 0 !important;
padding: 0 !important;
}
/* Hackaday figures have unreadable black on dark grey */
.news-post figcaption.wp-caption-text {
background-color: initial !important;