1package dmarc_test
2
3import (
4 "context"
5 "log"
6 "log/slog"
7 "net"
8 "strings"
9
10 "github.com/mjl-/mox/dkim"
11 "github.com/mjl-/mox/dmarc"
12 "github.com/mjl-/mox/dns"
13 "github.com/mjl-/mox/message"
14 "github.com/mjl-/mox/spf"
15)
16
17func ExampleLookup() {
18 ctx := context.Background()
19 resolver := dns.StrictResolver{}
20 msgFrom, err := dns.ParseDomain("sub.example.com")
21 if err != nil {
22 log.Fatalf("parsing from domain: %v", err)
23 }
24
25 // Lookup DMARC DNS record for domain.
26 status, domain, record, txt, authentic, err := dmarc.Lookup(ctx, slog.Default(), resolver, msgFrom)
27 if err != nil {
28 log.Fatalf("dmarc lookup: %v", err)
29 }
30
31 log.Printf("status %s, domain %s, record %v, txt %q, dnssec %v", status, domain, record, txt, authentic)
32}
33
34func ExampleVerify() {
35 ctx := context.Background()
36 resolver := dns.StrictResolver{}
37
38 // Message to verify.
39 msg := strings.NewReader("From: <sender@example.com>\r\nMore: headers\r\n\r\nBody\r\n")
40 msgFrom, _, _, err := message.From(slog.Default(), true, msg, nil)
41 if err != nil {
42 log.Fatalf("parsing message for from header: %v", err)
43 }
44
45 // Verify SPF, for use with DMARC.
46 args := spf.Args{
47 RemoteIP: net.ParseIP("10.11.12.13"),
48 MailFromDomain: dns.Domain{ASCII: "sub.example.com"},
49 }
50 spfReceived, spfDomain, _, _, err := spf.Verify(ctx, slog.Default(), resolver, args)
51 if err != nil {
52 log.Printf("verifying spf: %v", err)
53 }
54
55 // Verify DKIM-Signature headers, for use with DMARC.
56 smtputf8 := false
57 ignoreTestMode := false
58 dkimResults, err := dkim.Verify(ctx, slog.Default(), resolver, smtputf8, dkim.DefaultPolicy, msg, ignoreTestMode)
59 if err != nil {
60 log.Printf("verifying dkim: %v", err)
61 }
62
63 // Verify DMARC, based on DKIM and SPF results.
64 applyRandomPercentage := true
65 useResult, result := dmarc.Verify(ctx, slog.Default(), resolver, msgFrom.Domain, dkimResults, spfReceived.Result, &spfDomain, applyRandomPercentage)
66
67 // Print results.
68 log.Printf("dmarc status: %s", result.Status)
69 log.Printf("use result: %v", useResult)
70 if useResult && result.Reject {
71 log.Printf("should reject message")
72 }
73 log.Printf("result: %#v", result)
74}
75
76func ExampleParseRecord() {
77 txt := "v=DMARC1; p=reject; rua=mailto:postmaster@mox.example"
78
79 record, isdmarc, err := dmarc.ParseRecord(txt)
80 if err != nil {
81 log.Fatalf("parsing dmarc record: %v (isdmarc: %v)", err, isdmarc)
82 }
83
84 log.Printf("parsed record: %v", record)
85}
86