"Fossies" - the Fresh Open Source Software Archive

Member "libspf2-1.2.10/perl/t/rfc4408-tests.yml" (28 Jan 2012, 64866 Bytes) of package /linux/privat/libspf2-1.2.10.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Ansible YAML source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 # This is the openspf.org test suite (release 2008.08) based on RFC 4408.
    2 # http://www.openspf.org/Test_Suite
    3 #
    4 # $Id: rfc4408-tests.yml 50 2008-08-17 21:28:15Z Julian Mehnle $
    5 # vim:sw=2 sts=2 et
    6 #
    7 # See rfc4408-tests.CHANGES for a changelog.
    8 #
    9 # Contributors:
   10 #   Stuart D Gathman    90% of the tests
   11 #   Julian Mehnle       some tests, proofread YAML syntax, formal schema
   12 #   Frank Ellermann
   13 #   Scott Kitterman
   14 #   Wayne Schlitt
   15 #   Craig Whitmore
   16 #   Norman Maurer
   17 #   Mark Shewmaker
   18 #   Philip Gladstone
   19 #
   20 ---
   21 description: Initial processing
   22 tests:
   23   toolonglabel:
   24     description: >-
   25       DNS labels limited to 63 chars.
   26     comment: >-
   27       For initial processing, a long label results in None, not TempError
   28     spec: 4.3/1
   29     helo: mail.example.net
   30     host: 1.2.3.5
   31     mailfrom: lyme.eater@A123456789012345678901234567890123456789012345678901234567890123.example.com
   32     result: none
   33   longlabel:
   34     description: >-
   35       DNS labels limited to 63 chars.
   36     spec: 4.3/1
   37     helo: mail.example.net
   38     host: 1.2.3.5
   39     mailfrom: lyme.eater@A12345678901234567890123456789012345678901234567890123456789012.example.com
   40     result: fail
   41   emptylabel:
   42     spec: 4.3/1
   43     helo: mail.example.net
   44     host: 1.2.3.5
   45     mailfrom: lyme.eater@A...example.com
   46     result: none
   47   helo-not-fqdn:
   48     spec: 4.3/1
   49     helo: A2345678
   50     host: 1.2.3.5
   51     mailfrom: ""
   52     result: none
   53   helo-domain-literal:
   54     spec: 4.3/1
   55     helo: "[1.2.3.5]"
   56     host: 1.2.3.5
   57     mailfrom: ""
   58     result: none
   59   nolocalpart:
   60     spec: 4.3/2
   61     helo: mail.example.net
   62     host: 1.2.3.4
   63     mailfrom: '@example.net'
   64     result: fail
   65     explanation: postmaster
   66   domain-literal:
   67     spec: 4.3/1
   68     helo: OEMCOMPUTER
   69     host: 1.2.3.5
   70     mailfrom: "foo@[1.2.3.5]"
   71     result: none
   72 zonedata:
   73   example.com:
   74     - TIMEOUT
   75   example.net:
   76     - SPF:  v=spf1 -all exp=exp.example.net
   77   a.example.net:
   78     - SPF:  v=spf1 -all exp=exp.example.net
   79   exp.example.net:
   80     - TXT:  '%{l}'
   81   a12345678901234567890123456789012345678901234567890123456789012.example.com:
   82     - SPF:  v=spf1 -all
   83 ---
   84 description: Record lookup
   85 tests:
   86   both:
   87     spec: 4.4/1
   88     helo: mail.example.net
   89     host: 1.2.3.4
   90     mailfrom: foo@both.example.net
   91     result: fail
   92   txtonly:
   93     description: Result is none if checking SPF records only.
   94     spec: 4.4/1
   95     helo: mail.example.net
   96     host: 1.2.3.4
   97     mailfrom: foo@txtonly.example.net
   98     result: [fail, none]
   99   spfonly:
  100     description: Result is none if checking TXT records only.
  101     spec: 4.4/1
  102     helo: mail.example.net
  103     host: 1.2.3.4
  104     mailfrom: foo@spfonly.example.net
  105     result: [fail, none]
  106   spftimeout:
  107     description: >-
  108       TXT record present, but SPF lookup times out.
  109       Result is temperror if checking SPF records only.
  110     comment: >-
  111       This actually happens for a popular braindead DNS server.
  112     spec: 4.4/1
  113     helo: mail.example.net
  114     host: 1.2.3.4
  115     mailfrom: foo@spftimeout.example.net
  116     result: [fail, temperror]
  117   txttimeout:
  118     description: >-
  119       SPF record present, but TXT lookup times out.
  120       If only TXT records are checked, result is temperror.
  121     spec: 4.4/1
  122     helo: mail.example.net
  123     host: 1.2.3.4
  124     mailfrom: foo@txttimeout.example.net
  125     result: [fail, temperror]
  126   nospftxttimeout:
  127     description: >-
  128       No SPF record present, and TXT lookup times out.
  129       If only TXT records are checked, result is temperror.
  130     comment: >-
  131       Because TXT records is where v=spf1 records will likely be, returning
  132       temperror will try again later.  A timeout due to a braindead server
  133       is unlikely in the case of TXT, as opposed to the newer SPF RR.
  134     spec: 4.4/1
  135     helo: mail.example.net
  136     host: 1.2.3.4
  137     mailfrom: foo@nospftxttimeout.example.net
  138     result: [temperror, none]
  139   alltimeout:
  140     description: Both TXT and SPF queries time out
  141     spec: 4.4/2
  142     helo: mail.example.net
  143     host: 1.2.3.4
  144     mailfrom: foo@alltimeout.example.net
  145     result: temperror
  146 zonedata:
  147   both.example.net:
  148     - TXT:  v=spf1 -all
  149     - SPF:  v=spf1 -all
  150   txtonly.example.net:
  151     - TXT:  v=spf1 -all
  152   spfonly.example.net:
  153     - SPF:  v=spf1 -all
  154     - TXT:  NONE
  155   spftimeout.example.net:
  156     - TXT:  v=spf1 -all
  157     - TIMEOUT
  158   txttimeout.example.net:
  159     - SPF:  v=spf1 -all
  160     - TXT:  NONE
  161     - TIMEOUT
  162   nospftxttimeout.example.net:
  163     - SPF:  "v=spf3 !a:yahoo.com -all"
  164     - TXT:  NONE
  165     - TIMEOUT
  166   alltimeout.example.net:
  167     - TIMEOUT
  168 ---
  169 description: Selecting records
  170 tests:
  171   nospace1:
  172     description: >-
  173       Version must be terminated by space or end of record.  TXT pieces
  174       are joined without intervening spaces.
  175     spec: 4.5/4
  176     helo: mail.example1.com
  177     host: 1.2.3.4
  178     mailfrom: foo@example2.com
  179     result: none
  180   empty:
  181     description: Empty SPF record.
  182     spec: 4.5/4
  183     helo: mail1.example1.com
  184     host: 1.2.3.4
  185     mailfrom: foo@example1.com
  186     result: neutral
  187   nospace2:
  188     spec: 4.5/4
  189     helo: mail.example1.com
  190     host: 1.2.3.4
  191     mailfrom: foo@example3.com
  192     result: pass
  193   spfoverride:
  194     description: >-
  195       SPF records override TXT records.  Older implementation may
  196       check TXT records only.
  197     spec: 4.5/5
  198     helo: mail.example1.com
  199     host: 1.2.3.4
  200     mailfrom: foo@example4.com
  201     result: [pass, fail]
  202   multitxt1:
  203     description: >-
  204       Older implementations will give permerror/unknown because of
  205       the conflicting TXT records.  However, RFC 4408 says the SPF
  206       records overrides them.
  207     spec: 4.5/5
  208     helo: mail.example1.com
  209     host: 1.2.3.4
  210     mailfrom: foo@example5.com
  211     result: [pass, permerror]
  212   multitxt2:
  213     description: >-
  214       Multiple records is a permerror, v=spf1 is case insensitive
  215     spec: 4.5/6
  216     helo: mail.example1.com
  217     host: 1.2.3.4
  218     mailfrom: foo@example6.com
  219     result: permerror
  220   multispf1:
  221     description: >-
  222       Multiple records is a permerror, even when they are identical.
  223       However, this situation cannot be reliably reproduced with live
  224       DNS since cache and resolvers are allowed to combine identical
  225       records.
  226     spec: 4.5/6
  227     helo: mail.example1.com
  228     host: 1.2.3.4
  229     mailfrom: foo@example7.com
  230     result: [permerror, fail]
  231   multispf2:
  232     description: >-
  233       Older implementations ignoring SPF-type records will give pass because
  234       there is a (single) TXT record.  But RFC 4408 requires permerror because
  235       the SPF records override and there are more than one.
  236     spec: 4.5/6
  237     helo: mail.example1.com
  238     host: 1.2.3.4
  239     mailfrom: foo@example8.com
  240     result: [permerror, pass]
  241   nospf:
  242     spec: 4.5/7
  243     helo: mail.example1.com
  244     host: 1.2.3.4
  245     mailfrom: foo@mail.example1.com
  246     result: none
  247   case-insensitive:
  248     description: >-
  249       v=spf1 is case insensitive
  250     spec: 4.5/6
  251     helo: mail.example1.com
  252     host: 1.2.3.4
  253     mailfrom: foo@example9.com
  254     result: softfail
  255 zonedata:
  256   example3.com:
  257     - SPF:  v=spf10
  258     - SPF:  v=spf1 mx
  259     - MX:   [0, mail.example1.com]
  260   example1.com:
  261     - SPF:  v=spf1
  262   example2.com:
  263     - SPF:  ['v=spf1', 'mx']
  264   mail.example1.com:
  265     - A:    1.2.3.4
  266   example4.com:
  267     - SPF:  v=spf1 +all
  268     - TXT:  v=spf1 -all
  269   example5.com:
  270     - SPF:  v=spf1 +all
  271     - TXT:  v=spf1 -all
  272     - TXT:  v=spf1 +all
  273   example6.com:
  274     - TXT:  v=spf1 -all
  275     - TXT:  V=sPf1 +all
  276   example7.com:
  277     - SPF:  v=spf1 -all
  278     - SPF:  v=spf1 -all
  279   example8.com:
  280     - SPF:  V=spf1 -all
  281     - SPF:  v=spf1 -all
  282     - TXT:  v=spf1 +all
  283   example9.com:
  284     - SPF:  v=SpF1 ~all
  285 ---
  286 description: Record evaluation
  287 tests:
  288   detect-errors-anywhere:
  289     description: Any syntax errors anywhere in the record MUST be detected.
  290     spec: 4.6
  291     helo: mail.example.com
  292     host: 1.2.3.4
  293     mailfrom: foo@t1.example.com
  294     result: permerror
  295   modifier-charset-good:
  296     description: name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." )
  297     spec: 4.6.1/2
  298     helo: mail.example.com
  299     host: 1.2.3.4
  300     mailfrom: foo@t2.example.com
  301     result: pass
  302   modifier-charset-bad1:
  303     description: >-
  304       '=' character immediately after the name and before any ":" or "/"
  305     spec: 4.6.1/4
  306     helo: mail.example.com
  307     host: 1.2.3.4
  308     mailfrom: foo@t3.example.com
  309     result: permerror
  310   modifier-charset-bad2:
  311     description: >-
  312       '=' character immediately after the name and before any ":" or "/"
  313     spec: 4.6.1/4
  314     helo: mail.example.com
  315     host: 1.2.3.4
  316     mailfrom: foo@t4.example.com
  317     result: permerror
  318   redirect-after-mechanisms1:
  319     description: >-
  320       The "redirect" modifier has an effect after all the mechanisms.
  321     comment: >-
  322       The redirect in this example would violate processing limits, except
  323       that it is never used because of the all mechanism.
  324     spec: 4.6.3
  325     helo: mail.example.com
  326     host: 1.2.3.4
  327     mailfrom: foo@t5.example.com
  328     result: softfail
  329   redirect-after-mechanisms2:
  330     description: >-
  331       The "redirect" modifier has an effect after all the mechanisms.
  332     spec: 4.6.3
  333     helo: mail.example.com
  334     host: 1.2.3.5
  335     mailfrom: foo@t6.example.com
  336     result: fail
  337   default-result:
  338     description: Default result is neutral.
  339     spec: 4.7/1
  340     helo: mail.example.com
  341     host: 1.2.3.5
  342     mailfrom: foo@t7.example.com
  343     result: neutral
  344   redirect-is-modifier:
  345     description: |-
  346       Invalid mechanism.  Redirect is a modifier.
  347     spec: 4.6.1/4
  348     helo: mail.example.com
  349     host: 1.2.3.4
  350     mailfrom: foo@t8.example.com
  351     result: permerror
  352   invalid-domain:
  353     description: >-
  354       Domain-spec must end in macro-expand or valid toplabel.
  355     spec: 8.1/2
  356     helo: mail.example.com
  357     host: 1.2.3.4
  358     mailfrom: foo@t9.example.com
  359     result: permerror
  360   invalid-domain-empty-label:
  361     description: >-
  362       target-name that is a valid domain-spec per RFC 4408 but an invalid
  363       domain name per RFC 1035 (empty label) must be treated as non-existent.
  364     comment: >-
  365       An empty domain label, i.e. two successive dots, in a mechanism
  366       target-name is valid domain-spec syntax, even though a DNS query cannot
  367       be composed from it.  The spec being unclear about it, this could either
  368       be considered a syntax error, or, by analogy to 4.3/1 and 5/10/3, the
  369       mechanism chould be treated as a no-match.
  370     spec: [4.3/1, 5/10/3]
  371     helo: mail.example.com
  372     host: 1.2.3.4
  373     mailfrom: foo@t10.example.com
  374     result: [permerror, fail]
  375   invalid-domain-long:
  376     description: >-
  377       target-name that is a valid domain-spec per RFC 4408 but an invalid
  378       domain name per RFC 1035 (long label) must be treated as non-existent.
  379     comment: >-
  380       A domain label longer than 63 characters in a mechanism target-name is
  381       valid domain-spec syntax, even though a DNS query cannot be composed
  382       from it.  The spec being unclear about it, this could either be
  383       considered a syntax error, or, by analogy to 4.3/1 and 5/10/3, the
  384       mechanism chould be treated as a no-match.
  385     spec: [4.3/1, 5/10/3]
  386     helo: mail.example.com
  387     host: 1.2.3.4
  388     mailfrom: foo@t11.example.com
  389     result: [permerror,fail]
  390   invalid-domain-long-via-macro:
  391     description: >-
  392       target-name that is a valid domain-spec per RFC 4408 but an invalid
  393       domain name per RFC 1035 (long label) must be treated as non-existent.
  394     comment: >-
  395       A domain label longer than 63 characters that results from macro
  396       expansion in a mechanism target-name is valid domain-spec syntax (and is
  397       not even subject to syntax checking after macro expansion), even though
  398       a DNS query cannot be composed from it.  The spec being unclear about
  399       it, this could either be considered a syntax error, or, by analogy to
  400       4.3/1 and 5/10/3, the mechanism chould be treated as a no-match.
  401     spec: [4.3/1, 5/10/3]
  402     helo: "%%%%%%%%%%%%%%%%%%%%%%"
  403     host: 1.2.3.4
  404     mailfrom: foo@t12.example.com
  405     result: [permerror,fail]
  406 zonedata:
  407   mail.example.com:
  408     - A: 1.2.3.4
  409   t1.example.com:
  410     - SPF: v=spf1 ip4:1.2.3.4 -all moo
  411   t2.example.com:
  412     - SPF: v=spf1 moo.cow-far_out=man:dog/cat ip4:1.2.3.4 -all
  413   t3.example.com:
  414     - SPF: v=spf1 moo.cow/far_out=man:dog/cat ip4:1.2.3.4 -all
  415   t4.example.com:
  416     - SPF: v=spf1 moo.cow:far_out=man:dog/cat ip4:1.2.3.4 -all
  417   t5.example.com:
  418     - SPF: v=spf1 redirect=t5.example.com ~all
  419   t6.example.com:
  420     - SPF: v=spf1 ip4:1.2.3.4 redirect=t2.example.com
  421   t7.example.com:
  422     - SPF: v=spf1 ip4:1.2.3.4
  423   t8.example.com:
  424     - SPF: v=spf1 ip4:1.2.3.4 redirect:t2.example.com
  425   t9.example.com:
  426     - SPF: v=spf1 a:foo-bar -all
  427   t10.example.com:
  428     - SPF: v=spf1 a:mail.example...com -all
  429   t11.example.com:
  430     - SPF: v=spf1 a:a123456789012345678901234567890123456789012345678901234567890123.example.com -all
  431   t12.example.com:
  432     - SPF: v=spf1 a:%{H}.bar -all
  433 ---
  434 description: ALL mechanism syntax
  435 tests:
  436   all-dot:
  437     description: |
  438       all              = "all"
  439     comment: |-
  440       At least one implementation got this wrong
  441     spec: 5.1/1
  442     helo: mail.example.com
  443     host: 1.2.3.4
  444     mailfrom: foo@e1.example.com
  445     result: permerror
  446   all-arg:
  447     description: |
  448       all              = "all"
  449     comment: |-
  450       At least one implementation got this wrong
  451     spec: 5.1/1
  452     helo: mail.example.com
  453     host: 1.2.3.4
  454     mailfrom: foo@e2.example.com
  455     result: permerror
  456   all-cidr:
  457     description: |
  458       all              = "all"
  459     spec: 5.1/1
  460     helo: mail.example.com
  461     host: 1.2.3.4
  462     mailfrom: foo@e3.example.com
  463     result: permerror
  464   all-neutral:
  465     description: |
  466       all              = "all"
  467     spec: 5.1/1
  468     helo: mail.example.com
  469     host: 1.2.3.4
  470     mailfrom: foo@e4.example.com
  471     result: neutral
  472   all-double:
  473     description: |
  474       all              = "all"
  475     spec: 5.1/1
  476     helo: mail.example.com
  477     host: 1.2.3.4
  478     mailfrom: foo@e5.example.com
  479     result: pass
  480 zonedata:
  481   mail.example.com:
  482     - A: 1.2.3.4
  483   e1.example.com:
  484     - SPF: v=spf1 -all.
  485   e2.example.com:
  486     - SPF: v=spf1 -all:foobar
  487   e3.example.com:
  488     - SPF: v=spf1 -all/8
  489   e4.example.com:
  490     - SPF: v=spf1 ?all
  491   e5.example.com:
  492     - SPF: v=spf1 all -all
  493 ---
  494 description: PTR mechanism syntax
  495 tests:
  496   ptr-cidr:
  497     description: |-
  498       PTR              = "ptr"    [ ":" domain-spec ]
  499     spec: 5.5/2
  500     helo: mail.example.com
  501     host: 1.2.3.4
  502     mailfrom: foo@e1.example.com
  503     result: permerror
  504   ptr-match-target:
  505     description: >-
  506       Check all validated domain names to see if they end in the <target-name>
  507       domain.
  508     spec: 5.5/5
  509     helo: mail.example.com
  510     host: 1.2.3.4
  511     mailfrom: foo@e2.example.com
  512     result: pass
  513   ptr-match-implicit:
  514     description: >-
  515       Check all validated domain names to see if they end in the <target-name>
  516       domain.
  517     spec: 5.5/5
  518     helo: mail.example.com
  519     host: 1.2.3.4
  520     mailfrom: foo@e3.example.com
  521     result: pass
  522   ptr-nomatch-invalid:
  523     description: >-
  524       Check all validated domain names to see if they end in the <target-name>
  525       domain.
  526     comment: >-
  527       This PTR record does not validate
  528     spec: 5.5/5
  529     helo: mail.example.com
  530     host: 1.2.3.4
  531     mailfrom: foo@e4.example.com
  532     result: fail
  533   ptr-match-ip6:
  534     description: >-
  535       Check all validated domain names to see if they end in the <target-name>
  536       domain.
  537     spec: 5.5/5
  538     helo: mail.example.com
  539     host: CAFE:BABE::1
  540     mailfrom: foo@e3.example.com
  541     result: pass
  542   ptr-empty-domain:
  543     description: >-
  544       domain-spec cannot be empty.
  545     spec: 5.5/2
  546     helo: mail.example.com
  547     host: 1.2.3.4
  548     mailfrom: foo@e5.example.com
  549     result: permerror
  550 zonedata:
  551   mail.example.com:
  552     - A: 1.2.3.4
  553   e1.example.com:
  554     - SPF: v=spf1 ptr/0 -all
  555   e2.example.com:
  556     - SPF: v=spf1 ptr:example.com -all
  557   4.3.2.1.in-addr.arpa:
  558     - PTR: e3.example.com
  559     - PTR: e4.example.com
  560     - PTR: mail.example.com
  561   1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa:
  562     - PTR: e3.example.com
  563   e3.example.com:
  564     - SPF: v=spf1 ptr -all
  565     - A: 1.2.3.4
  566     - AAAA: CAFE:BABE::1
  567   e4.example.com:
  568     - SPF: v=spf1 ptr -all
  569   e5.example.com:
  570     - SPF: "v=spf1 ptr:"
  571 ---
  572 description: A mechanism syntax
  573 tests:
  574   a-cidr6:
  575     description: |
  576       A                = "a"      [ ":" domain-spec ] [ dual-cidr-length ]
  577       dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ]
  578     spec: 5.3/2
  579     helo: mail.example.com
  580     host: 1.2.3.4
  581     mailfrom: foo@e6.example.com
  582     result: fail
  583   a-bad-cidr4:
  584     description: |
  585       A                = "a"      [ ":" domain-spec ] [ dual-cidr-length ]
  586       dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ]
  587     spec: 5.3/2
  588     helo: mail.example.com
  589     host: 1.2.3.4
  590     mailfrom: foo@e6a.example.com
  591     result: permerror
  592   a-bad-cidr6:
  593     description: |
  594       A                = "a"      [ ":" domain-spec ] [ dual-cidr-length ]
  595       dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ]
  596     spec: 5.3/2
  597     helo: mail.example.com
  598     host: 1.2.3.4
  599     mailfrom: foo@e7.example.com
  600     result: permerror
  601   a-multi-ip1:
  602     description: >-
  603       A matches any returned IP.
  604     spec: 5.3/3
  605     helo: mail.example.com
  606     host: 1.2.3.4
  607     mailfrom: foo@e10.example.com
  608     result: pass
  609   a-multi-ip2:
  610     description: >-
  611       A matches any returned IP.
  612     spec: 5.3/3
  613     helo: mail.example.com
  614     host: 1.2.3.4
  615     mailfrom: foo@e10.example.com
  616     result: pass
  617   a-bad-domain:
  618     description: >-
  619       domain-spec must pass basic syntax checks;
  620       a ':' may appear in domain-spec, but not in top-label
  621     spec: 8.1/2
  622     helo: mail.example.com
  623     host: 1.2.3.4
  624     mailfrom: foo@e9.example.com
  625     result: permerror
  626   a-nxdomain:
  627     description: >-
  628       If no ips are returned, A mechanism does not match, even with /0.
  629     spec: 5.3/3
  630     helo: mail.example.com
  631     host: 1.2.3.4
  632     mailfrom: foo@e1.example.com
  633     result: fail
  634   a-cidr4-0:
  635     description: >-
  636       Matches if any A records are present in DNS.
  637     spec: 5.3/3
  638     helo: mail.example.com
  639     host: 1.2.3.4
  640     mailfrom: foo@e2.example.com
  641     result: pass
  642   a-cidr4-0-ip6:
  643     description: >-
  644       Matches if any A records are present in DNS.
  645     spec: 5.3/3
  646     helo: mail.example.com
  647     host: 1234::1
  648     mailfrom: foo@e2.example.com
  649     result: fail
  650   a-cidr6-0-ip4:
  651     description: >-
  652       Would match if any AAAA records are present in DNS,
  653       but not for an IP4 connection.
  654     spec: 5.3/3
  655     helo: mail.example.com
  656     host: 1.2.3.4
  657     mailfrom: foo@e2a.example.com
  658     result: fail
  659   a-cidr6-0-ip4mapped:
  660     description: >-
  661       Would match if any AAAA records are present in DNS,
  662       but not for an IP4 connection.
  663     spec: 5.3/3
  664     helo: mail.example.com
  665     host: ::FFFF:1.2.3.4
  666     mailfrom: foo@e2a.example.com
  667     result: fail
  668   a-cidr6-0-ip6:
  669     description: >-
  670       Matches if any AAAA records are present in DNS.
  671     spec: 5.3/3
  672     helo: mail.example.com
  673     host: 1234::1
  674     mailfrom: foo@e2a.example.com
  675     result: pass
  676   a-cidr6-0-nxdomain:
  677     description: >-
  678       No match if no AAAA records are present in DNS.
  679     spec: 5.3/3
  680     helo: mail.example.com
  681     host: 1234::1
  682     mailfrom: foo@e2b.example.com
  683     result: fail
  684   a-null:
  685     description: >-
  686       Null octets not allowed in toplabel
  687     spec: 8.1/2
  688     helo: mail.example.com
  689     host: 1.2.3.5
  690     mailfrom: foo@e3.example.com
  691     result: permerror
  692   a-numeric:
  693     description: >-
  694       toplabel may not be all numeric
  695     comment: >-
  696       A common publishing mistake is using ip4 addresses with A mechanism.
  697       This should receive special diagnostic attention in the permerror.
  698     spec: 8.1/2
  699     helo: mail.example.com
  700     host: 1.2.3.4
  701     mailfrom: foo@e4.example.com
  702     result: permerror
  703   a-numeric-toplabel:
  704     description: >-
  705       toplabel may not be all numeric
  706     spec: 8.1/2
  707     helo: mail.example.com
  708     host: 1.2.3.4
  709     mailfrom: foo@e5.example.com
  710     result: permerror
  711   a-dash-in-toplabel:
  712     description: >-
  713       toplabel may contain dashes
  714     comment: >-
  715       Going from the "toplabel" grammar definition, an implementation using
  716       regular expressions in incrementally parsing SPF records might
  717       erroneously try to match a TLD such as ".xn--zckzah" (cf. IDN TLDs!) to
  718       '( *alphanum ALPHA *alphanum )' first before trying the alternative
  719       '( 1*alphanum "-" *( alphanum / "-" ) alphanum )', essentially causing
  720       a non-greedy, and thus, incomplete match.  Make sure a greedy match is
  721       performed!
  722     spec: 8.1/2
  723     helo: mail.example.com
  724     host: 1.2.3.4
  725     mailfrom: foo@e14.example.com
  726     result: pass
  727   a-bad-toplabel:
  728     description: >-
  729       toplabel may not begin with a dash
  730     spec: 8.1/2
  731     helo: mail.example.com
  732     host: 1.2.3.4
  733     mailfrom: foo@e12.example.com
  734     result: permerror
  735   a-only-toplabel:
  736     description: >-
  737       domain-spec may not consist of only a toplabel.
  738     spec: 8.1/2
  739     helo: mail.example.com
  740     host: 1.2.3.4
  741     mailfrom: foo@e5a.example.com
  742     result: permerror
  743   a-only-toplabel-trailing-dot:
  744     description: >-
  745       domain-spec may not consist of only a toplabel.
  746     comment: >-
  747       "A trailing dot doesn't help."
  748     spec: 8.1/2
  749     helo: mail.example.com
  750     host: 1.2.3.4
  751     mailfrom: foo@e5b.example.com
  752     result: permerror
  753   a-colon-domain:
  754     description: >-
  755       domain-spec may contain any visible char except %
  756     spec: 8.1/2
  757     helo: mail.example.com
  758     host: 1.2.3.4
  759     mailfrom: foo@e11.example.com
  760     result: pass
  761   a-colon-domain-ip4mapped:
  762     description: >-
  763       domain-spec may contain any visible char except %
  764     spec: 8.1/2
  765     helo: mail.example.com
  766     host: ::FFFF:1.2.3.4
  767     mailfrom: foo@e11.example.com
  768     result: pass
  769   a-empty-domain:
  770     description: >-
  771       domain-spec cannot be empty.
  772     spec: 5.3/2
  773     helo: mail.example.com
  774     host: 1.2.3.4
  775     mailfrom: foo@e13.example.com
  776     result: permerror
  777 zonedata:
  778   mail.example.com:
  779     - A: 1.2.3.4
  780   e1.example.com:
  781     - SPF: v=spf1 a/0 -all
  782   e2.example.com:
  783     - A: 1.1.1.1
  784     - AAAA: 1234::2
  785     - SPF: v=spf1 a/0 -all
  786   e2a.example.com:
  787     - AAAA: 1234::1
  788     - SPF: v=spf1 a//0 -all
  789   e2b.example.com:
  790     - A: 1.1.1.1
  791     - SPF: v=spf1 a//0 -all
  792   e3.example.com:
  793     - SPF: "v=spf1 a:foo.example.com\0"
  794   e4.example.com:
  795     - SPF: v=spf1 a:111.222.33.44
  796   e5.example.com:
  797     - SPF: v=spf1 a:abc.123
  798   e5a.example.com:
  799     - SPF: v=spf1 a:museum
  800   e5b.example.com:
  801     - SPF: v=spf1 a:museum.
  802   e6.example.com:
  803     - SPF: v=spf1 a//33 -all
  804   e6a.example.com:
  805     - SPF: v=spf1 a/33 -all
  806   e7.example.com:
  807     - SPF: v=spf1 a//129 -all
  808   e9.example.com:
  809     - SPF: v=spf1 a:example.com:8080
  810   e10.example.com:
  811     - SPF: v=spf1 a:foo.example.com/24
  812   foo.example.com:
  813     - A: 1.1.1.1
  814     - A: 1.2.3.5
  815   e11.example.com:
  816     - SPF: v=spf1 a:foo:bar/baz.example.com
  817   foo:bar/baz.example.com:
  818     - A: 1.2.3.4
  819   e12.example.com:
  820     - SPF: v=spf1 a:example.-com
  821   e13.example.com:
  822     - SPF: "v=spf1 a:"
  823   e14.example.com:
  824     - SPF: "v=spf1 a:foo.example.xn--zckzah -all"
  825   foo.example.xn--zckzah:
  826     - A: 1.2.3.4
  827 ---
  828 description: Include mechanism semantics and syntax
  829 tests:
  830   include-fail:
  831     description: >-
  832       recursive check_host() result of fail causes include to not match.
  833     spec: 5.2/9
  834     helo: mail.example.com
  835     host: 1.2.3.4
  836     mailfrom: foo@e1.example.com
  837     result: softfail
  838   include-softfail:
  839     description: >-
  840       recursive check_host() result of softfail causes include to not match.
  841     spec: 5.2/9
  842     helo: mail.example.com
  843     host: 1.2.3.4
  844     mailfrom: foo@e2.example.com
  845     result: pass
  846   include-neutral:
  847     description: >-
  848       recursive check_host() result of neutral causes include to not match.
  849     spec: 5.2/9
  850     helo: mail.example.com
  851     host: 1.2.3.4
  852     mailfrom: foo@e3.example.com
  853     result: fail
  854   include-temperror:
  855     description: >-
  856       recursive check_host() result of temperror causes include to temperror
  857     spec: 5.2/9
  858     helo: mail.example.com
  859     host: 1.2.3.4
  860     mailfrom: foo@e4.example.com
  861     result: temperror
  862   include-permerror:
  863     description: >-
  864       recursive check_host() result of permerror causes include to permerror
  865     spec: 5.2/9
  866     helo: mail.example.com
  867     host: 1.2.3.4
  868     mailfrom: foo@e5.example.com
  869     result: permerror
  870   include-syntax-error:
  871     description: >-
  872       include          = "include"  ":" domain-spec
  873     spec: 5.2/1
  874     helo: mail.example.com
  875     host: 1.2.3.4
  876     mailfrom: foo@e6.example.com
  877     result: permerror
  878   include-cidr:
  879     description: >-
  880       include          = "include"  ":" domain-spec
  881     spec: 5.2/1
  882     helo: mail.example.com
  883     host: 1.2.3.4
  884     mailfrom: foo@e9.example.com
  885     result: permerror
  886   include-none:
  887     description: >-
  888       recursive check_host() result of none causes include to permerror
  889     spec: 5.2/9
  890     helo: mail.example.com
  891     host: 1.2.3.4
  892     mailfrom: foo@e7.example.com
  893     result: permerror
  894   include-empty-domain:
  895     description: >-
  896       domain-spec cannot be empty.
  897     spec: 5.2/1
  898     helo: mail.example.com
  899     host: 1.2.3.4
  900     mailfrom: foo@e8.example.com
  901     result: permerror
  902 zonedata:
  903   mail.example.com:
  904     - A: 1.2.3.4
  905   ip5.example.com:
  906     - SPF: v=spf1 ip4:1.2.3.5 -all
  907   ip6.example.com:
  908     - SPF: v=spf1 ip4:1.2.3.6 ~all
  909   ip7.example.com:
  910     - SPF: v=spf1 ip4:1.2.3.7 ?all
  911   ip8.example.com:
  912     - TIMEOUT
  913   erehwon.example.com:
  914     - TXT: v=spfl am not an SPF record
  915   e1.example.com:
  916     - SPF: v=spf1 include:ip5.example.com ~all
  917   e2.example.com:
  918     - SPF: v=spf1 include:ip6.example.com all
  919   e3.example.com:
  920     - SPF: v=spf1 include:ip7.example.com -all
  921   e4.example.com:
  922     - SPF: v=spf1 include:ip8.example.com -all
  923   e5.example.com:
  924     - SPF: v=spf1 include:e6.example.com -all
  925   e6.example.com:
  926     - SPF: v=spf1 include +all
  927   e7.example.com:
  928     - SPF: v=spf1 include:erehwon.example.com -all
  929   e8.example.com:
  930     - SPF: "v=spf1 include: -all"
  931   e9.example.com:
  932     - SPF: "v=spf1 include:ip5.example.com/24 -all"
  933 ---
  934 description: MX mechanism syntax
  935 tests:
  936   mx-cidr6:
  937     description: |
  938       MX                = "mx"      [ ":" domain-spec ] [ dual-cidr-length ]
  939       dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ]
  940     spec: 5.4/2
  941     helo: mail.example.com
  942     host: 1.2.3.4
  943     mailfrom: foo@e6.example.com
  944     result: fail
  945   mx-bad-cidr4:
  946     description: |
  947       MX                = "mx"      [ ":" domain-spec ] [ dual-cidr-length ]
  948       dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ]
  949     spec: 5.4/2
  950     helo: mail.example.com
  951     host: 1.2.3.4
  952     mailfrom: foo@e6a.example.com
  953     result: permerror
  954   mx-bad-cidr6:
  955     description: |
  956       MX                = "mx"      [ ":" domain-spec ] [ dual-cidr-length ]
  957       dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ]
  958     spec: 5.4/2
  959     helo: mail.example.com
  960     host: 1.2.3.4
  961     mailfrom: foo@e7.example.com
  962     result: permerror
  963   mx-multi-ip1:
  964     description: >-
  965       MX matches any returned IP.
  966     spec: 5.4/3
  967     helo: mail.example.com
  968     host: 1.2.3.4
  969     mailfrom: foo@e10.example.com
  970     result: pass
  971   mx-multi-ip2:
  972     description: >-
  973       MX matches any returned IP.
  974     spec: 5.4/3
  975     helo: mail.example.com
  976     host: 1.2.3.4
  977     mailfrom: foo@e10.example.com
  978     result: pass
  979   mx-bad-domain:
  980     description: >-
  981       domain-spec must pass basic syntax checks
  982     comment: >-
  983       A ':' may appear in domain-spec, but not in top-label.
  984     spec: 8.1/2
  985     helo: mail.example.com
  986     host: 1.2.3.4
  987     mailfrom: foo@e9.example.com
  988     result: permerror
  989   mx-nxdomain:
  990     description: >-
  991       If no ips are returned, MX mechanism does not match, even with /0.
  992     spec: 5.4/3
  993     helo: mail.example.com
  994     host: 1.2.3.4
  995     mailfrom: foo@e1.example.com
  996     result: fail
  997   mx-cidr4-0:
  998     description: >-
  999       Matches if any A records for any MX records are present in DNS.
 1000     spec: 5.4/3
 1001     helo: mail.example.com
 1002     host: 1.2.3.4
 1003     mailfrom: foo@e2.example.com
 1004     result: pass
 1005   mx-cidr4-0-ip6:
 1006     description: >-
 1007       Matches if any A records for any MX records are present in DNS.
 1008     spec: 5.4/3
 1009     helo: mail.example.com
 1010     host: 1234::1
 1011     mailfrom: foo@e2.example.com
 1012     result: fail
 1013   mx-cidr6-0-ip4:
 1014     description: >-
 1015       Would match if any AAAA records for MX records are present in DNS,
 1016       but not for an IP4 connection.
 1017     spec: 5.4/3
 1018     helo: mail.example.com
 1019     host: 1.2.3.4
 1020     mailfrom: foo@e2a.example.com
 1021     result: fail
 1022   mx-cidr6-0-ip4mapped:
 1023     description: >-
 1024       Would match if any AAAA records for MX records are present in DNS,
 1025       but not for an IP4 connection.
 1026     spec: 5.4/3
 1027     helo: mail.example.com
 1028     host: ::FFFF:1.2.3.4
 1029     mailfrom: foo@e2a.example.com
 1030     result: fail
 1031   mx-cidr6-0-ip6:
 1032     description: >-
 1033       Matches if any AAAA records for any MX records are present in DNS.
 1034     spec: 5.3/3
 1035     helo: mail.example.com
 1036     host: 1234::1
 1037     mailfrom: foo@e2a.example.com
 1038     result: pass
 1039   mx-cidr6-0-nxdomain:
 1040     description: >-
 1041       No match if no AAAA records for any MX records are present in DNS.
 1042     spec: 5.4/3
 1043     helo: mail.example.com
 1044     host: 1234::1
 1045     mailfrom: foo@e2b.example.com
 1046     result: fail
 1047   mx-null:
 1048     description: >-
 1049       Null not allowed in top-label.
 1050     spec: 8.1/2
 1051     helo: mail.example.com
 1052     host: 1.2.3.5
 1053     mailfrom: foo@e3.example.com
 1054     result: permerror
 1055   mx-numeric-top-label:
 1056     description: >-
 1057       Top-label may not be all numeric
 1058     spec: 8.1/2
 1059     helo: mail.example.com
 1060     host: 1.2.3.4
 1061     mailfrom: foo@e5.example.com
 1062     result: permerror
 1063   mx-colon-domain:
 1064     description: >-
 1065       Domain-spec may contain any visible char except %
 1066     spec: 8.1/2
 1067     helo: mail.example.com
 1068     host: 1.2.3.4
 1069     mailfrom: foo@e11.example.com
 1070     result: pass
 1071   mx-colon-domain-ip4mapped:
 1072     description: >-
 1073       Domain-spec may contain any visible char except %
 1074     spec: 8.1/2
 1075     helo: mail.example.com
 1076     host: ::FFFF:1.2.3.4
 1077     mailfrom: foo@e11.example.com
 1078     result: pass
 1079   mx-bad-toplab:
 1080     description: >-
 1081       Toplabel may not begin with -
 1082     spec: 8.1/2
 1083     helo: mail.example.com
 1084     host: 1.2.3.4
 1085     mailfrom: foo@e12.example.com
 1086     result: permerror
 1087   mx-empty:
 1088     description: >-
 1089       test null MX
 1090     comment: >-
 1091       Some implementations have had trouble with null MX
 1092     spec: 5.4/3
 1093     helo: mail.example.com
 1094     host: 1.2.3.4
 1095     mailfrom: ""
 1096     result: neutral
 1097   mx-implicit:
 1098     description: >-
 1099       If the target name has no MX records, check_host() MUST NOT pretend the
 1100       target is its single MX, and MUST NOT default to an A lookup on the
 1101       target-name directly.
 1102     spec: 5.4/4
 1103     helo: mail.example.com
 1104     host: 1.2.3.4
 1105     mailfrom: foo@e4.example.com
 1106     result: neutral
 1107   mx-empty-domain:
 1108     description: >-
 1109       domain-spec cannot be empty.
 1110     spec: 5.2/1
 1111     helo: mail.example.com
 1112     host: 1.2.3.4
 1113     mailfrom: foo@e13.example.com
 1114     result: permerror
 1115 zonedata:
 1116   mail.example.com:
 1117     - A: 1.2.3.4
 1118     - MX: [0, ""]
 1119     - SPF: v=spf1 mx
 1120   e1.example.com:
 1121     - SPF: v=spf1 mx/0 -all
 1122     - MX: [0, e1.example.com]
 1123   e2.example.com:
 1124     - A: 1.1.1.1
 1125     - AAAA: 1234::2
 1126     - MX: [0, e2.example.com]
 1127     - SPF: v=spf1 mx/0 -all
 1128   e2a.example.com:
 1129     - AAAA: 1234::1
 1130     - MX: [0, e2a.example.com]
 1131     - SPF: v=spf1 mx//0 -all
 1132   e2b.example.com:
 1133     - A: 1.1.1.1
 1134     - MX: [0, e2b.example.com]
 1135     - SPF: v=spf1 mx//0 -all
 1136   e3.example.com:
 1137     - SPF: "v=spf1 mx:foo.example.com\0"
 1138   e4.example.com:
 1139     - SPF: v=spf1 mx
 1140     - A: 1.2.3.4
 1141   e5.example.com:
 1142     - SPF: v=spf1 mx:abc.123
 1143   e6.example.com:
 1144     - SPF: v=spf1 mx//33 -all
 1145   e6a.example.com:
 1146     - SPF: v=spf1 mx/33 -all
 1147   e7.example.com:
 1148     - SPF: v=spf1 mx//129 -all
 1149   e9.example.com:
 1150     - SPF: v=spf1 mx:example.com:8080
 1151   e10.example.com:
 1152     - SPF: v=spf1 mx:foo.example.com/24
 1153   foo.example.com:
 1154     - MX: [0, foo1.example.com]
 1155   foo1.example.com:
 1156     - A: 1.1.1.1
 1157     - A: 1.2.3.5
 1158   e11.example.com:
 1159     - SPF: v=spf1 mx:foo:bar/baz.example.com
 1160   foo:bar/baz.example.com:
 1161     - MX: [0, "foo:bar/baz.example.com"]
 1162     - A: 1.2.3.4
 1163   e12.example.com:
 1164     - SPF: v=spf1 mx:example.-com
 1165   e13.example.com:
 1166     - SPF: "v=spf1 mx: -all"
 1167 ---
 1168 description: EXISTS mechanism syntax
 1169 tests:
 1170   exists-empty-domain:
 1171     description: >-
 1172       domain-spec cannot be empty.
 1173     spec: 5.7/2
 1174     helo: mail.example.com
 1175     host: 1.2.3.4
 1176     mailfrom: foo@e1.example.com
 1177     result: permerror
 1178   exists-implicit:
 1179     description: >-
 1180       exists           = "exists"   ":" domain-spec
 1181     spec: 5.7/2
 1182     helo: mail.example.com
 1183     host: 1.2.3.4
 1184     mailfrom: foo@e2.example.com
 1185     result: permerror
 1186   exists-cidr:
 1187     description: >-
 1188       exists           = "exists"   ":" domain-spec
 1189     spec: 5.7/2
 1190     helo: mail.example.com
 1191     host: 1.2.3.4
 1192     mailfrom: foo@e3.example.com
 1193     result: permerror
 1194 zonedata:
 1195   mail.example.com:
 1196     - A: 1.2.3.4
 1197   e1.example.com:
 1198     - SPF: "v=spf1 exists:"
 1199   e2.example.com:
 1200     - SPF: "v=spf1 exists"
 1201   e3.example.com:
 1202     - SPF: "v=spf1 exists:mail.example.com/24"
 1203 ---
 1204 description: IP4 mechanism syntax
 1205 tests:
 1206   cidr4-0:
 1207     description: >-
 1208       ip4-cidr-length  = "/" 1*DIGIT
 1209     spec: 5.6/2
 1210     helo: mail.example.com
 1211     host: 1.2.3.4
 1212     mailfrom: foo@e1.example.com
 1213     result: pass
 1214   cidr4-32:
 1215     description: >-
 1216       ip4-cidr-length  = "/" 1*DIGIT
 1217     spec: 5.6/2
 1218     helo: mail.example.com
 1219     host: 1.2.3.4
 1220     mailfrom: foo@e2.example.com
 1221     result: pass
 1222   cidr4-33:
 1223     description: >-
 1224       Invalid CIDR should get permerror.
 1225     comment: >-
 1226       The RFC is silent on ip4 CIDR > 32 or ip6 CIDR > 128.  However,
 1227       since there is no reasonable interpretation (except a noop), we have
 1228       read between the lines to see a prohibition on invalid CIDR.
 1229     spec: 5.6/2
 1230     helo: mail.example.com
 1231     host: 1.2.3.4
 1232     mailfrom: foo@e3.example.com
 1233     result: permerror
 1234   cidr4-032:
 1235     description: >-
 1236       Invalid CIDR should get permerror.
 1237     comment: >-
 1238       Leading zeros are not explicitly prohibited by the RFC. However,
 1239       since the RFC explicity prohibits leading zeros in ip4-network,
 1240       our interpretation is that CIDR should be also.
 1241     spec: 5.6/2
 1242     helo: mail.example.com
 1243     host: 1.2.3.4
 1244     mailfrom: foo@e4.example.com
 1245     result: permerror
 1246   bare-ip4:
 1247     description: >-
 1248       IP4              = "ip4"      ":" ip4-network   [ ip4-cidr-length ]
 1249     spec: 5.6/2
 1250     helo: mail.example.com
 1251     host: 1.2.3.4
 1252     mailfrom: foo@e5.example.com
 1253     result: permerror
 1254   bad-ip4-port:
 1255     description: >-
 1256       IP4              = "ip4"      ":" ip4-network   [ ip4-cidr-length ]
 1257     comment: >-
 1258       This has actually been published in SPF records.
 1259     spec: 5.6/2
 1260     helo: mail.example.com
 1261     host: 1.2.3.4
 1262     mailfrom: foo@e8.example.com
 1263     result: permerror
 1264   bad-ip4-short:
 1265     description: >-
 1266       It is not permitted to omit parts of the IP address instead of
 1267       using CIDR notations.
 1268     spec: 5.6/4
 1269     helo: mail.example.com
 1270     host: 1.2.3.4
 1271     mailfrom: foo@e9.example.com
 1272     result: permerror
 1273   ip4-dual-cidr:
 1274     description: >-
 1275       dual-cidr-length not permitted on ip4
 1276     spec: 5.6/2
 1277     helo: mail.example.com
 1278     host: 1.2.3.4
 1279     mailfrom: foo@e6.example.com
 1280     result: permerror
 1281   ip4-mapped-ip6:
 1282     description: >-
 1283       IP4 mapped IP6 connections MUST be treated as IP4
 1284     spec: 5/9/2
 1285     helo: mail.example.com
 1286     host: ::FFFF:1.2.3.4
 1287     mailfrom: foo@e7.example.com
 1288     result: fail
 1289 zonedata:
 1290   mail.example.com:
 1291     - A: 1.2.3.4
 1292   e1.example.com:
 1293     - SPF: v=spf1 ip4:1.1.1.1/0 -all
 1294   e2.example.com:
 1295     - SPF: v=spf1 ip4:1.2.3.4/32 -all
 1296   e3.example.com:
 1297     - SPF: v=spf1 ip4:1.2.3.4/33 -all
 1298   e4.example.com:
 1299     - SPF: v=spf1 ip4:1.2.3.4/032 -all
 1300   e5.example.com:
 1301     - SPF: v=spf1 ip4
 1302   e6.example.com:
 1303     - SPF: v=spf1 ip4:1.2.3.4//32
 1304   e7.example.com:
 1305     - SPF: v=spf1 -ip4:1.2.3.4 ip6:::FFFF:1.2.3.4
 1306   e8.example.com:
 1307     - SPF: v=spf1 ip4:1.2.3.4:8080
 1308   e9.example.com:
 1309     - SPF: v=spf1 ip4:1.2.3
 1310 ---
 1311 description: IP6 mechanism syntax
 1312 comment: >-
 1313   IP4 only implementations may skip tests where host is not IP4
 1314 tests:
 1315   bare-ip6:
 1316     description: >-
 1317       IP6              = "ip6"      ":" ip6-network   [ ip6-cidr-length ]
 1318     spec: 5.6/2
 1319     helo: mail.example.com
 1320     host: 1.2.3.4
 1321     mailfrom: foo@e1.example.com
 1322     result: permerror
 1323   cidr6-0-ip4:
 1324     description: >-
 1325       IP4 connections do not match ip6.
 1326     comment: >-
 1327       There is controversy over ip4 mapped connections.  RFC4408 clearly
 1328       requires such connections to be considered as ip4.  However,
 1329       some interpret the RFC to mean that such connections should *also*
 1330       match appropriate ip6 mechanisms (but not, inexplicably, A or MX
 1331       mechanisms).  Until there is consensus, both
 1332       results are acceptable.
 1333     spec: 5/9/2
 1334     helo: mail.example.com
 1335     host: 1.2.3.4
 1336     mailfrom: foo@e2.example.com
 1337     result: [neutral, pass]
 1338   cidr6-ip4:
 1339     description: >-
 1340       Even if the SMTP connection is via IPv6, an IPv4-mapped IPv6 IP address
 1341       (see RFC 3513, Section 2.5.5) MUST still be considered an IPv4 address.
 1342     comment: >-
 1343       There is controversy over ip4 mapped connections.  RFC4408 clearly
 1344       requires such connections to be considered as ip4.  However,
 1345       some interpret the RFC to mean that such connections should *also*
 1346       match appropriate ip6 mechanisms (but not, inexplicably, A or MX
 1347       mechanisms).  Until there is consensus, both
 1348       results are acceptable.
 1349     spec: 5/9/2
 1350     helo: mail.example.com
 1351     host: ::FFFF:1.2.3.4
 1352     mailfrom: foo@e2.example.com
 1353     result: [neutral, pass]
 1354   cidr6-0:
 1355     description: >-
 1356       Match any IP6
 1357     spec: 5/8
 1358     helo: mail.example.com
 1359     host: DEAF:BABE::CAB:FEE
 1360     mailfrom: foo@e2.example.com
 1361     result: pass
 1362   cidr6-129:
 1363     description: >-
 1364       Invalid CIDR
 1365     comment: >-
 1366       IP4 only implementations MUST fully syntax check all mechanisms,
 1367       even if they otherwise ignore them.
 1368     spec: 5.6/2
 1369     helo: mail.example.com
 1370     host: 1.2.3.4
 1371     mailfrom: foo@e3.example.com
 1372     result: permerror
 1373   cidr6-bad:
 1374     description: >-
 1375       dual-cidr syntax not used for ip6
 1376     comment: >-
 1377       IP4 only implementations MUST fully syntax check all mechanisms,
 1378       even if they otherwise ignore them.
 1379     spec: 5.6/2
 1380     helo: mail.example.com
 1381     host: 1.2.3.4
 1382     mailfrom: foo@e4.example.com
 1383     result: permerror
 1384   cidr6-33:
 1385     description: >-
 1386       make sure ip4 cidr restriction are not used for ip6
 1387     spec: 5.6/2
 1388     helo: mail.example.com
 1389     host: "CAFE:BABE:8000::"
 1390     mailfrom: foo@e5.example.com
 1391     result: pass
 1392   cidr6-33-ip4:
 1393     description: >-
 1394       make sure ip4 cidr restriction are not used for ip6
 1395     spec: 5.6/2
 1396     helo: mail.example.com
 1397     host: 1.2.3.4
 1398     mailfrom: foo@e5.example.com
 1399     result: neutral
 1400   ip6-bad1:
 1401     description: >-
 1402     spec: 5.6/2
 1403     helo: mail.example.com
 1404     host: 1.2.3.4
 1405     mailfrom: foo@e6.example.com
 1406     result: permerror
 1407 zonedata:
 1408   mail.example.com:
 1409     - A: 1.2.3.4
 1410   e1.example.com:
 1411     - SPF: v=spf1 -all ip6
 1412   e2.example.com:
 1413     - SPF: v=spf1 ip6:::1.1.1.1/0
 1414   e3.example.com:
 1415     - SPF: v=spf1 ip6:::1.1.1.1/129
 1416   e4.example.com:
 1417     - SPF: v=spf1 ip6:::1.1.1.1//33
 1418   e5.example.com:
 1419     - SPF: v=spf1 ip6:CAFE:BABE:8000::/33
 1420   e6.example.com:
 1421     - SPF: v=spf1 ip6::CAFE::BABE
 1422 ---
 1423 description: Semantics of exp and other modifiers
 1424 comment: >-
 1425   Implementing exp= is optional.  If not implemented, the test driver should
 1426   not check the explanation field.
 1427 tests:
 1428   redirect-none:
 1429     description: >-
 1430       If no SPF record is found, or if the target-name is malformed, the result
 1431       is a "PermError" rather than "None".
 1432     spec: 6.1/4
 1433     helo: mail.example.com
 1434     host: 1.2.3.4
 1435     mailfrom: foo@e10.example.com
 1436     result: permerror
 1437   redirect-cancels-exp:
 1438     description: >-
 1439       when executing "redirect", exp= from the original domain MUST NOT be used.
 1440     spec: 6.2/13
 1441     helo: mail.example.com
 1442     host: 1.2.3.4
 1443     mailfrom: foo@e1.example.com
 1444     result: fail
 1445     explanation: DEFAULT
 1446   redirect-syntax-error:
 1447     description: |
 1448       redirect      = "redirect" "=" domain-spec
 1449     comment: >-
 1450       A literal application of the grammar causes modifier syntax
 1451       errors (except for macro syntax) to become unknown-modifier.
 1452       
 1453         modifier = explanation | redirect | unknown-modifier
 1454       
 1455       However, it is generally agreed, with precedent in other RFCs,
 1456       that unknown-modifier should not be "greedy", and should not
 1457       match known modifier names.  There should have been explicit
 1458       prose to this effect, and some has been proposed as an erratum.
 1459     spec: 6.1/2
 1460     helo: mail.example.com
 1461     host: 1.2.3.4
 1462     mailfrom: foo@e17.example.com
 1463     result: permerror
 1464   include-ignores-exp:
 1465     description: >-
 1466       when executing "include", exp= from the target domain MUST NOT be used.
 1467     spec: 6.2/13
 1468     helo: mail.example.com
 1469     host: 1.2.3.4
 1470     mailfrom: foo@e7.example.com
 1471     result: fail
 1472     explanation: Correct!
 1473   redirect-cancels-prior-exp:
 1474     description: >-
 1475       when executing "redirect", exp= from the original domain MUST NOT be used.
 1476     spec: 6.2/13
 1477     helo: mail.example.com
 1478     host: 1.2.3.4
 1479     mailfrom: foo@e3.example.com
 1480     result: fail
 1481     explanation: See me.
 1482   invalid-modifier:
 1483     description: |
 1484       unknown-modifier = name "=" macro-string
 1485       name             = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." )
 1486     comment: >-
 1487       Unknown modifier name must begin with alpha.
 1488     spec: A/3
 1489     helo: mail.example.com
 1490     host: 1.2.3.4
 1491     mailfrom: foo@e5.example.com
 1492     result: permerror
 1493   empty-modifier-name:
 1494     description: |
 1495       name             = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." )
 1496     comment: >-
 1497       Unknown modifier name must not be empty.
 1498     spec: A/3
 1499     helo: mail.example.com
 1500     host: 1.2.3.4
 1501     mailfrom: foo@e6.example.com
 1502     result: permerror
 1503   dorky-sentinel:
 1504     description: >-
 1505       An implementation that uses a legal expansion as a sentinel.  We
 1506       cannot check them all, but we can check this one.
 1507     comment: >-
 1508       Spaces are allowed in local-part.
 1509     spec: 8.1/6
 1510     helo: mail.example.com
 1511     host: 1.2.3.4
 1512     mailfrom: "Macro Error@e8.example.com"
 1513     result: fail
 1514     explanation: Macro Error in implementation
 1515   exp-multiple-txt:
 1516     description: |
 1517       Ignore exp if multiple TXT records.
 1518     comment: >-
 1519       If domain-spec is empty, or there are any DNS processing errors (any
 1520       RCODE other than 0), or if no records are returned, or if more than one
 1521       record is returned, or if there are syntax errors in the explanation
 1522       string, then proceed as if no exp modifier was given.
 1523     spec: 6.2/4
 1524     helo: mail.example.com
 1525     host: 1.2.3.4
 1526     mailfrom: foo@e11.example.com
 1527     result: fail
 1528     explanation: DEFAULT
 1529   exp-no-txt:
 1530     description: |
 1531       Ignore exp if no TXT records.
 1532     comment: >-
 1533       If domain-spec is empty, or there are any DNS processing errors (any
 1534       RCODE other than 0), or if no records are returned, or if more than one
 1535       record is returned, or if there are syntax errors in the explanation
 1536       string, then proceed as if no exp modifier was given.
 1537     spec: 6.2/4
 1538     helo: mail.example.com
 1539     host: 1.2.3.4
 1540     mailfrom: foo@e22.example.com
 1541     result: fail
 1542     explanation: DEFAULT
 1543   exp-dns-error:
 1544     description: |
 1545       Ignore exp if DNS error.
 1546     comment: >-
 1547       If domain-spec is empty, or there are any DNS processing errors (any
 1548       RCODE other than 0), or if no records are returned, or if more than one
 1549       record is returned, or if there are syntax errors in the explanation
 1550       string, then proceed as if no exp modifier was given.
 1551     spec: 6.2/4
 1552     helo: mail.example.com
 1553     host: 1.2.3.4
 1554     mailfrom: foo@e21.example.com
 1555     result: fail
 1556     explanation: DEFAULT
 1557   exp-empty-domain:
 1558     description: |
 1559       PermError if exp= domain-spec is empty.
 1560     comment: >-
 1561       Section 6.2/4 says, "If domain-spec is empty, or there are any DNS
 1562       processing errors (any RCODE other than 0), or if no records are
 1563       returned, or if more than one record is returned, or if there are syntax
 1564       errors in the explanation string, then proceed as if no exp modifier was
 1565       given."  However, "if domain-spec is empty" conflicts with the grammar
 1566       given for the exp modifier.  This was reported as an erratum, and the
 1567       solution chosen was to report explicit "exp=" as PermError, but ignore
 1568       problems due to macro expansion, DNS, or invalid explanation string.
 1569     spec: 6.2/4
 1570     helo: mail.example.com
 1571     host: 1.2.3.4
 1572     mailfrom: foo@e12.example.com
 1573     result: permerror
 1574   explanation-syntax-error:
 1575     description: |
 1576       Ignore exp if the explanation string has a syntax error.
 1577     comment: >-
 1578       If domain-spec is empty, or there are any DNS processing errors (any
 1579       RCODE other than 0), or if no records are returned, or if more than one
 1580       record is returned, or if there are syntax errors in the explanation
 1581       string, then proceed as if no exp modifier was given.
 1582     spec: 6.2/4
 1583     helo: mail.example.com
 1584     host: 1.2.3.4
 1585     mailfrom: foo@e13.example.com
 1586     result: fail
 1587     explanation: DEFAULT
 1588   exp-syntax-error:
 1589     description: |
 1590       explanation      = "exp" "=" domain-spec
 1591     comment: >-
 1592       A literal application of the grammar causes modifier syntax
 1593       errors (except for macro syntax) to become unknown-modifier.
 1594       
 1595         modifier = explanation | redirect | unknown-modifier
 1596       
 1597       However, it is generally agreed, with precedent in other RFCs,
 1598       that unknown-modifier should not be "greedy", and should not
 1599       match known modifier names.  There should have been explicit
 1600       prose to this effect, and some has been proposed as an erratum.
 1601     spec: 6.2/1
 1602     helo: mail.example.com
 1603     host: 1.2.3.4
 1604     mailfrom: foo@e16.example.com
 1605     result: permerror
 1606   exp-twice:
 1607     description: |
 1608       exp= appears twice.
 1609     comment: >-
 1610       These two modifiers (exp,redirect) MUST NOT appear in a record more than
 1611       once each. If they do, then check_host() exits with a result of
 1612       "PermError".
 1613     spec: 6/2
 1614     helo: mail.example.com
 1615     host: 1.2.3.4
 1616     mailfrom: foo@e14.example.com
 1617     result: permerror
 1618   redirect-empty-domain:
 1619     description: |
 1620       redirect = "redirect" "=" domain-spec
 1621     comment: >-
 1622       Unlike for exp, there is no instruction to override the permerror
 1623       for an empty domain-spec (which is invalid syntax).
 1624     spec: 6.2/4
 1625     helo: mail.example.com
 1626     host: 1.2.3.4
 1627     mailfrom: foo@e18.example.com
 1628     result: permerror
 1629   redirect-twice:
 1630     description: |
 1631       redirect= appears twice.
 1632     comment: >-
 1633       These two modifiers (exp,redirect) MUST NOT appear in a record more than
 1634       once each. If they do, then check_host() exits with a result of
 1635       "PermError".
 1636     spec: 6/2
 1637     helo: mail.example.com
 1638     host: 1.2.3.4
 1639     mailfrom: foo@e15.example.com
 1640     result: permerror
 1641   unknown-modifier-syntax:
 1642     description: |
 1643       unknown-modifier = name "=" macro-string
 1644     comment: >-
 1645       Unknown modifiers must have valid macro syntax.
 1646     spec: A/3
 1647     helo: mail.example.com
 1648     host: 1.2.3.4
 1649     mailfrom: foo@e9.example.com
 1650     result: permerror
 1651   default-modifier-obsolete:
 1652     description: |
 1653       Unknown modifiers do not modify the RFC SPF result.
 1654     comment: >-
 1655       Some implementations may have a leftover default= modifier from
 1656       earlier drafts.
 1657     spec: 6/3
 1658     helo: mail.example.com
 1659     host: 1.2.3.4
 1660     mailfrom: foo@e19.example.com
 1661     result: neutral
 1662   default-modifier-obsolete2:
 1663     description: |
 1664       Unknown modifiers do not modify the RFC SPF result.
 1665     comment: >-
 1666       Some implementations may have a leftover default= modifier from
 1667       earlier drafts.
 1668     spec: 6/3
 1669     helo: mail.example.com
 1670     host: 1.2.3.4
 1671     mailfrom: foo@e20.example.com
 1672     result: neutral
 1673 zonedata:
 1674   mail.example.com:
 1675     - A: 1.2.3.4
 1676   e1.example.com:
 1677     - SPF: v=spf1 exp=exp1.example.com redirect=e2.example.com
 1678   e2.example.com:
 1679     - SPF: v=spf1 -all
 1680   e3.example.com:
 1681     - SPF: v=spf1 exp=exp1.example.com redirect=e4.example.com
 1682   e4.example.com:
 1683     - SPF: v=spf1 -all exp=exp2.example.com
 1684   exp1.example.com:
 1685     - TXT: No-see-um
 1686   exp2.example.com:
 1687     - TXT: See me.
 1688   exp3.example.com:
 1689     - TXT: Correct!
 1690   exp4.example.com:
 1691     - TXT: "%{l} in implementation"
 1692   e5.example.com:
 1693     - SPF: v=spf1 1up=foo
 1694   e6.example.com:
 1695     - SPF: v=spf1 =all
 1696   e7.example.com:
 1697     - SPF: v=spf1 include:e3.example.com -all exp=exp3.example.com
 1698   e8.example.com:
 1699     - SPF: v=spf1 -all exp=exp4.example.com
 1700   e9.example.com:
 1701     - SPF: v=spf1 -all foo=%abc
 1702   e10.example.com:
 1703     - SPF: v=spf1 redirect=erehwon.example.com
 1704   e11.example.com:
 1705     - SPF: v=spf1 -all exp=e11msg.example.com
 1706   e11msg.example.com:
 1707     - TXT: Answer a fool according to his folly.
 1708     - TXT: Do not answer a fool according to his folly.
 1709   e12.example.com:
 1710     - SPF: v=spf1 exp= -all
 1711   e13.example.com:
 1712     - SPF: v=spf1 exp=e13msg.example.com -all
 1713   e13msg.example.com:
 1714     - TXT: The %{x}-files.
 1715   e14.example.com:
 1716     - SPF: v=spf1 exp=e13msg.example.com -all exp=e11msg.example.com
 1717   e15.example.com:
 1718     - SPF: v=spf1 redirect=e12.example.com -all redirect=e12.example.com
 1719   e16.example.com:
 1720     - SPF: v=spf1 exp=-all
 1721   e17.example.com:
 1722     - SPF: v=spf1 redirect=-all ?all
 1723   e18.example.com:
 1724     - SPF: v=spf1 ?all redirect=
 1725   e19.example.com:
 1726     - SPF: v=spf1 default=pass
 1727   e20.example.com:
 1728     - SPF: "v=spf1 default=+"
 1729   e21.example.com:
 1730     - SPF: v=spf1 exp=e21msg.example.com -all
 1731   e21msg.example.com:
 1732     - TIMEOUT
 1733   e22.example.com:
 1734     - SPF: v=spf1 exp=mail.example.com -all
 1735 ---
 1736 description: Macro expansion rules
 1737 tests:
 1738   trailing-dot-domain:
 1739     spec: 8.1/16
 1740     description: >-
 1741       trailing dot is ignored for domains
 1742     helo: msgbas2x.cos.example.com
 1743     host: 192.168.218.40
 1744     mailfrom: test@example.com
 1745     result: pass
 1746   trailing-dot-exp:
 1747     spec: 8.1
 1748     description: >-
 1749       trailing dot is not removed from explanation
 1750     comment: >-
 1751       A simple way for an implementation to ignore trailing dots on
 1752       domains is to remove it when present.  But be careful not to
 1753       remove it for explanation text.
 1754     helo: msgbas2x.cos.example.com
 1755     host: 192.168.218.40
 1756     mailfrom: test@exp.example.com
 1757     result: fail
 1758     explanation: This is a test.
 1759   exp-only-macro-char:
 1760     spec: 8.1/8
 1761     description: >-
 1762       The following macro letters are allowed only in "exp" text: c, r, t
 1763     helo: msgbas2x.cos.example.com
 1764     host: 192.168.218.40
 1765     mailfrom: test@e2.example.com
 1766     result: permerror
 1767   invalid-macro-char:
 1768     spec: 8.1/9
 1769     description: >-
 1770       A '%' character not followed by a '{', '%', '-', or '_' character
 1771       is a syntax error.
 1772     helo: msgbas2x.cos.example.com
 1773     host: 192.168.218.40
 1774     mailfrom: test@e1.example.com
 1775     result: permerror
 1776   macro-mania-in-domain:
 1777     description: >-
 1778       macro-encoded percents (%%), spaces (%_), and URL-percent-encoded
 1779       spaces (%-)
 1780     spec: 8.1/3, 8.1/4
 1781     helo: mail.example.com
 1782     host: 1.2.3.4
 1783     mailfrom: test@e1a.example.com
 1784     result: pass
 1785   exp-txt-macro-char:
 1786     spec: 8.1/20
 1787     description: >-
 1788       For IPv4 addresses, both the "i" and "c" macros expand
 1789       to the standard dotted-quad format.
 1790     helo: msgbas2x.cos.example.com
 1791     host: 192.168.218.40
 1792     mailfrom: test@e3.example.com
 1793     result: fail
 1794     explanation: Connections from 192.168.218.40 not authorized.
 1795   domain-name-truncation:
 1796     spec: 8.1/25
 1797     description: >-
 1798       When the result of macro expansion is used in a domain name query, if the
 1799       expanded domain name exceeds 253 characters, the left side is truncated
 1800       to fit, by removing successive domain labels until the total length does
 1801       not exceed 253 characters.
 1802     helo: msgbas2x.cos.example.com
 1803     host: 192.168.218.40
 1804     mailfrom: test@somewhat.long.exp.example.com
 1805     result: fail
 1806     explanation: Congratulations!  That was tricky.
 1807   v-macro-ip4:
 1808     spec: 8.1/6
 1809     description: |-
 1810       v = the string "in-addr" if <ip> is ipv4, or "ip6" if <ip> is ipv6
 1811     helo: msgbas2x.cos.example.com
 1812     host: 192.168.218.40
 1813     mailfrom: test@e4.example.com
 1814     result: fail
 1815     explanation: 192.168.218.40 is queried as 40.218.168.192.in-addr.arpa
 1816   v-macro-ip6:
 1817     spec: 8.1/6
 1818     description: |-
 1819       v = the string "in-addr" if <ip> is ipv4, or "ip6" if <ip> is ipv6
 1820     helo: msgbas2x.cos.example.com
 1821     host: CAFE:BABE::1
 1822     mailfrom: test@e4.example.com
 1823     result: fail
 1824     explanation: cafe:babe::1 is queried as 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa
 1825   undef-macro:
 1826     spec: 8.1/6
 1827     description: >-
 1828       Allowed macros chars are 'slodipvh' plus 'crt' in explanation.
 1829     helo: msgbas2x.cos.example.com
 1830     host: CAFE:BABE::192.168.218.40
 1831     mailfrom: test@e5.example.com
 1832     result: permerror
 1833   p-macro-ip4-novalid:
 1834     spec: 8.1/22
 1835     description: |-
 1836       p = the validated domain name of <ip>
 1837     comment: >-
 1838       The PTR in this example does not validate.
 1839     helo: msgbas2x.cos.example.com
 1840     host: 192.168.218.40
 1841     mailfrom: test@e6.example.com
 1842     result: fail
 1843     explanation: connect from unknown
 1844   p-macro-ip4-valid:
 1845     spec: 8.1/22
 1846     description: |-
 1847       p = the validated domain name of <ip>
 1848     comment: >-
 1849       If a subdomain of the <domain> is present, it SHOULD be used.
 1850     helo: msgbas2x.cos.example.com
 1851     host: 192.168.218.41
 1852     mailfrom: test@e6.example.com
 1853     result: fail
 1854     explanation: connect from mx.example.com
 1855   p-macro-ip6-novalid:
 1856     spec: 8.1/22
 1857     description: |-
 1858       p = the validated domain name of <ip>
 1859     comment: >-
 1860       The PTR in this example does not validate.
 1861     helo: msgbas2x.cos.example.com
 1862     host: CAFE:BABE::1
 1863     mailfrom: test@e6.example.com
 1864     result: fail
 1865     explanation: connect from unknown
 1866   p-macro-ip6-valid:
 1867     spec: 8.1/22
 1868     description: |-
 1869       p = the validated domain name of <ip>
 1870     comment: >-
 1871       If a subdomain of the <domain> is present, it SHOULD be used.
 1872     helo: msgbas2x.cos.example.com
 1873     host: CAFE:BABE::3
 1874     mailfrom: test@e6.example.com
 1875     result: fail
 1876     explanation: connect from mx.example.com
 1877   p-macro-multiple:
 1878     spec: 8.1/22
 1879     description: |-
 1880       p = the validated domain name of <ip>
 1881     comment: >-
 1882       If a subdomain of the <domain> is present, it SHOULD be used.
 1883     helo: msgbas2x.cos.example.com
 1884     host: 192.168.218.42
 1885     mailfrom: test@e7.example.com
 1886     result: [pass, softfail]
 1887   upper-macro:
 1888     spec: 8.1/26
 1889     description: >-
 1890       Uppercased macros expand exactly as their lowercased equivalents,
 1891       and are then URL escaped.
 1892     helo: msgbas2x.cos.example.com
 1893     host: 192.168.218.42
 1894     mailfrom: jack&jill=up@e8.example.com
 1895     result: fail
 1896     explanation: http://example.com/why.html?l=jack%26jill%3Dup
 1897   hello-macro:
 1898     spec: 8.1/6
 1899     description: |-
 1900       h = HELO/EHLO domain
 1901     helo: msgbas2x.cos.example.com
 1902     host: 192.168.218.40
 1903     mailfrom: test@e9.example.com
 1904     result: pass
 1905   invalid-hello-macro:
 1906     spec: 8.1/2
 1907     description: |-
 1908       h = HELO/EHLO domain, but HELO is invalid
 1909     comment: >-
 1910       Domain-spec must end in either a macro, or a valid toplabel.
 1911       It is not correct to check syntax after macro expansion.
 1912     helo: "JUMPIN' JUPITER"
 1913     host: 192.168.218.40
 1914     mailfrom: test@e9.example.com
 1915     result: fail
 1916   hello-domain-literal:
 1917     spec: 8.1/2
 1918     description: |-
 1919       h = HELO/EHLO domain, but HELO is a domain literal
 1920     comment: >-
 1921       Domain-spec must end in either a macro, or a valid toplabel.
 1922       It is not correct to check syntax after macro expansion.
 1923     helo: "[192.168.218.40]"
 1924     host: 192.168.218.40
 1925     mailfrom: test@e9.example.com
 1926     result: fail
 1927   require-valid-helo:
 1928     spec: 8.1/6
 1929     description: >-
 1930       Example of requiring valid helo in sender policy.  This is a complex
 1931       policy testing several points at once.
 1932     helo: OEMCOMPUTER
 1933     host: 1.2.3.4
 1934     mailfrom: test@e10.example.com
 1935     result: fail
 1936   macro-reverse-split-on-dash:
 1937     spec: [8.1/15, 8.1/16, 8.1/17, 8.1/18]
 1938     description: >-
 1939       Macro value transformation (splitting on arbitrary characters, reversal,
 1940       number of right-hand parts to use)
 1941     helo: mail.example.com
 1942     host: 1.2.3.4
 1943     mailfrom: philip-gladstone-test@e11.example.com
 1944     result: pass
 1945 zonedata:
 1946   example.com.d.spf.example.com:
 1947     - SPF: v=spf1 redirect=a.spf.example.com
 1948   a.spf.example.com:
 1949     - SPF: v=spf1 include:o.spf.example.com. ~all
 1950   o.spf.example.com:
 1951     - SPF: v=spf1 ip4:192.168.218.40
 1952   msgbas2x.cos.example.com:
 1953     - A: 192.168.218.40
 1954   example.com:
 1955     - A: 192.168.90.76
 1956     - SPF: v=spf1 redirect=%{d}.d.spf.example.com.
 1957   exp.example.com:
 1958     - SPF: v=spf1 exp=msg.example.com. -all
 1959   msg.example.com:
 1960     - TXT: This is a test.
 1961   e1.example.com:
 1962     - SPF: v=spf1 -exists:%(ir).sbl.example.com ?all
 1963   e1a.example.com:
 1964     - SPF: "v=spf1 a:macro%%percent%_%_space%-url-space.example.com -all"
 1965   "macro%percent  space%20url-space.example.com":
 1966     - A: 1.2.3.4
 1967   e2.example.com:
 1968     - SPF: v=spf1 -all exp=%{r}.example.com
 1969   e3.example.com:
 1970     - SPF: v=spf1 -all exp=%{ir}.example.com
 1971   40.218.168.192.example.com:
 1972     - TXT: Connections from %{c} not authorized.
 1973   somewhat.long.exp.example.com:
 1974     - SPF: v=spf1 -all exp=foobar.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.%{o}.example.com
 1975   somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.somewhat.long.exp.example.com.example.com:
 1976     - TXT: Congratulations!  That was tricky.
 1977   e4.example.com:
 1978     - SPF: v=spf1 -all exp=e4msg.example.com
 1979   e4msg.example.com:
 1980     - TXT: "%{c} is queried as %{ir}.%{v}.arpa"
 1981   e5.example.com:
 1982     - SPF: v=spf1 a:%{a}.example.com -all
 1983   e6.example.com:
 1984     - SPF: v=spf1 -all exp=e6msg.example.com
 1985   e6msg.example.com:
 1986     - TXT: "connect from %{p}"
 1987   mx.example.com:
 1988     - A: 192.168.218.41
 1989     - A: 192.168.218.42
 1990     - AAAA: CAFE:BABE::2
 1991     - AAAA: CAFE:BABE::3
 1992   40.218.168.192.in-addr.arpa:
 1993     - PTR: mx.example.com
 1994   41.218.168.192.in-addr.arpa:
 1995     - PTR: mx.example.com
 1996   42.218.168.192.in-addr.arpa:
 1997     - PTR: mx.example.com
 1998     - PTR: mx.e7.example.com
 1999   1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa:
 2000     - PTR: mx.example.com
 2001   3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.E.B.A.B.E.F.A.C.ip6.arpa:
 2002     - PTR: mx.example.com
 2003   mx.e7.example.com:
 2004     - A: 192.168.218.42
 2005   mx.e7.example.com.should.example.com:
 2006     - A: 127.0.0.2
 2007   mx.example.com.ok.example.com:
 2008     - A: 127.0.0.2
 2009   e7.example.com:
 2010     - SPF: v=spf1 exists:%{p}.should.example.com ~exists:%{p}.ok.example.com
 2011   e8.example.com:
 2012     - SPF: v=spf1 -all exp=msg8.%{D2}
 2013   msg8.example.com:
 2014     - TXT: "http://example.com/why.html?l=%{L}"
 2015   e9.example.com:
 2016     - SPF: v=spf1 a:%{H} -all
 2017   e10.example.com:
 2018     - SPF: v=spf1 -include:_spfh.%{d2} ip4:1.2.3.0/24 -all
 2019   _spfh.example.com:
 2020     - SPF: v=spf1 -a:%{h} +all
 2021   e11.example.com:
 2022     - SPF: v=spf1 exists:%{i}.%{l2r-}.user.%{d2}
 2023   1.2.3.4.gladstone.philip.user.example.com:
 2024     - A: 127.0.0.2
 2025 ---
 2026 description: Processing limits
 2027 tests:
 2028   redirect-loop:
 2029     description: >-
 2030       SPF implementations MUST limit the number of mechanisms and modifiers
 2031       that do DNS lookups to at most 10 per SPF check.
 2032     spec: 10.1/6
 2033     helo: mail.example.com
 2034     host: 1.2.3.4
 2035     mailfrom: foo@e1.example.com
 2036     result: permerror
 2037   include-loop:
 2038     description: >-
 2039       SPF implementations MUST limit the number of mechanisms and modifiers
 2040       that do DNS lookups to at most 10 per SPF check.
 2041     spec: 10.1/6
 2042     helo: mail.example.com
 2043     host: 1.2.3.4
 2044     mailfrom: foo@e2.example.com
 2045     result: permerror
 2046   mx-limit:
 2047     description: >-
 2048       there MUST be a limit of no more than 10 MX looked up and checked.
 2049     comment: >-
 2050       The required result for this test was the subject of much
 2051       controversy.  Many felt that the RFC *should* have specified
 2052       permerror, but the consensus was that it failed to actually do so.
 2053       The preferred result reflects evaluating the 10 allowed MX records in the
 2054       order returned by the test data - or sorted via priority.
 2055       If testing with live DNS, the MX order may be random, and a pass
 2056       result would still be compliant.  The SPF result is effectively
 2057       random.
 2058     spec: 10.1/7
 2059     helo: mail.example.com
 2060     host: 1.2.3.5
 2061     mailfrom: foo@e4.example.com
 2062     result: [neutral, pass]
 2063   ptr-limit:
 2064     description: >-
 2065       there MUST be a limit of no more than 10 PTR looked up and checked.
 2066     comment: >-
 2067       The result of this test cannot be permerror not only because the
 2068       RFC does not specify it, but because the sender has no control over
 2069       the PTR records of spammers.
 2070       The preferred result reflects evaluating the 10 allowed PTR records in
 2071       the order returned by the test data.
 2072       If testing with live DNS, the PTR order may be random, and a pass
 2073       result would still be compliant.  The SPF result is effectively
 2074       randomized.
 2075     spec: 10.1/7
 2076     helo: mail.example.com
 2077     host: 1.2.3.5
 2078     mailfrom: foo@e5.example.com
 2079     result: [neutral, pass]
 2080   false-a-limit:
 2081     description: >-
 2082       unlike MX, PTR, there is no RR limit for A
 2083     comment: >-
 2084       There seems to be a tendency for developers to want to limit
 2085       A RRs in addition to MX and PTR.  These are IPs, not usable for
 2086       3rd party DoS attacks, and hence need no low limit.
 2087     spec: 10.1/7
 2088     helo: mail.example.com
 2089     host: 1.2.3.12
 2090     mailfrom: foo@e10.example.com
 2091     result: pass
 2092   mech-at-limit:
 2093     description: >-
 2094       SPF implementations MUST limit the number of mechanisms and modifiers
 2095       that do DNS lookups to at most 10 per SPF check.
 2096     spec: 10.1/6
 2097     helo: mail.example.com
 2098     host: 1.2.3.4
 2099     mailfrom: foo@e6.example.com
 2100     result: pass
 2101   mech-over-limit:
 2102     description: >-
 2103       SPF implementations MUST limit the number of mechanisms and modifiers
 2104       that do DNS lookups to at most 10 per SPF check.
 2105     comment: >-
 2106       We do not check whether an implementation counts mechanisms before
 2107       or after evaluation.  The RFC is not clear on this.
 2108     spec: 10.1/6
 2109     helo: mail.example.com
 2110     host: 1.2.3.4
 2111     mailfrom: foo@e7.example.com
 2112     result: permerror
 2113   include-at-limit:
 2114     description: >-
 2115       SPF implementations MUST limit the number of mechanisms and modifiers
 2116       that do DNS lookups to at most 10 per SPF check.
 2117     comment: >-
 2118       The part of the RFC that talks about MAY parse the entire record first
 2119       (4.6) is specific to syntax errors.  Processing limits is a different,
 2120       non-syntax issue.  Processing limits (10.1) specifically talks about
 2121       limits during a check.
 2122     spec: 10.1/6
 2123     helo: mail.example.com
 2124     host: 1.2.3.4
 2125     mailfrom: foo@e8.example.com
 2126     result: pass
 2127   include-over-limit:
 2128     description: >-
 2129       SPF implementations MUST limit the number of mechanisms and modifiers
 2130       that do DNS lookups to at most 10 per SPF check.
 2131     spec: 10.1/6
 2132     helo: mail.example.com
 2133     host: 1.2.3.4
 2134     mailfrom: foo@e9.example.com
 2135     result: permerror
 2136 zonedata:
 2137   mail.example.com:
 2138     - A: 1.2.3.4
 2139   e1.example.com:
 2140     - SPF: v=spf1 ip4:1.1.1.1 redirect=e1.example.com
 2141   e2.example.com:
 2142     - SPF: v=spf1 include:e3.example.com
 2143   e3.example.com:
 2144     - SPF: v=spf1 include:e2.example.com
 2145   e4.example.com:
 2146     - SPF: v=spf1 mx
 2147     - MX: [0, mail.example.com]
 2148     - MX: [1, mail.example.com]
 2149     - MX: [2, mail.example.com]
 2150     - MX: [3, mail.example.com]
 2151     - MX: [4, mail.example.com]
 2152     - MX: [5, mail.example.com]
 2153     - MX: [6, mail.example.com]
 2154     - MX: [7, mail.example.com]
 2155     - MX: [8, mail.example.com]
 2156     - MX: [9, mail.example.com]
 2157     - MX: [10, e4.example.com]
 2158     - A: 1.2.3.5
 2159   e5.example.com:
 2160     - SPF: v=spf1 ptr
 2161     - A: 1.2.3.5
 2162   5.3.2.1.in-addr.arpa:
 2163     - PTR: e1.example.com.
 2164     - PTR: e2.example.com.
 2165     - PTR: e3.example.com.
 2166     - PTR: e4.example.com.
 2167     - PTR: example.com.
 2168     - PTR: e6.example.com.
 2169     - PTR: e7.example.com.
 2170     - PTR: e8.example.com.
 2171     - PTR: e9.example.com.
 2172     - PTR: e10.example.com.
 2173     - PTR: e5.example.com.
 2174   e6.example.com:
 2175     - SPF: v=spf1 a mx a mx a mx a mx a ptr ip4:1.2.3.4 -all
 2176   e7.example.com:
 2177     - SPF: v=spf1 a mx a mx a mx a mx a ptr a ip4:1.2.3.4 -all
 2178   e8.example.com:
 2179     - SPF: v=spf1 a include:inc.example.com ip4:1.2.3.4 mx -all
 2180   inc.example.com:
 2181     - SPF: v=spf1 a a a a a a a a
 2182   e9.example.com:
 2183     - SPF: v=spf1 a include:inc.example.com a ip4:1.2.3.4 -all
 2184   e10.example.com:
 2185     - SPF: v=spf1 a -all
 2186     - A: 1.2.3.1
 2187     - A: 1.2.3.2
 2188     - A: 1.2.3.3
 2189     - A: 1.2.3.4
 2190     - A: 1.2.3.5
 2191     - A: 1.2.3.6
 2192     - A: 1.2.3.7
 2193     - A: 1.2.3.8
 2194     - A: 1.2.3.9
 2195     - A: 1.2.3.10
 2196     - A: 1.2.3.11
 2197     - A: 1.2.3.12