Fix DMARC guidance for send-only relays with optional rua= settings.
test / test (push) Has been cancelled
test / test (push) Has been cancelled
The panel now suggests policy-only DMARC by default, lets operators configure a default and per-domain report address, and DNS-checks hub _report._dmarc records. Future in-panel report ingestion is tracked as dmarc-reports in the roadmap. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/mixeme/selfpost/internal/buildinfo"
|
||||
@@ -23,6 +24,7 @@ type DomainExport struct {
|
||||
Domain string `json:"domain"`
|
||||
DKIMSelector string `json:"dkim_selector"`
|
||||
DKIMPrivateKey string `json:"dkim_private_key"` // PKCS#1 PEM
|
||||
DMARCRua *string `json:"dmarc_rua,omitempty"` // nil = inherit profile; set = override ("" = none)
|
||||
Applications []AppExport `json:"applications"`
|
||||
}
|
||||
|
||||
@@ -59,6 +61,10 @@ func (s *Service) Export(id int64) (DomainExport, error) {
|
||||
DKIMPrivateKey: string(pem),
|
||||
Applications: make([]AppExport, 0, len(apps)),
|
||||
}
|
||||
if d.DMARCRua.Valid {
|
||||
s := d.DMARCRua.String
|
||||
exp.DMARCRua = &s
|
||||
}
|
||||
for _, a := range apps {
|
||||
password, err := s.apps.Secret(a.Login)
|
||||
if err != nil {
|
||||
@@ -110,6 +116,14 @@ func (s *Service) Import(exp DomainExport) (store.Domain, error) {
|
||||
return store.Domain{}, err
|
||||
}
|
||||
|
||||
if exp.DMARCRua != nil {
|
||||
if err := s.store.UpdateDomainDMARCRua(d.ID, sql.NullString{Valid: true, String: *exp.DMARCRua}); err != nil {
|
||||
s.importRollback(d.ID)
|
||||
return store.Domain{}, err
|
||||
}
|
||||
d.DMARCRua = sql.NullString{Valid: true, String: *exp.DMARCRua}
|
||||
}
|
||||
|
||||
for _, a := range exp.Applications {
|
||||
if err := s.apps.ImportApplication(d.ID, a.Login, a.AddressMode, a.Addresses, a.Password); err != nil {
|
||||
s.importRollback(d.ID)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
@@ -72,6 +73,9 @@ func TestExportImportRoundTrip(t *testing.T) {
|
||||
if _, err := src.store.AddApplication(d.ID, "alerts", store.AddressModeList, []string{"a@example.com"}); err != nil {
|
||||
t.Fatalf("add alerts: %v", err)
|
||||
}
|
||||
if err := src.store.UpdateDomainDMARCRua(d.ID, sql.NullString{Valid: true, String: "reports@hub.example"}); err != nil {
|
||||
t.Fatalf("set dmarc rua: %v", err)
|
||||
}
|
||||
|
||||
exp, err := src.Export(d.ID)
|
||||
if err != nil {
|
||||
@@ -107,6 +111,12 @@ func TestExportImportRoundTrip(t *testing.T) {
|
||||
if got.Name != "example.com" || got.DKIMSelector != "selfpost" {
|
||||
t.Errorf("imported domain = %+v", got)
|
||||
}
|
||||
if !got.DMARCRua.Valid || got.DMARCRua.String != "reports@hub.example" {
|
||||
t.Errorf("imported dmarc rua = %+v", got.DMARCRua)
|
||||
}
|
||||
if exp.DMARCRua == nil || *exp.DMARCRua != "reports@hub.example" {
|
||||
t.Errorf("exported dmarc rua = %v", exp.DMARCRua)
|
||||
}
|
||||
// The DKIM key was imported byte-for-byte, so the DNS record is unchanged.
|
||||
dstKey, err := dstOdk.ExportKey("example.com", "selfpost")
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user