// 公共类型模型。
//
// 判定不是布尔值,而是「状态 + 证据 + 原因」三件套:
// 每一层都把自己看到的证据留下来,调用方可以解释任何一个结论。
///|
/// 认证状态。对应 RFC 8601 的 result 取值。
pub enum AuthStatus {
Pass
Fail
SoftFail
None_
Neutral
TempError
PermError
} derive(Eq)
///|
/// 一条判定证据。
pub struct Evidence {
/// 证据来源:`dkim` / `spf` / `dmarc`
kind : String
/// 人类可读的证据标签
label : String
/// 具体细节,例如命中的标签、规范化后的字节数
detail : String
}
///|
/// 单条 DKIM 签名的验签结果。
pub struct DkimResult {
domain : String
selector : String
algorithm : String
status : AuthStatus
reason : String
evidence : Array[Evidence]
}
///|
/// SPF 求值结果。
pub struct SpfResult {
domain : String
identity : String
status : AuthStatus
/// 命中的 qualifier:`+` `-` `~` `?`
qualifier : String
/// 命中的机制,例如 `include:_spf.example.com`
mechanism : String
reason : String
dns_lookups : Int
void_lookups : Int
}
///|
/// DMARC 对齐与策略结果。
pub struct DmarcResult {
domain : String
policy : String
disposition : String
dkim_aligned : Bool
spf_aligned : Bool
status : AuthStatus
reason : String
}
///|
/// 一封邮件的完整认证结果。
pub struct AuthReport {
dkim : Array[DkimResult]
spf : SpfResult?
dmarc : DmarcResult?
}
///|
/// 判定状态的短名称,用于渲染。
pub fn AuthStatus::label(self : AuthStatus) -> String {
match self {
Pass => "pass"
Fail => "fail"
SoftFail => "softfail"
None_ => "none"
Neutral => "neutral"
TempError => "temperror"
PermError => "permerror"
}
}