Create basic form for SPF record

This commit is contained in:
nemunaire 2023-12-11 18:53:17 +01:00
parent df76dd5476
commit ead38fdf76
4 changed files with 51 additions and 42 deletions

View File

@ -37,7 +37,6 @@ import (
"strings"
"github.com/StackExchange/dnscontrol/v4/models"
"github.com/StackExchange/dnscontrol/v4/pkg/spflib"
"github.com/miekg/dns"
"git.happydns.org/happyDomain/model"
@ -198,27 +197,14 @@ func email_analyze(a *svcs.Analyzer) (err error) {
// Is there SPF record?
for _, record := range a.SearchRR(svcs.AnalyzerRecordFilter{Type: dns.TypeTXT, Domain: domain, Contains: "v=spf1"}) {
if record.Type == "TXT" || record.Type == "SPF" {
_, err := spflib.Parse(record.GetTargetTXTJoined(), nil)
if err != nil {
continue
}
if service.SPF == nil {
service.SPF = &svcs.SPF{}
}
fields := strings.Fields(service.SPF.Content + " " + strings.TrimPrefix(strings.TrimSpace(record.GetTargetTXTJoined()), "v=spf1"))
for i := 0; i < len(fields); i += 1 {
for j := i + 1; j < len(fields); j += 1 {
if fields[i] == fields[j] {
fields = append(fields[:j], fields[j+1:]...)
j -= 1
}
}
err = service.SPF.Analyze(record.GetTargetTXTJoined())
if err != nil {
return
}
service.SPF.Content = strings.Join(fields, " ")
}
err = a.UseRR(record, domain, service)

View File

@ -56,7 +56,7 @@ func (s *GSuite) GenKnownSvcs() []happydns.Service {
svcs.MX{Target: "alt4.aspmx.l.google.com.", Preference: 10},
},
SPF: &svcs.SPF{
Content: "include:_spf.google.com ~all",
Directives: []string{"include:_spf.google.com", "~all"},
},
}

View File

@ -32,35 +32,46 @@
package svcs
import (
"fmt"
"strings"
"github.com/StackExchange/dnscontrol/v4/pkg/spflib"
)
type SPFDirective struct {
Qualifier byte
Mechanism string
}
type SPFModifier struct {
Name string
Mechanism string
}
type SPFExplanation struct {
DomainSpec string
}
type SPFRedirect struct {
DomainSpec string
}
type SPF struct {
Content string
Version uint `json:"version" happydomain:"label=Version,placeholder=1,required,description=The version of SPF to use.,default=1,hidden"`
Directives []string `json:"directives" happydomain:"label=Directives,placeholder=ip4:203.0.113.12"`
}
func (t *SPF) Analyze(txt string) error {
_, err := spflib.Parse(txt, nil)
if err != nil {
return err
}
t.Version = 1
fields := strings.Fields(txt)
// Avoid doublon
for _, directive := range fields[1:] {
exists := false
for _, known := range t.Directives {
if known == directive {
exists = true
break
}
}
if !exists {
t.Directives = append(t.Directives, directive)
}
}
return nil
}
func (t *SPF) String() string {
var ret = t.Content
if !strings.HasPrefix(ret, "v=spf1") {
ret = "v=spf1 " + ret
}
return ret
directives := append([]string{fmt.Sprintf("v=spf%d", t.Version)}, t.Directives...)
return strings.Join(directives, " ")
}

View File

@ -76,6 +76,18 @@ func migrateFrom5_analyseEMailSvc(s *LevelDBStorage) (err error) {
for dn, zServices := range zone.Services {
for ksvc, svc := range zServices {
if svc.Type == "abstract.EMail" {
// SPF
if oldspf, ok := svc.Service["spf"].(map[string]interface{}); ok {
if content, ok := oldspf["Content"]; ok {
if cnt, ok := content.(string); ok {
newspf := &svcs.SPF{}
newspf.Analyze("v=spf1 " + cnt)
zone.Services[dn][ksvc].Service["spf"] = newspf
changed = true
}
}
}
// DKIM
newdkim := map[string]*svcs.DKIM{}