Merge branch 'feature/mail-deliverability'

This commit is contained in:
Veillax committed 2026-10-27 17:07:49 -06:00
commit e81c0fe7e2
3 files changed
+483

No files matched your search

+52
View File
@@ -242,6 +242,58 @@ type MailCheck struct {
HeloResolves bool `json:"heloResolves"` // the HELO name resolves back to the source IP
Port25 string `json:"port25"` // "open" or why not
DKIM map[string]string `json:"dkim"` // key ID -> "published", "missing" or "mismatch"
Domains map[string]DomainCheck `json:"domains,omitempty"` // sending domain -> its DNS checks
Blocklists []string `json:"blocklists,omitempty"` // DNS blocklists that list the source IP
Listable int `json:"listable,omitempty"` // how many blocklists answered, so "none listed" means something
Outcomes *MailOutcomes `json:"outcomes,omitempty"` // what happened to the mail this egress sent
}
// Finding statuses.
const (
FindingPass = "pass"
FindingWarn = "warn"
FindingFail = "fail"
FindingNone = "none" // nothing published
)
// MailFinding is the result of one deliverability check, with what to do about it.
type MailFinding struct {
Status string `json:"status"`
Detail string `json:"detail"`
Hint string `json:"hint,omitempty"`
}
// DomainCheck is how the DNS of one sending domain looks to a receiving server.
type DomainCheck struct {
SPF MailFinding `json:"spf"`
DMARC MailFinding `json:"dmarc"`
MTASTS MailFinding `json:"mtaSts"`
}
// MailOutcomes counts what became of the mail an egress handled over a window.
type MailOutcomes struct {
Since time.Time `json:"since"`
Delivered int `json:"delivered"`
Deferred int `json:"deferred"` // 4xx: the receiver asked us to try later
Failed int `json:"failed"` // 5xx: refused for good
ByDomain map[string]OutcomeCount `json:"byDomain,omitempty"` // recipient domain
Recent []OutcomeFailure `json:"recent,omitempty"` // latest problems, newest first
}
// OutcomeCount is delivered/deferred/failed for one recipient domain.
type OutcomeCount struct {
Delivered int `json:"delivered"`
Deferred int `json:"deferred"`
Failed int `json:"failed"`
}
// OutcomeFailure is one deferral or refusal, for the dashboard to explain.
type OutcomeFailure struct {
Time time.Time `json:"time"`
Domain string `json:"domain"`
Code int `json:"code"`
Text string `json:"text"`
}
// ---------- edge <-> hammerhead ----------