Improve headers reporting
This commit is contained in:
parent
e77bffb04f
commit
41013d8af2
2 changed files with 44 additions and 7 deletions
|
|
@ -63,7 +63,13 @@ func (h *HeaderAnalyzer) CalculateHeaderScore(analysis *api.HeaderAnalysis) int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check recommended headers (30 points)
|
// Check recommended headers (30 points)
|
||||||
recommendedHeaders := []string{"subject", "to", "reply-to"}
|
recommendedHeaders := []string{"subject", "to"}
|
||||||
|
|
||||||
|
// Add reply-to when from is a no-reply address
|
||||||
|
if h.isNoReplyAddress(headers["from"]) {
|
||||||
|
recommendedHeaders = append(recommendedHeaders, "reply-to")
|
||||||
|
}
|
||||||
|
|
||||||
recommendedCount := len(recommendedHeaders)
|
recommendedCount := len(recommendedHeaders)
|
||||||
presentRecommended := 0
|
presentRecommended := 0
|
||||||
|
|
||||||
|
|
@ -72,7 +78,7 @@ func (h *HeaderAnalyzer) CalculateHeaderScore(analysis *api.HeaderAnalysis) int
|
||||||
presentRecommended++
|
presentRecommended++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
score += int(30 * (float32(presentRecommended) / float32(recommendedCount)))
|
score += presentRecommended * 30 / recommendedCount
|
||||||
|
|
||||||
// Check for proper MIME structure (20 points)
|
// Check for proper MIME structure (20 points)
|
||||||
if analysis.HasMimeStructure != nil && *analysis.HasMimeStructure {
|
if analysis.HasMimeStructure != nil && *analysis.HasMimeStructure {
|
||||||
|
|
@ -120,6 +126,29 @@ func (h *HeaderAnalyzer) isValidMessageID(messageID string) bool {
|
||||||
return len(parts[0]) > 0 && len(parts[1]) > 0
|
return len(parts[0]) > 0 && len(parts[1]) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isNoReplyAddress checks if a header check represents a no-reply email address
|
||||||
|
func (h *HeaderAnalyzer) isNoReplyAddress(headerCheck api.HeaderCheck) bool {
|
||||||
|
if !headerCheck.Present || headerCheck.Value == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
value := strings.ToLower(*headerCheck.Value)
|
||||||
|
noReplyPatterns := []string{
|
||||||
|
"no-reply",
|
||||||
|
"noreply",
|
||||||
|
"ne-pas-repondre",
|
||||||
|
"nepasrepondre",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pattern := range noReplyPatterns {
|
||||||
|
if strings.Contains(value, pattern) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// GenerateHeaderAnalysis creates structured header analysis from email
|
// GenerateHeaderAnalysis creates structured header analysis from email
|
||||||
func (h *HeaderAnalyzer) GenerateHeaderAnalysis(email *EmailMessage) *api.HeaderAnalysis {
|
func (h *HeaderAnalyzer) GenerateHeaderAnalysis(email *EmailMessage) *api.HeaderAnalysis {
|
||||||
if email == nil {
|
if email == nil {
|
||||||
|
|
@ -142,16 +171,19 @@ func (h *HeaderAnalyzer) GenerateHeaderAnalysis(email *EmailMessage) *api.Header
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check recommended headers
|
// Check recommended headers
|
||||||
recommendedHeaders := []string{"Reply-To", "Return-Path"}
|
recommendedHeaders := []string{}
|
||||||
|
if h.isNoReplyAddress(headers["from"]) {
|
||||||
|
recommendedHeaders = append(recommendedHeaders, "reply-to")
|
||||||
|
}
|
||||||
for _, headerName := range recommendedHeaders {
|
for _, headerName := range recommendedHeaders {
|
||||||
check := h.checkHeader(email, headerName, "recommended")
|
check := h.checkHeader(email, headerName, "recommended")
|
||||||
headers[strings.ToLower(headerName)] = *check
|
headers[strings.ToLower(headerName)] = *check
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check optional headers
|
// Check optional headers
|
||||||
optionalHeaders := []string{"List-Unsubscribe", "List-Unsubscribe-Post", "Precedence"}
|
optionalHeaders := []string{"List-Unsubscribe", "List-Unsubscribe-Post"}
|
||||||
for _, headerName := range optionalHeaders {
|
for _, headerName := range optionalHeaders {
|
||||||
check := h.checkHeader(email, headerName, "optional")
|
check := h.checkHeader(email, headerName, "newsletter")
|
||||||
headers[strings.ToLower(headerName)] = *check
|
headers[strings.ToLower(headerName)] = *check
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,12 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each Object.entries(headerAnalysis.headers) as [name, check]}
|
{#each Object.entries(headerAnalysis.headers).sort((a, b) => {
|
||||||
|
const importanceOrder = { 'required': 0, 'recommended': 1, 'optional': 2, 'newsletter': 3 };
|
||||||
|
const aImportance = importanceOrder[a[1].importance || 'optional'];
|
||||||
|
const bImportance = importanceOrder[b[1].importance || 'optional'];
|
||||||
|
return aImportance - bImportance;
|
||||||
|
}) as [name, check]}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<code>{name}</code>
|
<code>{name}</code>
|
||||||
|
|
@ -112,7 +117,7 @@
|
||||||
<i class="bi {check.present ? 'bi-check-circle text-success' : 'bi-x-circle text-danger'}"></i>
|
<i class="bi {check.present ? 'bi-check-circle text-success' : 'bi-x-circle text-danger'}"></i>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{#if check.valid !== undefined}
|
{#if check.present && check.valid !== undefined}
|
||||||
<i class="bi {check.valid ? 'bi-check-circle text-success' : 'bi-x-circle text-warning'}"></i>
|
<i class="bi {check.valid ? 'bi-check-circle text-success' : 'bi-x-circle text-warning'}"></i>
|
||||||
{:else}
|
{:else}
|
||||||
-
|
-
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue