Compare commits

...

2 commits

Author SHA1 Message Date
16b7dcb057 Incorporate DNSWL (whitelist) grade into blacklist scoring
All checks were successful
continuous-integration/drone/push Build is passing
CalculateScore now accepts a forWhitelist flag to handle whitelist
scoring logic separately. The final blacklist grade combines both
RBL and DNSWL results using MinGrade for a more accurate reputation
assessment.
2026-03-26 10:36:27 +07:00
dfa38e8a26 Fix RBL score: return A+ when not listed on any blocklist
Move the ListedCount check before scoringListCount calculation so we
return early with a perfect score when the IP/domain is not listed,
regardless of how many informational-only lists exist.
2026-03-26 10:36:25 +07:00
4 changed files with 21 additions and 6 deletions

View file

@ -138,7 +138,7 @@ func (a *APIAdapter) CheckBlacklistIP(ip string) ([]api.BlacklistCheck, []api.Bl
IPsChecked: []string{ip}, IPsChecked: []string{ip},
ListedCount: listedCount, ListedCount: listedCount,
} }
score, grade := a.analyzer.generator.rblChecker.CalculateScore(results) score, grade := a.analyzer.generator.rblChecker.CalculateScore(results, false)
// Check the IP against all configured DNSWLs (informational only) // Check the IP against all configured DNSWLs (informational only)
whitelists, _, err := a.analyzer.generator.dnswlChecker.CheckIP(ip) whitelists, _, err := a.analyzer.generator.dnswlChecker.CheckIP(ip)

View file

@ -300,13 +300,24 @@ func (r *DNSListChecker) reverseIP(ipStr string) string {
// CalculateScore calculates the list contribution to deliverability. // CalculateScore calculates the list contribution to deliverability.
// Informational lists are not counted in the score. // Informational lists are not counted in the score.
func (r *DNSListChecker) CalculateScore(results *DNSListResults) (int, string) { func (r *DNSListChecker) CalculateScore(results *DNSListResults, forWhitelist bool) (int, string) {
scoringListCount := len(r.Lists) - len(r.informationalSet)
if forWhitelist {
if results.ListedCount >= scoringListCount {
return 100, "A++"
} else if results.ListedCount > 0 {
return 100, "A+"
} else {
return 95, "A"
}
}
if results == nil || len(results.IPsChecked) == 0 { if results == nil || len(results.IPsChecked) == 0 {
return 100, "" return 100, ""
} }
scoringListCount := len(r.Lists) - len(r.informationalSet) if results.ListedCount <= 0 {
if scoringListCount <= 0 {
return 100, "A+" return 100, "A+"
} }

View file

@ -141,8 +141,10 @@ func (r *ReportGenerator) GenerateReport(testID uuid.UUID, results *AnalysisResu
blacklistScore := 0 blacklistScore := 0
var blacklistGrade string var blacklistGrade string
var whitelistGrade string
if results.RBL != nil { if results.RBL != nil {
blacklistScore, blacklistGrade = r.rblChecker.CalculateScore(results.RBL) blacklistScore, blacklistGrade = r.rblChecker.CalculateScore(results.RBL, false)
_, whitelistGrade = r.dnswlChecker.CalculateScore(results.DNSWL, true)
} }
saScore, saGrade := r.spamAnalyzer.CalculateSpamAssassinScore(results.SpamAssassin) saScore, saGrade := r.spamAnalyzer.CalculateSpamAssassinScore(results.SpamAssassin)
@ -173,7 +175,7 @@ func (r *ReportGenerator) GenerateReport(testID uuid.UUID, results *AnalysisResu
AuthenticationScore: authScore, AuthenticationScore: authScore,
AuthenticationGrade: api.ScoreSummaryAuthenticationGrade(authGrade), AuthenticationGrade: api.ScoreSummaryAuthenticationGrade(authGrade),
BlacklistScore: blacklistScore, BlacklistScore: blacklistScore,
BlacklistGrade: api.ScoreSummaryBlacklistGrade(blacklistGrade), BlacklistGrade: api.ScoreSummaryBlacklistGrade(MinGrade(blacklistGrade, whitelistGrade)),
ContentScore: contentScore, ContentScore: contentScore,
ContentGrade: api.ScoreSummaryContentGrade(contentGrade), ContentGrade: api.ScoreSummaryContentGrade(contentGrade),
HeaderScore: headerScore, HeaderScore: headerScore,

View file

@ -73,6 +73,8 @@ func ScoreToReportGrade(score int) api.ReportGrade {
// gradeRank returns a numeric rank for a grade (lower = worse) // gradeRank returns a numeric rank for a grade (lower = worse)
func gradeRank(grade string) int { func gradeRank(grade string) int {
switch grade { switch grade {
case "A++":
return 7
case "A+": case "A+":
return 6 return 6
case "A": case "A":