package mail import ( "strings" "testing" "github.com/carlosframework/platform/internal/dnsrec" ) // The MAIL FROM subdomain carries its region from the FIRST domain ever // verified. For a custom domain this record lives in the CUSTOMER's zone, // so it is the one thing we cannot republish for them — and the MX target // is region-specific, so an unqualified "mail." could never hold a second // region without ambiguity (spec §7, §8). func TestMailFromDomainCarriesTheRegion(t *testing.T) { got := MailFromDomain("harbourmail.bag.oncarlos.com", "eu-west-1") want := "mail-eu-west-1.harbourmail.bag.oncarlos.com" if got != want { t.Fatalf("MailFromDomain = %q, want %q", got, want) } if MailFromDomain("x.com", "eu-west-1") == MailFromDomain("x.com", "us-east-1") { t.Fatal("two regions collided on one MAIL FROM subdomain") } } // Nothing is EVER written at the app host itself. The edge owns an A record // there, and an email record sharing that name could fight it — this is a // permanent invariant, not an implementation detail (spec §7). func TestNoRecordSitsAtTheDomainApex(t *testing.T) { const domain = "harbourmail.bag.oncarlos.com" for _, r := range RecordSet(domain, "eu-west-1", []string{"t1", "t2", "t3"}, "") { if r.Name == domain { t.Fatalf("record %s %s sits at the apex — it would fight the edge's A record", r.Type, r.Name) } } } func TestRecordSetGolden(t *testing.T) { got := RecordSet("harbourmail.bag.oncarlos.com", "eu-west-1", []string{"tok1", "tok2", "tok3"}, "") want := []dnsrec.Record{ {Name: "tok1._domainkey.harbourmail.bag.oncarlos.com", Type: dnsrec.TypeCNAME, Values: []string{"tok1.dkim.amazonses.com"}, TTL: 300}, {Name: "tok2._domainkey.harbourmail.bag.oncarlos.com", Type: dnsrec.TypeCNAME, Values: []string{"tok2.dkim.amazonses.com"}, TTL: 300}, {Name: "tok3._domainkey.harbourmail.bag.oncarlos.com", Type: dnsrec.TypeCNAME, Values: []string{"tok3.dkim.amazonses.com"}, TTL: 300}, {Name: "mail-eu-west-1.harbourmail.bag.oncarlos.com", Type: dnsrec.TypeMX, Values: []string{"10 feedback-smtp.eu-west-1.amazonses.com"}, TTL: 300}, {Name: "mail-eu-west-1.harbourmail.bag.oncarlos.com", Type: dnsrec.TypeTXT, Values: []string{"v=spf1 include:amazonses.com ~all"}, TTL: 300}, {Name: "_dmarc.harbourmail.bag.oncarlos.com", Type: dnsrec.TypeTXT, Values: []string{"v=DMARC1; p=none; adkim=s; aspf=s"}, TTL: 300}, } if len(got) != len(want) { t.Fatalf("got %d records, want %d:\n%+v", len(got), len(want), got) } for i := range want { if got[i].Name != want[i].Name || got[i].Type != want[i].Type || got[i].TTL != want[i].TTL || len(got[i].Values) != len(want[i].Values) || got[i].Values[0] != want[i].Values[0] { t.Fatalf("record %d:\n got %+v\nwant %+v", i, got[i], want[i]) } } } // adkim=s is the TENANT BOUNDARY on a shared registrable domain, not // hygiene. DMARC's default relaxed alignment compares ORGANIZATIONAL // domains, so without it tenant bag's DKIM signature authenticates a From // address at bae.oncarlos.com (spec §7). func TestDMARCIsStrictlyAligned(t *testing.T) { var dmarc string for _, r := range RecordSet("x.bag.oncarlos.com", "eu-west-1", []string{"t"}, "") { if r.Name == "_dmarc.x.bag.oncarlos.com" { dmarc = r.Values[0] } } if dmarc == "" { t.Fatal("no _dmarc record emitted") } for _, want := range []string{"adkim=s", "aspf=s"} { if !contains(dmarc, want) { t.Fatalf("DMARC %q is missing %q — tenants are not isolated", dmarc, want) } } } // rua is CONFIGURATION. Unset means publish no rua at all: a reporting // address is only honoured by receivers when the destination authorises it // (RFC 7489 §7.1), so emitting one by default would publish a record that // looks right and yields nothing. func TestRUAIsOmittedWhenUnset(t *testing.T) { for _, r := range RecordSet("x.com", "eu-west-1", []string{"t"}, "") { if r.Name == "_dmarc.x.com" && contains(r.Values[0], "rua=") { t.Fatalf("unset rua still emitted: %q", r.Values[0]) } } for _, r := range RecordSet("x.com", "eu-west-1", []string{"t"}, "reports@cribado.report") { if r.Name == "_dmarc.x.com" { if !contains(r.Values[0], "rua=mailto:reports@cribado.report") { t.Fatalf("rua not rendered: %q", r.Values[0]) } } } } func contains(h, n string) bool { return len(n) > 0 && len(h) >= len(n) && strings.Contains(h, n) }