mirror of
https://github.com/mjl-/mox.git
synced 2024-12-26 16:33:47 +03:00
webadmin: in list with dmarc evaluations, add the dispositions applied
to easily spot rejects
This commit is contained in:
parent
bcb80c3598
commit
651fa68067
4 changed files with 41 additions and 22 deletions
|
@ -22,6 +22,7 @@ import (
|
|||
"time"
|
||||
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
|
@ -219,9 +220,10 @@ func Evaluations(ctx context.Context) ([]Evaluation, error) {
|
|||
// EvaluationStat summarizes stored evaluations, for inclusion in an upcoming
|
||||
// aggregate report, for a domain.
|
||||
type EvaluationStat struct {
|
||||
Domain dns.Domain
|
||||
Dispositions []string
|
||||
Count int
|
||||
SendReport bool
|
||||
Domain dns.Domain
|
||||
}
|
||||
|
||||
// EvaluationStats returns evaluation counts and report-sending status per domain.
|
||||
|
@ -235,6 +237,9 @@ func EvaluationStats(ctx context.Context) (map[string]EvaluationStat, error) {
|
|||
|
||||
err = bstore.QueryDB[Evaluation](ctx, db).ForEach(func(e Evaluation) error {
|
||||
if stat, ok := r[e.PolicyDomain]; ok {
|
||||
if !slices.Contains(stat.Dispositions, string(e.Disposition)) {
|
||||
stat.Dispositions = append(stat.Dispositions, string(e.Disposition))
|
||||
}
|
||||
stat.Count++
|
||||
stat.SendReport = stat.SendReport || !e.Optional
|
||||
r[e.PolicyDomain] = stat
|
||||
|
@ -244,9 +249,10 @@ func EvaluationStats(ctx context.Context) (map[string]EvaluationStat, error) {
|
|||
return fmt.Errorf("parsing domain %q: %v", e.PolicyDomain, err)
|
||||
}
|
||||
r[e.PolicyDomain] = EvaluationStat{
|
||||
Domain: dom,
|
||||
Dispositions: []string{string(e.Disposition)},
|
||||
Count: 1,
|
||||
SendReport: !e.Optional,
|
||||
Domain: dom,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -109,14 +109,16 @@ func TestEvaluations(t *testing.T) {
|
|||
|
||||
expStats := map[string]EvaluationStat{
|
||||
"sender1.example": {
|
||||
Domain: dns.Domain{ASCII: "sender1.example"},
|
||||
Dispositions: []string{"none"},
|
||||
Count: 3,
|
||||
SendReport: true,
|
||||
Domain: dns.Domain{ASCII: "sender1.example"},
|
||||
},
|
||||
"sender2.example": {
|
||||
Domain: dns.Domain{ASCII: "sender2.example"},
|
||||
Dispositions: []string{"none"},
|
||||
Count: 1,
|
||||
SendReport: true,
|
||||
Domain: dns.Domain{ASCII: "sender2.example"},
|
||||
},
|
||||
}
|
||||
stats, err := EvaluationStats(ctxbg)
|
||||
|
@ -142,9 +144,10 @@ func TestEvaluations(t *testing.T) {
|
|||
|
||||
expStats = map[string]EvaluationStat{
|
||||
"sender2.example": {
|
||||
Domain: dns.Domain{ASCII: "sender2.example"},
|
||||
Dispositions: []string{"none"},
|
||||
Count: 1,
|
||||
SendReport: true,
|
||||
Domain: dns.Domain{ASCII: "sender2.example"},
|
||||
},
|
||||
}
|
||||
stats, err = EvaluationStats(ctxbg)
|
||||
|
|
|
@ -1112,6 +1112,7 @@ const dmarcEvaluations = async () => {
|
|||
dom.thead(
|
||||
dom.tr(
|
||||
dom.th('Domain', attr({title: 'Domain in the message From header. Keep in mind these can be forged, so this does not necessarily mean someone from this domain authentically tried delivering email.'})),
|
||||
dom.th('Dispositions', attr({title: 'Unique dispositions occurring in report.'})),
|
||||
dom.th('Evaluations', attr({title: 'Total number of message delivery attempts, including retries.'})),
|
||||
dom.th('Send report', attr({title: 'Whether the current evaluations will cause a report to be sent.'})),
|
||||
),
|
||||
|
@ -1120,6 +1121,7 @@ const dmarcEvaluations = async () => {
|
|||
Object.entries(evalStats).sort((a, b) => a[0] < b[0] ? -1 : 1).map(t =>
|
||||
dom.tr(
|
||||
dom.td(dom.a(attr({href: '#dmarc/evaluations/'+domainName(t[1].Domain)}), domainString(t[1].Domain))),
|
||||
dom.td((t[1].Dispositions || []).join(' ')),
|
||||
dom.td(style({textAlign: 'right'}), ''+t[1].Count),
|
||||
dom.td(style({textAlign: 'right'}), t[1].SendReport ? '✓' : ''),
|
||||
),
|
||||
|
|
|
@ -3798,6 +3798,21 @@
|
|||
"Name": "EvaluationStat",
|
||||
"Docs": "EvaluationStat summarizes stored evaluations, for inclusion in an upcoming\naggregate report, for a domain.",
|
||||
"Fields": [
|
||||
{
|
||||
"Name": "Domain",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"Domain"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "Dispositions",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"[]",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "Count",
|
||||
"Docs": "",
|
||||
|
@ -3811,13 +3826,6 @@
|
|||
"Typewords": [
|
||||
"bool"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "Domain",
|
||||
"Docs": "",
|
||||
"Typewords": [
|
||||
"Domain"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue