///|
pub(all) enum Severity {
Pass
Warn
Fail
} derive(Eq, Debug)
///|
pub(all) struct PolicyFinding {
id : String
severity : Severity
title : String
detail : String
evidence : String
repair : String
penalty : Int
} derive(Eq, Debug)
///|
pub(all) struct SpfMechanism {
raw : String
qualifier : String
name : String
value : String
dns_lookup : Bool
terminal : Bool
} derive(Eq, Debug)
///|
pub(all) struct SpfRecord {
raw : String
valid_version : Bool
mechanisms : Array[SpfMechanism]
redirect : String
explanation : String
dns_lookup_count : Int
all_qualifier : String
findings : Array[PolicyFinding]
} derive(Eq, Debug)
///|
pub(all) struct DmarcRecord {
raw : String
valid_version : Bool
policy : String
subdomain_policy : String
pct : Int
rua_count : Int
ruf_count : Int
alignment_spf : String
alignment_dkim : String
findings : Array[PolicyFinding]
} derive(Eq, Debug)
///|
pub(all) struct MailPolicyReport {
domain : String
spf : SpfRecord
dmarc : DmarcRecord
score : Int
verdict : String
findings : Array[PolicyFinding]
} derive(Eq, Debug)
///|
pub(all) struct ReportSummary {
pass_count : Int
warn_count : Int
fail_count : Int
total_count : Int
} derive(Eq, Debug)
///|
pub(all) struct ActionItem {
id : String
module_name : String
title : String
priority : Int
detail : String
next_step : String
} derive(Eq, Debug)
///|
pub(all) struct DkimRecord {
raw : String
valid_version : Bool
key_type : String
key_length_hint : Int
public_key_length : Int
testing_mode : Bool
service_count : Int
hash_count : Int
notes : String
findings : Array[PolicyFinding]
} derive(Eq, Debug)
///|
pub(all) struct MtastsRecord {
raw : String
valid_version : Bool
version : String
mode : String
max_age : Int
id : String
mx_count : Int
mx_hosts : Array[String]
findings : Array[PolicyFinding]
} derive(Eq, Debug)
///|
pub(all) struct TlsRptRecord {
raw : String
valid_version : Bool
version : String
rua_count : Int
mailto_count : Int
https_count : Int
findings : Array[PolicyFinding]
} derive(Eq, Debug)
///|
pub(all) struct BimiRecord {
raw : String
valid_version : Bool
version : String
logo_url : String
authority_url : String
logo_svg : Bool
findings : Array[PolicyFinding]
} derive(Eq, Debug)
///|
pub(all) struct MailSecuritySuiteReport {
domain : String
spf : SpfRecord
dmarc : DmarcRecord
dkim : DkimRecord
mtasts : MtastsRecord
tlsrpt : TlsRptRecord
bimi : BimiRecord
score : Int
verdict : String
summary : ReportSummary
actions : Array[ActionItem]
findings : Array[PolicyFinding]
} derive(Eq, Debug)
///|
pub(all) struct MailSecuritySuiteInput {
domain : String
spf_text : String
dmarc_text : String
dkim_text : String
mtasts_text : String
tlsrpt_text : String
bimi_text : String
} derive(Eq, Debug)
///|
pub(all) struct BatchSecurityReport {
reports : Array[MailSecuritySuiteReport]
domains_checked : Int
average_score : Int
lowest_score : Int
highest_score : Int
summary : ReportSummary
actions : Array[ActionItem]
findings : Array[PolicyFinding]
} derive(Eq, Debug)
///|
pub(all) struct MailSecurityProfile {
name : String
minimum_score : Int
require_spf_hardfail : Bool
require_dmarc_enforcement : Bool
require_dkim : Bool
require_mtasts : Bool
require_tlsrpt : Bool
require_bimi : Bool
allow_testing_modes : Bool
} derive(Eq, Debug)
///|
pub(all) struct ProfileAssessment {
profile_name : String
passed : Bool
score : Int
missing_count : Int
failed_requirements : Array[String]
findings : Array[PolicyFinding]
} derive(Eq, Debug)
///|
fn finding(
id : String,
severity : Severity,
title : String,
detail : String,
evidence : String,
repair : String,
penalty : Int,
) -> PolicyFinding {
{ id, severity, title, detail, evidence, repair, penalty }
}
///|
fn pass(id : String, title : String, evidence : String) -> PolicyFinding {
finding(id, Pass, title, "Requirement satisfied.", evidence, "", 0)
}
///|
fn warn(
id : String,
title : String,
detail : String,
evidence : String,
repair : String,
penalty? : Int = 6,
) -> PolicyFinding {
finding(id, Warn, title, detail, evidence, repair, penalty)
}
///|
fn fail(
id : String,
title : String,
detail : String,
evidence : String,
repair : String,
penalty? : Int = 18,
) -> PolicyFinding {
finding(id, Fail, title, detail, evidence, repair, penalty)
}
///|
pub fn ReportSummary::has_failures(self : ReportSummary) -> Bool {
self.fail_count > 0
}
///|
pub fn ReportSummary::has_warnings(self : ReportSummary) -> Bool {
self.warn_count > 0
}
///|
pub fn ReportSummary::is_clean(self : ReportSummary) -> Bool {
self.fail_count == 0 && self.warn_count == 0
}
///|
pub fn ReportSummary::to_short_text(self : ReportSummary) -> String {
"pass=" +
self.pass_count.to_string() +
" warn=" +
self.warn_count.to_string() +
" fail=" +
self.fail_count.to_string()
}
///|
pub fn ActionItem::to_markdown(self : ActionItem) -> String {
let out = StringBuilder()
out.write_string("- [")
out.write_string(self.module_name)
out.write_string("] ")
out.write_string(self.id)
out.write_string(": ")
out.write_string(self.title)
out.write_string(" | priority=")
out.write_string(self.priority.to_string())
if !self.detail.is_empty() {
out.write_string(" | ")
out.write_string(self.detail)
}
if !self.next_step.is_empty() {
out.write_string(" | next: ")
out.write_string(self.next_step)
}
out.to_string()
}