rfc4408.txt | draft-ietf-spfbis-4408bis-05.txt | |||
---|---|---|---|---|
Network Working Group M. Wong | Network Working Group S. Kitterman | |||
Request for Comments: 4408 W. Schlitt | Internet-Draft Kitterman Technical Services | |||
Sender Policy Framework (SPF) for | Obsoletes: 4408 (if approved) August 18, 2012 | |||
Authorizing Use of Domains in E-Mail, Version 1 | Intended status: Standards Track | |||
Expires: February 19, 2013 | ||||
Status of This Memo | Sender Policy Framework (SPF) for Authorizing Use of Domains in Email, | |||
Version 1 | ||||
draft-ietf-spfbis-4408bis-05.txt | ||||
This memo defines an Experimental Protocol for the Internet | Abstract | |||
community. It does not specify an Internet standard of any kind. | ||||
Discussion and suggestions for improvement are requested. | ||||
Distribution of this memo is unlimited. | ||||
Copyright Notice | Email on the Internet can be forged in a number of ways. In | |||
particular, existing protocols place no restriction on what a sending | ||||
host can use as the "MAIL FROM" of a message or the domain given on | ||||
the SMTP HELO/EHLO commands. This document describes version 1 of | ||||
the Sender Policy Framework (SPF) protocol, whereby a domain can | ||||
explicitly authorize the hosts that are allowed to use its domain | ||||
name, and a receiving host can check such authorization. | ||||
Copyright (C) The Internet Society (2006). | This document obsoletes RFC4408. | |||
IESG Note | Status of this Memo | |||
The following documents (RFC 4405, RFC 4406, RFC 4407, and RFC 4408) | This Internet-Draft is submitted in full conformance with the | |||
are published simultaneously as Experimental RFCs, although there is | provisions of BCP 78 and BCP 79. | |||
no general technical consensus and efforts to reconcile the two | ||||
approaches have failed. As such, these documents have not received | ||||
full IETF review and are published "AS-IS" to document the different | ||||
approaches as they were considered in the MARID working group. | ||||
The IESG takes no position about which approach is to be preferred | Internet-Drafts are working documents of the Internet Engineering | |||
and cautions the reader that there are serious open issues for each | Task Force (IETF). Note that other groups may also distribute | |||
approach and concerns about using them in tandem. The IESG believes | working documents as Internet-Drafts. The list of current Internet- | |||
that documenting the different approaches does less harm than not | Drafts is at http://datatracker.ietf.org/drafts/current/. | |||
documenting them. | ||||
Note that the Sender ID experiment may use DNS records that may have | Internet-Drafts are draft documents valid for a maximum of six months | |||
been created for the current SPF experiment or earlier versions in | and may be updated, replaced, or obsoleted by other documents at any | |||
this set of experiments. Depending on the content of the record, | time. It is inappropriate to use Internet-Drafts as reference | |||
this may mean that Sender-ID heuristics would be applied incorrectly | material or to cite them other than as "work in progress." | |||
to a message. Depending on the actions associated by the recipient | ||||
with those heuristics, the message may not be delivered or may be | ||||
discarded on receipt. | ||||
Participants relying on Sender ID experiment DNS records are warned | This Internet-Draft will expire on February 19, 2013. | |||
that they may lose valid messages in this set of circumstances. | ||||
aParticipants publishing SPF experiment DNS records should consider | ||||
the advice given in section 3.4 of RFC 4406 and may wish to publish | ||||
both v=spf1 and spf2.0 records to avoid the conflict. | ||||
Participants in the Sender-ID experiment need to be aware that the | Copyright Notice | |||
way Resent-* header fields are used will result in failure to receive | ||||
legitimate email when interacting with standards-compliant systems | ||||
(specifically automatic forwarders which comply with the standards by | ||||
not adding Resent-* headers, and systems which comply with RFC 822 | ||||
but have not yet implemented RFC 2822 Resent-* semantics). It would | ||||
be inappropriate to advance Sender-ID on the standards track without | ||||
resolving this interoperability problem. | ||||
The community is invited to observe the success or failure of the two | Copyright (c) 2012 IETF Trust and the persons identified as the | |||
approaches during the two years following publication, in order that | document authors. All rights reserved. | |||
a community consensus can be reached in the future. | ||||
Abstract | This document is subject to BCP 78 and the IETF Trust's Legal | |||
Provisions Relating to IETF Documents | ||||
(http://trustee.ietf.org/license-info) in effect on the date of | ||||
publication of this document. Please review these documents | ||||
carefully, as they describe your rights and restrictions with respect | ||||
to this document. Code Components extracted from this document must | ||||
include Simplified BSD License text as described in Section 4.e of | ||||
the Trust Legal Provisions and are provided without warranty as | ||||
described in the Simplified BSD License. | ||||
E-mail on the Internet can be forged in a number of ways. In | This document may contain material from IETF Documents or IETF | |||
particular, existing protocols place no restriction on what a sending | Contributions published or made publicly available before November | |||
host can use as the reverse-path of a message or the domain given on | 10, 2008. The person(s) controlling the copyright in some of this | |||
the SMTP HELO/EHLO commands. This document describes version 1 of | material may not have granted the IETF Trust the right to allow | |||
the Sender Policy Framework (SPF) protocol, whereby a domain may | modifications of such material outside the IETF Standards Process. | |||
explicitly authorize the hosts that are allowed to use its domain | Without obtaining an adequate license from the person(s) controlling | |||
name, and a receiving host may check such authorization. | the copyright in such materials, this document may not be modified | |||
outside the IETF Standards Process, and derivative works of it may | ||||
not be created outside the IETF Standards Process, except to format | ||||
it for publication as an RFC or to translate it into languages other | ||||
than English. | ||||
Table of Contents | Table of Contents | |||
1. Introduction ....................................................4 | 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . 6 | |||
1.1. Protocol Status ............................................4 | 1.1. Protocol Status . . . . . . . . . . . . . . . . . . . . . 6 | |||
1.2. Terminology ................................................5 | 1.2. Experimental History . . . . . . . . . . . . . . . . . . . 7 | |||
2. Operation .......................................................5 | 1.3. Terminology . . . . . . . . . . . . . . . . . . . . . . . 7 | |||
2.1. The HELO Identity ..........................................5 | 1.3.1. Keywords . . . . . . . . . . . . . . . . . . . . . . . 7 | |||
2.2. The MAIL FROM Identity .....................................5 | 1.3.2. Imported Definitions . . . . . . . . . . . . . . . . . 7 | |||
2.3. Publishing Authorization ...................................6 | 1.3.3. Mail From Definition . . . . . . . . . . . . . . . . . 7 | |||
2.4. Checking Authorization .....................................6 | 1.3.4. HELO Definition . . . . . . . . . . . . . . . . . . . 8 | |||
2.5. Interpreting the Result ....................................7 | 1.3.5. Deprecated . . . . . . . . . . . . . . . . . . . . . . 8 | |||
2.5.1. None ................................................8 | 2. Operation . . . . . . . . . . . . . . . . . . . . . . . . . . 9 | |||
2.5.2. Neutral .............................................8 | 2.1. The "HELO" Identity . . . . . . . . . . . . . . . . . . . 9 | |||
2.5.3. Pass ................................................8 | 2.2. The "MAIL FROM" Identity . . . . . . . . . . . . . . . . . 9 | |||
2.5.4. Fail ................................................8 | 2.3. Publishing Authorization . . . . . . . . . . . . . . . . . 9 | |||
2.5.5. SoftFail ............................................9 | 2.4. Checking Authorization . . . . . . . . . . . . . . . . . . 10 | |||
2.5.6. TempError ...........................................9 | 2.5. Interpreting the Result . . . . . . . . . . . . . . . . . 11 | |||
2.5.7. PermError ...........................................9 | 2.5.1. None . . . . . . . . . . . . . . . . . . . . . . . . . 12 | |||
3. SPF Records .....................................................9 | 2.5.2. Neutral . . . . . . . . . . . . . . . . . . . . . . . 12 | |||
3.1. Publishing ................................................10 | 2.5.3. Pass . . . . . . . . . . . . . . . . . . . . . . . . . 12 | |||
3.1.1. DNS Resource Record Types ..........................10 | 2.5.4. Fail . . . . . . . . . . . . . . . . . . . . . . . . . 12 | |||
3.1.2. Multiple DNS Records ...............................11 | 2.5.5. Softfail . . . . . . . . . . . . . . . . . . . . . . . 13 | |||
3.1.3. Multiple Strings in a Single DNS record ............11 | 2.5.6. TempError . . . . . . . . . . . . . . . . . . . . . . 13 | |||
3.1.4. Record Size ........................................11 | 2.5.7. PermError . . . . . . . . . . . . . . . . . . . . . . 13 | |||
3.1.5. Wildcard Records ...................................11 | 3. SPF Records . . . . . . . . . . . . . . . . . . . . . . . . . 14 | |||
4. The check_host() Function ......................................12 | 3.1. DNS Resource Records . . . . . . . . . . . . . . . . . . . 14 | |||
4.1. Arguments .................................................12 | 3.2. Multiple DNS Records . . . . . . . . . . . . . . . . . . . 14 | |||
4.2. Results ...................................................13 | 3.3. Multiple Strings in a Single DNS record . . . . . . . . . 15 | |||
4.3. Initial Processing ........................................13 | 3.4. Record Size . . . . . . . . . . . . . . . . . . . . . . . 15 | |||
4.4. Record Lookup .............................................13 | 3.5. Wildcard Records . . . . . . . . . . . . . . . . . . . . . 15 | |||
4.5. Selecting Records .........................................13 | 4. The check_host() Function . . . . . . . . . . . . . . . . . . 17 | |||
4.6. Record Evaluation .........................................14 | 4.1. Arguments . . . . . . . . . . . . . . . . . . . . . . . . 17 | |||
4.6.1. Term Evaluation ....................................14 | 4.2. Results . . . . . . . . . . . . . . . . . . . . . . . . . 17 | |||
4.6.2. Mechanisms .........................................15 | 4.3. Initial Processing . . . . . . . . . . . . . . . . . . . . 17 | |||
4.6.3. Modifiers ..........................................15 | 4.4. Record Lookup . . . . . . . . . . . . . . . . . . . . . . 18 | |||
4.7. Default Result ............................................16 | 4.5. Selecting Records . . . . . . . . . . . . . . . . . . . . 18 | |||
4.8. Domain Specification ......................................16 | 4.6. Record Evaluation . . . . . . . . . . . . . . . . . . . . 18 | |||
5. Mechanism Definitions ..........................................16 | 4.6.1. Term Evaluation . . . . . . . . . . . . . . . . . . . 19 | |||
5.1. "all" .....................................................17 | 4.6.2. Mechanisms . . . . . . . . . . . . . . . . . . . . . . 19 | |||
5.2. "include" .................................................18 | 4.6.3. Modifiers . . . . . . . . . . . . . . . . . . . . . . 20 | |||
5.3. "a" .......................................................19 | 4.6.4. DNS Lookup Limits . . . . . . . . . . . . . . . . . . 20 | |||
5.4. "mx" ......................................................20 | 4.7. Default Result . . . . . . . . . . . . . . . . . . . . . . 21 | |||
5.5. "ptr" .....................................................20 | 4.8. Domain Specification . . . . . . . . . . . . . . . . . . . 21 | |||
5.6. "ip4" and "ip6" ...........................................21 | 5. Mechanism Definitions . . . . . . . . . . . . . . . . . . . . 22 | |||
5.7. "exists" ..................................................22 | 5.1. "all" . . . . . . . . . . . . . . . . . . . . . . . . . . 23 | |||
6. Modifier Definitions ...........................................22 | 5.2. "include" . . . . . . . . . . . . . . . . . . . . . . . . 23 | |||
6.1. redirect: Redirected Query ................................23 | 5.3. "a" . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 | |||
6.2. exp: Explanation ..........................................23 | 5.4. "mx" . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 | |||
7. The Received-SPF Header Field ..................................25 | 5.5. "ptr" (deprecated) . . . . . . . . . . . . . . . . . . . . 25 | |||
8. Macros .........................................................27 | 5.6. "ip4" and "ip6" . . . . . . . . . . . . . . . . . . . . . 27 | |||
8.1. Macro Definitions .........................................27 | 5.7. "exists" . . . . . . . . . . . . . . . . . . . . . . . . . 27 | |||
8.2. Expansion Examples ........................................30 | 6. Modifier Definitions . . . . . . . . . . . . . . . . . . . . . 29 | |||
9. Implications ...................................................31 | 6.1. redirect: Redirected Query . . . . . . . . . . . . . . . . 29 | |||
9.1. Sending Domains ...........................................31 | 6.2. exp: Explanation . . . . . . . . . . . . . . . . . . . . . 30 | |||
9.2. Mailing Lists .............................................32 | 7. Recording The Result . . . . . . . . . . . . . . . . . . . . . 32 | |||
9.3. Forwarding Services and Aliases ...........................32 | 7.1. The Received-SPF Header Field . . . . . . . . . . . . . . 32 | |||
9.4. Mail Services .............................................34 | 7.2. SPF Results in the Authentication-Results Header Field . . 34 | |||
9.5. MTA Relays ................................................34 | 8. Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 | |||
10. Security Considerations .......................................35 | 8.1. Macro Definitions . . . . . . . . . . . . . . . . . . . . 36 | |||
10.1. Processing Limits ........................................35 | 8.2. Expansion Examples . . . . . . . . . . . . . . . . . . . . 39 | |||
10.2. SPF-Authorized E-Mail May Contain Other False | 9. Implications . . . . . . . . . . . . . . . . . . . . . . . . . 41 | |||
Identities ...............................................37 | 9.1. Sending Domains . . . . . . . . . . . . . . . . . . . . . 41 | |||
10.3. Spoofed DNS and IP Data ..................................37 | 9.1.1. DNS Resource Considerations . . . . . . . . . . . . . 41 | |||
10.4. Cross-User Forgery .......................................37 | 9.1.2. Administrator's Considerations . . . . . . . . . . . . 42 | |||
10.5. Untrusted Information Sources ............................38 | 9.1.3. Bounces . . . . . . . . . . . . . . . . . . . . . . . 43 | |||
10.6. Privacy Exposure .........................................38 | 9.2. Mediators . . . . . . . . . . . . . . . . . . . . . . . . 43 | |||
11. Contributors and Acknowledgements .............................38 | 9.2.1. Mailing Lists . . . . . . . . . . . . . . . . . . . . 43 | |||
12. IANA Considerations ...........................................39 | 9.2.2. Forwarding Services and Aliases . . . . . . . . . . . 44 | |||
12.1. The SPF DNS Record Type ..................................39 | 9.2.3. Mail Services . . . . . . . . . . . . . . . . . . . . 46 | |||
12.2. The Received-SPF Mail Header Field .......................39 | 9.2.4. MTA Relays . . . . . . . . . . . . . . . . . . . . . . 46 | |||
13. References ....................................................39 | 9.3. Receivers . . . . . . . . . . . . . . . . . . . . . . . . 47 | |||
13.1. Normative References .....................................39 | 9.3.1. Policy For SPF Pass . . . . . . . . . . . . . . . . . 47 | |||
13.2. Informative References ...................................40 | 9.3.2. Policy For SPF Fail . . . . . . . . . . . . . . . . . 47 | |||
Appendix A. Collected ABNF .......................................42 | 9.3.3. Policy For SPF Permerror . . . . . . . . . . . . . . . 47 | |||
Appendix B. Extended Examples ....................................44 | 10. Security Considerations . . . . . . . . . . . . . . . . . . . 49 | |||
B.1. Simple Examples ..........................................44 | 10.1. Processing Limits . . . . . . . . . . . . . . . . . . . . 49 | |||
B.2. Multiple Domain Example ..................................45 | 10.2. SPF-Authorized Email May Contain Other False Identities . 49 | |||
B.3. DNSBL Style Example ......................................46 | 10.3. Spoofed DNS and IP Data . . . . . . . . . . . . . . . . . 50 | |||
B.4. Multiple Requirements Example ............................46 | 10.4. Cross-User Forgery . . . . . . . . . . . . . . . . . . . . 50 | |||
10.5. Untrusted Information Sources . . . . . . . . . . . . . . 50 | ||||
10.5.1. Recorded Results . . . . . . . . . . . . . . . . . . . 50 | ||||
10.5.2. External Explanations . . . . . . . . . . . . . . . . 51 | ||||
10.5.3. Macro Expansion . . . . . . . . . . . . . . . . . . . 51 | ||||
10.6. Privacy Exposure . . . . . . . . . . . . . . . . . . . . . 51 | ||||
11. Contributors and Acknowledgements . . . . . . . . . . . . . . 52 | ||||
12. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 53 | ||||
12.1. The SPF DNS Record Type . . . . . . . . . . . . . . . . . 53 | ||||
12.2. The Received-SPF Mail Header Field . . . . . . . . . . . . 53 | ||||
12.3. SPF Modifier Registration . . . . . . . . . . . . . . . . 53 | ||||
13. References . . . . . . . . . . . . . . . . . . . . . . . . . . 54 | ||||
13.1. Normative References . . . . . . . . . . . . . . . . . . . 54 | ||||
13.2. Informative References . . . . . . . . . . . . . . . . . . 55 | ||||
Appendix A. Collected ABNF . . . . . . . . . . . . . . . . . . . 57 | ||||
Appendix B. Extended Examples . . . . . . . . . . . . . . . . . . 60 | ||||
B.1. Simple Examples . . . . . . . . . . . . . . . . . . . . . 60 | ||||
B.2. Multiple Domain Example . . . . . . . . . . . . . . . . . 61 | ||||
B.3. DNSBL Style Example . . . . . . . . . . . . . . . . . . . 62 | ||||
B.4. Multiple Requirements Example . . . . . . . . . . . . . . 62 | ||||
Appendix C. Change History . . . . . . . . . . . . . . . . . . . 63 | ||||
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 66 | ||||
1. Introduction | 1. Introduction | |||
The current E-Mail infrastructure has the property that any host | The current email infrastructure has the property that any host | |||
injecting mail into the mail system can identify itself as any domain | injecting mail into the system can use any DNS domain name it wants | |||
name it wants. Hosts can do this at a variety of levels: in | in each of the various identifiers specified by [RFC5321] and | |||
particular, the session, the envelope, and the mail headers. | [RFC5322]. Although this feature is desirable in some circumstances, | |||
Although this feature is desirable in some circumstances, it is a | it is a major obstacle to reducing Unsolicited Bulk email (UBE, aka | |||
major obstacle to reducing Unsolicited Bulk E-Mail (UBE, aka spam). | spam). Furthermore, many domain owning ADMDs (ADministrative | |||
Furthermore, many domain name holders are understandably concerned | Management Domains, see [RFC5598]) are understandably concerned about | |||
about the ease with which other entities may make use of their domain | the ease with which other entities can make use of their domain | |||
names, often with malicious intent. | names, often with malicious intent. | |||
This document defines a protocol by which domain owners may authorize | This document defines a protocol by which ADMDs can authorize hosts | |||
hosts to use their domain name in the "MAIL FROM" or "HELO" identity. | to use their domain names in the "MAIL FROM" or "HELO" identities. | |||
Compliant domain holders publish Sender Policy Framework (SPF) | Compliant ADMDs publish Sender Policy Framework (SPF) records in DNS | |||
records specifying which hosts are permitted to use their names, and | specifying which hosts are permitted to use their names, and | |||
compliant mail receivers use the published SPF records to test the | compliant mail receivers use the published SPF records to test the | |||
authorization of sending Mail Transfer Agents (MTAs) using a given | authorization of sending Mail Transfer Agents (MTAs) using a given | |||
"HELO" or "MAIL FROM" identity during a mail transaction. | "HELO" or "MAIL FROM" identity during a mail transaction. | |||
An additional benefit to mail receivers is that after the use of an | An additional benefit to mail receivers is that after the use of an | |||
identity is verified, local policy decisions about the mail can be | identity is verified, local policy decisions about the mail can be | |||
made based on the sender's domain, rather than the host's IP address. | made based on the sender's domain, rather than the host's IP address. | |||
This is advantageous because reputation of domain names is likely to | This is advantageous because reputation of domain names is likely to | |||
be more accurate than reputation of host IP addresses. Furthermore, | be more accurate than reputation of host IP addresses. Furthermore, | |||
if a claimed identity fails verification, local policy can take | if a claimed identity fails verification, local policy can take | |||
stronger action against such E-Mail, such as rejecting it. | stronger action against such email, such as rejecting it. | |||
1.1. Protocol Status | 1.1. Protocol Status | |||
SPF has been in development since the summer of 2003 and has seen | SPF has been in development since the summer of 2003 and has seen | |||
deployment beyond the developers beginning in December 2003. The | deployment beyond the developers beginning in December 2003. The | |||
design of SPF slowly evolved until the spring of 2004 and has since | design of SPF slowly evolved until the spring of 2004 and has since | |||
stabilized. There have been quite a number of forms of SPF, some | stabilized. There have been quite a number of forms of SPF, some | |||
written up as documents, some submitted as Internet Drafts, and many | written up as documents, some submitted as Internet Drafts, and many | |||
discussed and debated in development forums. | discussed and debated in development forums. The protocol was | |||
originally defined in [RFC4408], which this document replaces. | ||||
The goal of this document is to clearly document the protocol defined | The goal of this work is to clearly document the protocol defined by | |||
by earlier draft specifications of SPF as used in existing | earlier draft specifications of SPF as used in existing | |||
implementations. This conception of SPF is sometimes called "SPF | implementations. This conception of SPF is sometimes called "SPF | |||
Classic". It is understood that particular implementations and | Classic". It is understood that particular implementations and | |||
deployments may differ from, and build upon, this work. It is hoped | deployments will differ from, and build upon, this work. It is hoped | |||
that we have nonetheless captured the common understanding of SPF | that we have nonetheless captured the common understanding of SPF | |||
version 1. | version 1. | |||
1.2. Terminology | 1.2. Experimental History | |||
This document updates and replaces RFC 4408 that was part of a group | ||||
of simultaneously published Experimental RFCs (RFC 4405, RFC 4406, | ||||
RFC 4407, and RFC 4408) in 2006. At that time the IESG requested the | ||||
community observe the success or failure of the two approaches | ||||
documented in these RFCs during the two years following publication, | ||||
in order that a community consensus could be reached in the future. | ||||
SPF is widely deployed by large and small email providers alike. | ||||
There are multiple, interoperable implementations. | ||||
For SPF (as documented in RFC 4408) a careful effort was made to | ||||
collect and document lessons learned and errata during the two year | ||||
period. The errata list has been stable (no new submissions) and | ||||
only minor protocol lessons learned were identified. Resolution of | ||||
the IESG's experiment is documented in [RFC6686]. | ||||
1.3. Terminology | ||||
1.3.1. Keywords | ||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", | |||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this | "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and | |||
document are to be interpreted as described in [RFC2119]. | "OPTIONAL" in this document are to be interpreted as described in | |||
[RFC2119]. | ||||
1.3.2. Imported Definitions | ||||
The ABNF tokens "ALPHA", "DIGIT", and "SP" are defined in [RFC5234]. | ||||
The token "local-part" is defined in [RFC5321]. | ||||
"dot-atom", "quoted-string", "comment", "CFWS", "FWS", and "CRLF" are | ||||
defined in [RFC5322]. | ||||
1.3.3. Mail From Definition | ||||
This document is concerned with the portion of a mail message | This document is concerned with the portion of a mail message | |||
commonly called "envelope sender", "return path", "reverse path", | commonly called "envelope sender", "return path", "reverse path", | |||
"bounce address", "2821 FROM", or "MAIL FROM". Since these terms are | "bounce address", "5321 FROM", "MAIL FROM", or RFC5321.MailFrom. | |||
either not well defined or often used casually, this document defines | Since these terms are either not well defined or often used casually, | |||
the "MAIL FROM" identity in Section 2.2. Note that other terms that | this document uses "MAIL FROM" for consistency. This means the | |||
may superficially look like the common terms, such as "reverse-path", | RFC5321.MailFrom as defined in [RFC5598]. Note that other terms that | |||
are used only with the defined meanings from normative documents. | might superficially look like the common terms, such as "reverse- | |||
path", are used only with the defined meanings from normative | ||||
documents. | ||||
2. Operation | 1.3.4. HELO Definition | |||
2.1. The HELO Identity | This document also makes use of the HELO/EHLO identity. The "HELO" | |||
identity derives from either the SMTP HELO or EHLO command (see | ||||
[RFC5321]). Since HELO and EHLO can, in many cases, be used | ||||
interchangeably, they are identified commonly as "HELO" in this | ||||
document. This means RFC5321.HELO/.EHLO as defined in [RFC5598]. | ||||
These commands supply the identity of the SMTP client (sending host) | ||||
for the SMTP session. | ||||
The "HELO" identity derives from either the SMTP HELO or EHLO command | 1.3.5. Deprecated | |||
(see [RFC2821]). These commands supply the SMTP client (sending | ||||
host) for the SMTP session. Note that requirements for the domain | ||||
presented in the EHLO or HELO command are not always clear to the | ||||
sending party, and SPF clients must be prepared for the "HELO" | ||||
identity to be malformed or an IP address literal. At the time of | ||||
this writing, many legitimate E-Mails are delivered with invalid HELO | ||||
domains. | ||||
It is RECOMMENDED that SPF clients not only check the "MAIL FROM" | There are [RFC4408] features that are marked "deprecated". In the | |||
context of this document, deprecated means that senders SHOULD NOT | ||||
publish SPF records that make use of such features because they might | ||||
be removed entirely in future updates to the protocol. Such features | ||||
do, however, remain part of the SPF protocol and receiving systems | ||||
MUST support them unless this document explicitly says otherwise. | ||||
2. Operation | ||||
2.1. The "HELO" Identity | ||||
It is RECOMMENDED that SPF verifiers not only check the "MAIL FROM" | ||||
identity, but also separately check the "HELO" identity by applying | identity, but also separately check the "HELO" identity by applying | |||
the check_host() function (Section 4) to the "HELO" identity as the | the check_host() function (Section 4) to the "HELO" identity as the | |||
<sender>. | <sender>. Checking "HELO" promotes consistency of results and can | |||
reduce DNS resource usage. Additionally, since SPF records published | ||||
for "HELO" identities refer to a single host, when available, they | ||||
are a very reliable source of host authorization status. | ||||
2.2. The MAIL FROM Identity | Note that requirements for the domain presented in the EHLO or HELO | |||
command are not always clear to the sending party, and SPF verifiers | ||||
MUST be prepared for the "HELO" identity to be malformed or an IP | ||||
address literal. SPF checks can only be performed when the "HELO" | ||||
string is a valid fully qualified domain. | ||||
The "MAIL FROM" identity derives from the SMTP MAIL command (see | 2.2. The "MAIL FROM" Identity | |||
[RFC2821]). This command supplies the "reverse-path" for a message, | ||||
which generally consists of the sender mailbox, and is the mailbox to | ||||
which notification messages are to be sent if there are problems | ||||
delivering the message. | ||||
[RFC2821] allows the reverse-path to be null (see Section 4.5.5 in | SPF verifiers MUST check the ""MAIL FROM" identity if a completed | |||
RFC 2821). In this case, there is no explicit sender mailbox, and | "HELO" check has not reached a definitive policy result by applying | |||
the check_host() function to the "MAIL FROM" identity as the | ||||
<sender>. | ||||
[RFC5321] allows the reverse-path to be null (see Section 4.5.5 in | ||||
[RFC5321]). In this case, there is no explicit sender mailbox, and | ||||
such a message can be assumed to be a notification message from the | such a message can be assumed to be a notification message from the | |||
mail system itself. When the reverse-path is null, this document | mail system itself. When the reverse-path is null, this document | |||
defines the "MAIL FROM" identity to be the mailbox composed of the | defines the "MAIL FROM" identity to be the mailbox composed of the | |||
localpart "postmaster" and the "HELO" identity (which may or may not | local-part "postmaster" and the "HELO" identity (which might or might | |||
have been checked separately before). | not have been checked separately before). | |||
SPF clients MUST check the "MAIL FROM" identity. SPF clients check | ||||
the "MAIL FROM" identity by applying the check_host() function to the | ||||
"MAIL FROM" identity as the <sender>. | ||||
2.3. Publishing Authorization | 2.3. Publishing Authorization | |||
An SPF-compliant domain MUST publish a valid SPF record as described | An SPF-compliant domain MUST publish a valid SPF record as described | |||
in Section 3. This record authorizes the use of the domain name in | in Section 3. This record authorizes the use of the domain name in | |||
the "HELO" and "MAIL FROM" identities by the MTAs it specifies. | the "HELO" and "MAIL FROM" identities by the MTAs it specifies. | |||
If domain owners choose to publish SPF records, it is RECOMMENDED | SPF results can be used to make both positive (source is authorized) | |||
that they end in "-all", or redirect to other records that do, so | and negative (source is not authorized) determinations. If domain | |||
that a definitive determination of authorization can be made. | owners choose to publish SPF records and want to support receivers | |||
making negative authorization determinations, then they MUST publish | ||||
records that end in "-all", or redirect to other records that do, | ||||
otherwise, no definitive determination of authorization can be made. | ||||
Potential issues and mitigations associated with negative | ||||
determinations are discussed in Section 9. | ||||
Domain holders may publish SPF records that explicitly authorize no | Domain holders can publish SPF records that explicitly authorize no | |||
hosts if mail should never originate using that domain. | hosts if mail is not expected to originate using that domain. | |||
When changing SPF records, care must be taken to ensure that there is | When changing SPF records, care must be taken to ensure that there is | |||
a transition period so that the old policy remains valid until all | a transition period so that the old policy remains valid until all | |||
legitimate E-Mail has been checked. | legitimate email can reasonably expect to have been checked. This | |||
can be as much as 30 days. | ||||
2.4. Checking Authorization | 2.4. Checking Authorization | |||
A mail receiver can perform a set of SPF checks for each mail message | A mail receiver can perform a set of SPF checks for each mail message | |||
it receives. An SPF check tests the authorization of a client host | it receives. An SPF check tests the authorization of a client host | |||
to emit mail with a given identity. Typically, such checks are done | to emit mail with a given identity. Typically, such checks are done | |||
by a receiving MTA, but can be performed elsewhere in the mail | by a receiving MTA, but can be performed elsewhere in the mail | |||
processing chain so long as the required information is available and | processing chain so long as the required information is available and | |||
reliable. At least the "MAIL FROM" identity MUST be checked, but it | reliable. At least the "MAIL FROM" identity MUST be checked, but it | |||
is RECOMMENDED that the "HELO" identity also be checked beforehand. | is RECOMMENDED that the "HELO" identity also be checked beforehand. | |||
Without explicit approval of the domain owner, checking other | Without explicit approval of the domain owner, checking other | |||
identities against SPF version 1 records is NOT RECOMMENDED because | identities against SPF version 1 records is NOT RECOMMENDED because | |||
there are cases that are known to give incorrect results. For | there are cases that are known to give incorrect results. For | |||
example, almost all mailing lists rewrite the "MAIL FROM" identity | example, almost all mailing lists rewrite the "MAIL FROM" identity | |||
(see Section 9.2), but some do not change any other identities in the | (see Section 9.2.1), but some do not change any other identities in | |||
message. The scenario described in Section 9.3, sub-section 1.2, is | the message. The scenario described in Section 9.2.2, sub-section | |||
another example. Documents that define other identities should | 1.2, is another example. Documents that define other identities will | |||
define the method for explicit approval. | have to define the method for explicit approval. | |||
It is possible that mail receivers will use the SPF check as part of | It is possible that mail receivers will use the SPF check as part of | |||
a larger set of tests on incoming mail. The results of other tests | a larger set of tests on incoming mail. The results of other tests | |||
may influence whether or not a particular SPF check is performed. | might influence whether or not a particular SPF check is performed. | |||
For example, finding the sending host's IP address on a local white | For example, finding the sending host's IP address on a local white | |||
list may cause all other tests to be skipped and all mail from that | list might cause all other tests to be skipped and all mail from that | |||
host to be accepted. | host to be accepted. | |||
When a mail receiver decides to perform an SPF check, it MUST use a | When a mail receiver decides to perform an SPF check, it MUST use a | |||
correctly-implemented check_host() function (Section 4) evaluated | correctly-implemented check_host() function (Section 4) evaluated | |||
with the correct parameters. Although the test as a whole is | with the correct parameters. Although the test as a whole is | |||
optional, once it has been decided to perform a test it must be | optional, once it has been decided to perform a test it must be | |||
performed as specified so that the correct semantics are preserved | performed as specified so that the correct semantics are preserved | |||
between publisher and receiver. | between publisher and receiver. | |||
To make the test, the mail receiver MUST evaluate the check_host() | To make the test, the mail receiver MUST evaluate the check_host() | |||
function with the arguments set as follows: | function with the arguments set as follows: | |||
<ip> - the IP address of the SMTP client that is emitting the | <ip> - the IP address of the SMTP client that is emitting the | |||
mail, either IPv4 or IPv6. | mail, either IPv4 or IPv6. | |||
<domain> - the domain portion of the "MAIL FROM" or "HELO" identity. | <domain> - the domain portion of the "MAIL FROM" or "HELO" identity. | |||
<sender> - the "MAIL FROM" or "HELO" identity. | <sender> - the "MAIL FROM" or "HELO" identity. | |||
Note that the <domain> argument may not be a well-formed domain name. | Note that the <domain> argument might not be a well-formed domain | |||
For example, if the reverse-path was null, then the EHLO/HELO domain | name. For example, if the reverse-path was null, then the EHLO/HELO | |||
is used, with its associated problems (see Section 2.1). In these | domain is used, with its associated problems (see Section 2.1). In | |||
cases, check_host() is defined in Section 4.3 to return a "None" | these cases, check_host() is defined in Section 4.3 to return a | |||
result. | "none" result. | |||
Although invalid, malformed, or non-existent domains cause SPF checks | Although invalid, malformed, or non-existent domains cause SPF checks | |||
to return "None" because no SPF record can be found, it has long been | to return "none" because no SPF record can be found, it has long been | |||
the policy of many MTAs to reject E-Mail from such domains, | the policy of many MTAs to reject email from such domains, especially | |||
especially in the case of invalid "MAIL FROM". In order to prevent | in the case of invalid "MAIL FROM". Rejecting email will prevent one | |||
the circumvention of SPF records, rejecting E-Mail from invalid | method of circumventing of SPF records. | |||
domains should be considered. | ||||
Implementations must take care to correctly extract the <domain> from | Implementations MUST take care to correctly extract the <domain> from | |||
the data given with the SMTP MAIL FROM command as many MTAs will | the data given with the SMTP MAIL FROM command as many MTAs will | |||
still accept such things as source routes (see [RFC2821], Appendix | still accept such things as source routes (see [RFC5321], Appendix | |||
C), the %-hack (see [RFC1123]), and bang paths (see [RFC1983]). | C), the %-hack (see [RFC1123]), and bang paths (see [RFC1983]). | |||
These archaic features have been maliciously used to bypass security | These archaic features have been maliciously used to bypass security | |||
systems. | systems. | |||
2.5. Interpreting the Result | 2.5. Interpreting the Result | |||
This section describes how software that performs the authorization | This section describes how software that performs the authorization | |||
should interpret the results of the check_host() function. The | interprets the results of the check_host() function. The | |||
authorization check SHOULD be performed during the processing of the | authorization check SHOULD be performed during the processing of the | |||
SMTP transaction that sends the mail. This allows errors to be | SMTP transaction that sends the mail. This allows errors to be | |||
returned directly to the sending MTA by way of SMTP replies. | returned directly to the sending MTA by way of SMTP replies. | |||
Performing the authorization after the SMTP transaction has finished | Performing the authorization other than using the return-path and | |||
may cause problems, such as the following: (1) It may be difficult to | client address at the time of the MAIL command during the SMTP | |||
accurately extract the required information from potentially | transaction can cause problems, such as the following: (1) It might | |||
deceptive headers; (2) legitimate E-Mail may fail because the | be difficult to accurately extract the required information from | |||
sender's policy may have since changed. | potentially deceptive headers; (2) legitimate email might fail | |||
because the sender's policy had since changed. | ||||
Generating non-delivery notifications to forged identities that have | Generating non-delivery notifications to forged identities that have | |||
failed the authorization check is generally abusive and against the | failed the authorization check is a source of backscatter and SHOULD | |||
explicit wishes of the identity owner. | be avoided. [RFC3834] section 2 describes backscatter and the | |||
problems it causes. | ||||
2.5.1. None | 2.5.1. None | |||
A result of "None" means that no records were published by the domain | A result of "none" means either (a) no syntactically valid DNS domain | |||
or that no checkable sender domain could be determined from the given | name was extracted from the SMTP session that could be used as the | |||
identity. The checking software cannot ascertain whether or not the | one to be authorized, or (b) no TXT records were retrieved from the | |||
client host is authorized. | DNS that appeared to be intended for use by SPF verifiers. | |||
2.5.2. Neutral | 2.5.2. Neutral | |||
The domain owner has explicitly stated that he cannot or does not | The domain owner has explicitly stated that they cannot or do not | |||
want to assert whether or not the IP address is authorized. A | want to assert whether the IP address is authorized or not. A | |||
"Neutral" result MUST be treated exactly like the "None" result; the | "neutral" result MUST be treated exactly like the "none" result; the | |||
distinction exists only for informational purposes. Treating | distinction exists only for informational purposes. Treating | |||
"Neutral" more harshly than "None" would discourage domain owners | "neutral" more harshly than "none" would discourage domain owners | |||
from testing the use of SPF records (see Section 9.1). | from testing the use of SPF records (see Section 9.1). | |||
2.5.3. Pass | 2.5.3. Pass | |||
A "Pass" result means that the client is authorized to inject mail | A "pass" result means that the client is authorized to inject mail | |||
with the given identity. The domain can now, in the sense of | with the given identity. The domain can now, in the sense of | |||
reputation, be considered responsible for sending the message. | reputation, be considered responsible for sending the message. | |||
Further policy checks can now proceed with confidence in the | Further policy checks can now proceed with confidence in the | |||
legitimate use of the identity. | legitimate use of the identity. | |||
2.5.4. Fail | 2.5.4. Fail | |||
A "Fail" result is an explicit statement that the client is not | A "fail" result is an explicit statement that the client is not | |||
authorized to use the domain in the given identity. The checking | authorized to use the domain in the given identity. Disposition of | |||
software can choose to mark the mail based on this or to reject the | SPF fail messages is a matter of local policy. See Section 9.3 for | |||
mail outright. | considerations on developing local policy. | |||
If the checking software chooses to reject the mail during the SMTP | If the checking software chooses to reject the mail during the SMTP | |||
transaction, then it SHOULD use an SMTP reply code of 550 (see | transaction, then it SHOULD use an SMTP reply code of 550 (see | |||
[RFC2821]) and, if supported, the 5.7.1 Delivery Status Notification | [RFC5321]) and, if supported, the 5.7.1 enhanced status code (see | |||
(DSN) code (see [RFC3464]), in addition to an appropriate reply text. | [RFC3463]), in addition to an appropriate reply text. The | |||
The check_host() function may return either a default explanation | check_host() function will return either a default explanation string | |||
string or one from the domain that published the SPF records (see | or one from the domain that published the SPF records (see | |||
Section 6.2). If the information does not originate with the | Section 6.2). If the information does not originate with the | |||
checking software, it should be made clear that the text is provided | checking software, it should be made clear that the text is provided | |||
by the sender's domain. For example: | by the sender's domain. For example: | |||
550-5.7.1 SPF MAIL FROM check failed: | 550-5.7.1 SPF MAIL FROM check failed: | |||
550-5.7.1 The domain example.com explains: | 550-5.7.1 The domain example.com explains: | |||
550 5.7.1 Please see http://www.example.com/mailpolicy.html | 550 5.7.1 Please see http://www.example.com/mailpolicy.html | |||
2.5.5. SoftFail | If the checking software chooses not to reject the mail during the | |||
SMTP transaction, then is SHOULD add a Received-SPF or | ||||
Authentication-Results header field (see Section 7) to communicate | ||||
this result to downstream message processors. While this is true for | ||||
all SPF results, it is of particular importance for "fail" results | ||||
since the message is explicitly not authorized by the domain owner. | ||||
A "SoftFail" result should be treated as somewhere between a "Fail" | 2.5.5. Softfail | |||
and a "Neutral". The domain believes the host is not authorized but | ||||
is not willing to make that strong of a statement. Receiving | A "softfail" result ought to be treated as somewhere between "fail" | |||
and "neutral"/"none". The domain believes the host is not authorized | ||||
but is not willing to make a strong policy statement. Receiving | ||||
software SHOULD NOT reject the message based solely on this result, | software SHOULD NOT reject the message based solely on this result, | |||
but MAY subject the message to closer scrutiny than normal. | but MAY subject the message to closer scrutiny than normal. | |||
The domain owner wants to discourage the use of this host and thus | The domain owner wants to discourage the use of this host and thus | |||
desires limited feedback when a "SoftFail" result occurs. For | desires limited feedback when a "softfail" result occurs. For | |||
example, the recipient's Mail User Agent (MUA) could highlight the | example, the recipient's Mail User Agent (MUA) could highlight the | |||
"SoftFail" status, or the receiving MTA could give the sender a | "softfail" status, or the receiving MTA could give the sender a | |||
message using a technique called "greylisting" whereby the MTA can | message using greylisting, [RFC6647], with a note the first time the | |||
issue an SMTP reply code of 451 (4.3.0 DSN code) with a note the | message is received, but accept it on a later attempt based on | |||
first time the message is received, but accept it the second time. | receiver policy. | |||
2.5.6. TempError | 2.5.6. TempError | |||
A "TempError" result means that the SPF client encountered a | A "temperror" result means the SPF verifier encountered a transient | |||
transient error while performing the check. Checking software can | (DNS) error while performing the check. Checking software can choose | |||
choose to accept or temporarily reject the message. If the message | to accept or temporarily reject the message. If the message is | |||
is rejected during the SMTP transaction for this reason, the software | rejected during the SMTP transaction for this reason, the software | |||
SHOULD use an SMTP reply code of 451 and, if supported, the 4.4.3 DSN | SHOULD use an SMTP reply code of 451 and, if supported, the 4.4.3 | |||
code. | enhanced status code. These errors can be caused by problems in | |||
either the sender's or receiver's DNS software. | ||||
2.5.7. PermError | 2.5.7. PermError | |||
A "PermError" result means that the domain's published records could | A "permerror" result means the domain's published records could not | |||
not be correctly interpreted. This signals an error condition that | be correctly interpreted. This signals an error condition that | |||
requires manual intervention to be resolved, as opposed to the | definitely requires manual intervention to be resolved. If the | |||
TempError result. Be aware that if the domain owner uses macros | message is rejected during the SMTP transaction for this reason, the | |||
(Section 8), it is possible that this result is due to the checked | software SHOULD use an SMTP reply code of 550 and, if supported, the | |||
identities having an unexpected format. | 5.5.2 enhanced status code. Be aware that if the domain owner uses | |||
macros (Section 8), it is possible that this result is due to the | ||||
checked identities having an unexpected format. | ||||
3. SPF Records | 3. SPF Records | |||
An SPF record is a DNS Resource Record (RR) that declares which hosts | An SPF record is a DNS TXT (type 16) Resource Record (RR) that | |||
are, and are not, authorized to use a domain name for the "HELO" and | declares which hosts are, and are not, authorized to use a domain | |||
"MAIL FROM" identities. Loosely, the record partitions all hosts | name for the "HELO" and "MAIL FROM" identities. Loosely, the record | |||
into permitted and not-permitted sets (though some hosts might fall | partitions all hosts into permitted and not-permitted sets (though | |||
into neither category). | some hosts might fall into neither category). | |||
The SPF record is a single string of text. An example record is the | The SPF record is a single string of text. An example record is the | |||
following: | following: | |||
v=spf1 +mx a:colo.example.com/28 -all | v=spf1 +mx a:colo.example.com/28 -all | |||
This record has a version of "spf1" and three directives: "+mx", | This record has a version of "spf1" and three directives: "+mx", | |||
"a:colo.example.com/28" (the + is implied), and "-all". | "a:colo.example.com/28" (the + is implied), and "-all". | |||
3.1. Publishing | ||||
Domain owners wishing to be SPF compliant must publish SPF records | ||||
for the hosts that are used in the "MAIL FROM" and "HELO" identities. | ||||
The SPF records are placed in the DNS tree at the host name it | The SPF records are placed in the DNS tree at the host name it | |||
pertains to, not a subdomain under it, such as is done with SRV | pertains to, not a subdomain under it, such as is done with SRV | |||
records. This is the same whether the TXT or SPF RR type (see | records [RFC2782]. | |||
Section 3.1.1) is used. | ||||
The example above in Section 3 might be published via these lines in | The example in Section 3 might be published via these lines in a | |||
a domain zone file: | domain zone file: | |||
example.com. TXT "v=spf1 +mx a:colo.example.com/28 -all" | example.com. TXT "v=spf1 +mx a:colo.example.com/28 -all" | |||
smtp-out.example.com. TXT "v=spf1 a -all" | smtp-out.example.com. TXT "v=spf1 a -all" | |||
When publishing via TXT records, beware of other TXT records | Since TXT records have multiple uses, beware of other TXT records | |||
published there for other purposes. They may cause problems with | published there for other purposes. They might cause problems with | |||
size limits (see Section 3.1.4). | size limits (see Section 3.4) and care MUST be taken to ensure only | |||
SPF records are used for SPF processing. | ||||
3.1.1. DNS Resource Record Types | ||||
This document defines a new DNS RR of type SPF, code 99. The format | ||||
of this type is identical to the TXT RR [RFC1035]. For either type, | ||||
the character content of the record is encoded as [US-ASCII]. | ||||
It is recognized that the current practice (using a TXT record) is | Domains publishing records SHOULD try to keep the number of "include" | |||
not optimal, but it is necessary because there are a number of DNS | mechanisms and chained "redirect" modifiers to a minimum. Domains | |||
server and resolver implementations in common use that cannot handle | SHOULD also try to minimize the amount of other DNS information | |||
the new RR type. The two-record-type scheme provides a forward path | needed to evaluate a record. Section 4.6.4 and Section 9.1.1 provide | |||
to the better solution of using an RR type reserved for this purpose. | some suggestions on how to achieve this. | |||
An SPF-compliant domain name SHOULD have SPF records of both RR | 3.1. DNS Resource Records | |||
types. A compliant domain name MUST have a record of at least one | ||||
type. If a domain has records of both types, they MUST have | ||||
identical content. For example, instead of publishing just one | ||||
record as in Section 3.1 above, it is better to publish: | ||||
example.com. IN TXT "v=spf1 +mx a:colo.example.com/28 -all" | SPF records MUST be published as type TXT [RFC1035]. The character | |||
example.com. IN SPF "v=spf1 +mx a:colo.example.com/28 -all" | content of the record is encoded as [US-ASCII]. Use of alternate DNS | |||
Example RRs in this document are shown with the TXT record type; | RR types was supported in SPF's experimental phase, but has been | |||
however, they could be published with the SPF type or with both | discontinued. See Appendix A of [RFC6686] for further information. | |||
types. | ||||
3.1.2. Multiple DNS Records | 3.2. Multiple DNS Records | |||
A domain name MUST NOT have multiple records that would cause an | A domain name MUST NOT have multiple records that would cause an | |||
authorization check to select more than one record. See Section 4.5 | authorization check to select more than one record. See Section 4.5 | |||
for the selection rules. | for the selection rules. | |||
3.1.3. Multiple Strings in a Single DNS record | 3.3. Multiple Strings in a Single DNS record | |||
As defined in [RFC1035] sections 3.3.14 and 3.3, a single text DNS | As defined in [RFC1035] sections 3.3.14 and 3.3, a single text DNS | |||
record (either TXT or SPF RR types) can be composed of more than one | record can be composed of more than one string. If a published | |||
string. If a published record contains multiple strings, then the | record contains multiple character-strings, then the record MUST be | |||
record MUST be treated as if those strings are concatenated together | treated as if those strings are concatenated together without adding | |||
without adding spaces. For example: | spaces. For example: | |||
IN TXT "v=spf1 .... first" "second string..." | IN TXT "v=spf1 .... first" "second string..." | |||
MUST be treated as equivalent to | MUST be treated as equivalent to | |||
IN TXT "v=spf1 .... firstsecond string..." | IN TXT "v=spf1 .... firstsecond string..." | |||
SPF or TXT records containing multiple strings are useful in | TXT records containing multiple strings are useful in constructing | |||
constructing records that would exceed the 255-byte maximum length of | records that would exceed the 255-byte maximum length of a character- | |||
a string within a single TXT or SPF RR record. | string within a single TXT record. | |||
3.1.4. Record Size | 3.4. Record Size | |||
The published SPF record for a given domain name SHOULD remain small | The published SPF record for a given domain name SHOULD remain small | |||
enough that the results of a query for it will fit within 512 octets. | enough that the results of a query for it will fit within 512 octets. | |||
This will keep even older DNS implementations from falling over to | This UDP limit is defined in [RFC1035] section 2.3.4. This will keep | |||
TCP. Since the answer size is dependent on many things outside the | even older DNS implementations from falling over to TCP. Since the | |||
scope of this document, it is only possible to give this guideline: | answer size is dependent on many things outside the scope of this | |||
If the combined length of the DNS name and the text of all the | document, it is only possible to give this guideline: If the combined | |||
records of a given type (TXT or SPF) is under 450 characters, then | length of the DNS name and the text of all the records of a given | |||
DNS answers should fit in UDP packets. Note that when computing the | type is under 450 characters, then DNS answers ought to fit in UDP | |||
sizes for queries of the TXT format, one must take into account any | packets. Note that when computing the sizes for queries of the TXT | |||
other TXT records published at the domain name. Records that are too | format, one must take into account any other TXT records published at | |||
long to fit in a single UDP packet MAY be silently ignored by SPF | the domain name. Records that are too long to fit in a single UDP | |||
clients. | packet could be silently ignored by SPF verifiers due to firewall and | |||
other issues that cause DNS over TCP to be less reliable than DNS | ||||
over UDP. | ||||
3.1.5. Wildcard Records | 3.5. Wildcard Records | |||
Use of wildcard records for publishing is not recommended. Care must | Use of wildcard records for publishing is NOT RECOMMENDED. Care must | |||
be taken if wildcard records are used. If a domain publishes | be taken if wildcard records are used. If a domain publishes | |||
wildcard MX records, it may want to publish wildcard declarations, | wildcard MX records, it might want to publish wildcard declarations, | |||
subject to the same requirements and problems. In particular, the | subject to the same requirements and problems. In particular, the | |||
declaration must be repeated for any host that has any RR records at | declaration MUST be repeated for any host that has any RR records at | |||
all, and for subdomains thereof. For example, the example given in | all, and for subdomains thereof. For example, the example given in | |||
[RFC1034], Section 4.3.3, could be extended with the following: | [RFC1034], Section 4.3.3, could be extended with the following: | |||
X.COM. MX 10 A.X.COM | X.COM. MX 10 A.X.COM | |||
X.COM. TXT "v=spf1 a:A.X.COM -all" | X.COM. TXT "v=spf1 a:A.X.COM -all" | |||
*.X.COM. MX 10 A.X.COM | *.X.COM. MX 10 A.X.COM | |||
*.X.COM. TXT "v=spf1 a:A.X.COM -all" | *.X.COM. TXT "v=spf1 a:A.X.COM -all" | |||
A.X.COM. A 1.2.3.4 | A.X.COM. A 1.2.3.4 | |||
A.X.COM. MX 10 A.X.COM | A.X.COM. MX 10 A.X.COM | |||
A.X.COM. TXT "v=spf1 a:A.X.COM -all" | A.X.COM. TXT "v=spf1 a:A.X.COM -all" | |||
*.A.X.COM. MX 10 A.X.COM | *.A.X.COM. MX 10 A.X.COM | |||
*.A.X.COM. TXT "v=spf1 a:A.X.COM -all" | *.A.X.COM. TXT "v=spf1 a:A.X.COM -all" | |||
Notice that SPF records must be repeated twice for every name within | SPF records MUST be listed twice for every name within the domain: | |||
the domain: once for the name, and once with a wildcard to cover the | once for the name, and once with a wildcard to cover the tree under | |||
tree under the name. | the name in order to cover all domains in use in outgoing mail. | |||
Use of wildcards is discouraged in general as they cause every name | ||||
under the domain to exist and queries against arbitrary names will | ||||
never return RCODE 3 (Name Error). | ||||
4. The check_host() Function | 4. The check_host() Function | |||
This description is not an API (Application Program Interface) | ||||
definition, but rather a function description used to illustrate the | ||||
algorithm. A compliant SPF implementation MUST do something | ||||
semantically equivalent to this description. | ||||
The check_host() function fetches SPF records, parses them, and | The check_host() function fetches SPF records, parses them, and | |||
interprets them to determine whether a particular host is or is not | evaluates them to determine whether a particular host is or is not | |||
permitted to send mail with a given identity. Mail receivers that | permitted to send mail with a given identity. Mail receivers that | |||
perform this check MUST correctly evaluate the check_host() function | perform this check MUST correctly evaluate the check_host() function | |||
as described here. | as described here. | |||
Implementations MAY use a different algorithm than the canonical | Implementations MAY use a different algorithm than the canonical | |||
algorithm defined here, so long as the results are the same in all | algorithm defined here, so long as the results are the same in all | |||
cases. | cases. | |||
4.1. Arguments | 4.1. Arguments | |||
skipping to change at page 13, line 12 | skipping to change at page 17, line 40 | |||
information; initially, the domain portion of the "MAIL | information; initially, the domain portion of the "MAIL | |||
FROM" or "HELO" identity. | FROM" or "HELO" identity. | |||
<sender> - the "MAIL FROM" or "HELO" identity. | <sender> - the "MAIL FROM" or "HELO" identity. | |||
The domain portion of <sender> will usually be the same as the | The domain portion of <sender> will usually be the same as the | |||
<domain> argument when check_host() is initially evaluated. However, | <domain> argument when check_host() is initially evaluated. However, | |||
this will generally not be true for recursive evaluations (see | this will generally not be true for recursive evaluations (see | |||
Section 5.2 below). | Section 5.2 below). | |||
Actual implementations of the check_host() function may need | ||||
additional arguments. | ||||
4.2. Results | 4.2. Results | |||
The function check_host() can return one of several results described | The function check_host() can return one of several results described | |||
in Section 2.5. Based on the result, the action to be taken is | in Section 2.5. Based on the result, the action to be taken is | |||
determined by the local policies of the receiver. | determined by the local policies of the receiver. | |||
4.3. Initial Processing | 4.3. Initial Processing | |||
If the <domain> is malformed (label longer than 63 characters, zero- | If the <domain> is malformed (e.g. label longer than 63 characters, | |||
length label not at the end, etc.) or is not a fully qualified domain | zero-length label not at the end, etc.) or is not a fully qualified | |||
name, or if the DNS lookup returns "domain does not exist" (RCODE 3), | domain name, or if the DNS lookup returns "domain does not exist" | |||
check_host() immediately returns the result "None". | (RCODE 3), check_host() immediately returns the result "none". | |||
Properly formed domains are fully qualified email domains as | ||||
described in [RFC5321] Section 2.3.5. Internationalized domain names | ||||
MUST be encoded as A-labels, as described in Section 2.3 of | ||||
[RFC5890]. | ||||
If the <sender> has no localpart, substitute the string "postmaster" | If the <sender> has no local-part, substitute the string "postmaster" | |||
for the localpart. | for the local-part. | |||
4.4. Record Lookup | 4.4. Record Lookup | |||
In accordance with how the records are published (see Section 3.1 | In accordance with how the records are published (see Section 3 | |||
above), a DNS query needs to be made for the <domain> name, querying | above), a DNS query needs to be made for the <domain> name, querying | |||
for either RR type TXT, SPF, or both. If both SPF and TXT RRs are | for type TXT only. | |||
looked up, the queries MAY be done in parallel. | ||||
If all DNS lookups that are made return a server failure (RCODE 2), | If all DNS lookups that are made return a server failure (RCODE 2), | |||
or other error (RCODE other than 0 or 3), or time out, then | or other error (RCODE other than 0 or 3), or time out, then | |||
check_host() exits immediately with the result "TempError". | check_host() terminates immediately with the result "temperror". | |||
Alternatively, for a server failure (RCODE 2) result, check_host() | ||||
MAY track failures and treat multiple failures within 24 hours for | ||||
the same domain as "permerror". | ||||
This alternative is intended to shorten the queue time of messages | ||||
that cannot be accepted, by returning a permanent negative completion | ||||
reply code to the client, instead of a transient one. [RFC2308] | ||||
suggests on an algorithm for doing such tracking and handling of | ||||
server failure codes. | ||||
4.5. Selecting Records | 4.5. Selecting Records | |||
Records begin with a version section: | Records begin with a version section: | |||
record = version terms *SP | record = version terms *SP | |||
version = "v=spf1" | version = "v=spf1" | |||
Starting with the set of records that were returned by the lookup, | Starting with the set of records that were returned by the lookup, | |||
record selection proceeds in two steps: | discard records that do not begin with a version section of exactly | |||
"v=spf1". Note that the version section is terminated either by an | ||||
1. Records that do not begin with a version section of exactly | SP character or the end of the record. A record with a version | |||
"v=spf1" are discarded. Note that the version section is | section of "v=spf10" does not match and must be discarded. | |||
terminated either by an SP character or the end of the record. A | ||||
record with a version section of "v=spf10" does not match and must | ||||
be discarded. | ||||
2. If any records of type SPF are in the set, then all records of | ||||
type TXT are discarded. | ||||
After the above steps, there should be exactly one record remaining | ||||
and evaluation can proceed. If there are two or more records | ||||
remaining, then check_host() exits immediately with the result of | ||||
"PermError". | ||||
If no matching records are returned, an SPF client MUST assume that | If the resultant record set includes no records, check_host() | |||
the domain makes no SPF declarations. SPF processing MUST stop and | produces the "none" result. If the resultant record set includes | |||
return "None". | more than one record, check_host() produces the "permerror" result. | |||
4.6. Record Evaluation | 4.6. Record Evaluation | |||
After one SPF record has been selected, the check_host() function | After one SPF record has been selected, the check_host() function | |||
parses and interprets it to find a result for the current test. If | parses and interprets it to find a result for the current test. If | |||
there are any syntax errors, check_host() returns immediately with | there are any syntax errors, check_host() returns immediately with | |||
the result "PermError". | the result "permerror". | |||
Implementations MAY choose to parse the entire record first and | Implementations MAY choose to parse the entire record first and | |||
return "PermError" if the record is not syntactically well formed. | return "permerror" if the record is not syntactically well formed. | |||
However, in all cases, any syntax errors anywhere in the record MUST | However, in all cases, any syntax errors anywhere in the record MUST | |||
be detected. | be detected. | |||
4.6.1. Term Evaluation | 4.6.1. Term Evaluation | |||
There are two types of terms: mechanisms and modifiers. A record | There are two types of terms: mechanisms and modifiers. A record | |||
contains an ordered list of these as specified in the following | contains an ordered list of these as specified in the following | |||
Augmented Backus-Naur Form (ABNF). | Augmented Backus-Naur Form (ABNF). | |||
terms = *( 1*SP ( directive / modifier ) ) | terms = *( 1*SP ( directive / modifier ) ) | |||
directive = [ qualifier ] mechanism | directive = [ qualifier ] mechanism | |||
qualifier = "+" / "-" / "?" / "~" | qualifier = "+" / "-" / "?" / "~" | |||
mechanism = ( all / include | mechanism = ( all / include | |||
/ A / MX / PTR / IP4 / IP6 / exists ) | / A / MX / PTR / IP4 / IP6 / exists ) | |||
modifier = redirect / explanation / unknown-modifier | modifier = redirect / explanation / unknown-modifier | |||
unknown-modifier = name "=" macro-string | unknown-modifier = name "=" macro-string | |||
; where name is not any known modifier | ||||
name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." ) | name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." ) | |||
Most mechanisms allow a ":" or "/" character after the name. | Most mechanisms allow a ":" or "/" character after the name. | |||
Modifiers always contain an equals ('=') character immediately after | Modifiers always contain an equals ('=') character immediately after | |||
the name, and before any ":" or "/" characters that may be part of | the name, and before any ":" or "/" characters that might be part of | |||
the macro-string. | the macro-string. | |||
Terms that do not contain any of "=", ":", or "/" are mechanisms, as | Terms that do not contain any of "=", ":", or "/" are mechanisms, as | |||
defined in Section 5. | defined in Section 5. | |||
As per the definition of the ABNF notation in [RFC4234], mechanism | As per the definition of the ABNF notation in [RFC5234], mechanism | |||
and modifier names are case-insensitive. | and modifier names are case-insensitive. | |||
4.6.2. Mechanisms | 4.6.2. Mechanisms | |||
Each mechanism is considered in turn from left to right. If there | Each mechanism is considered in turn from left to right. If there | |||
are no more mechanisms, the result is specified in Section 4.7. | are no more mechanisms, the result is specified in Section 4.7. | |||
When a mechanism is evaluated, one of three things can happen: it can | When a mechanism is evaluated, one of three things can happen: it can | |||
match, not match, or throw an exception. | match, not match, or throw an exception. | |||
If it matches, processing ends and the qualifier value is returned as | If it matches, processing ends and the qualifier value is returned as | |||
the result of that record. If it does not match, processing | the result of that record. If it does not match, processing | |||
continues with the next mechanism. If it throws an exception, | continues with the next mechanism. If it returns an exception, | |||
mechanism processing ends and the exception value is returned. | mechanism processing ends and the exception value is returned. | |||
The possible qualifiers, and the results they return are as follows: | The possible qualifiers, and the results they cause check_host() to | |||
return are as follows: | ||||
"+" Pass | "+" pass | |||
"-" Fail | "-" fail | |||
"~" SoftFail | "~" softfail | |||
"?" Neutral | "?" neutral | |||
The qualifier is optional and defaults to "+". | The qualifier is optional and defaults to "+". | |||
When a mechanism matches and the qualifier is "-", then a "Fail" | When a mechanism matches and the qualifier is "-", then a "fail" | |||
result is returned and the explanation string is computed as | result is returned and the explanation string is computed as | |||
described in Section 6.2. | described in Section 6.2. | |||
The specific mechanisms are described in Section 5. | The specific mechanisms are described in Section 5. | |||
4.6.3. Modifiers | 4.6.3. Modifiers | |||
Modifiers are not mechanisms: they do not return match or not-match. | Modifiers are not mechanisms. They do not return match or not-match. | |||
Instead they provide additional information. Although modifiers do | Instead, they provide additional information. Although modifiers do | |||
not directly affect the evaluation of the record, the "redirect" | not directly affect the evaluation of the record, the "redirect" | |||
modifier has an effect after all the mechanisms have been evaluated. | modifier has an effect after all the mechanisms have been evaluated. | |||
4.6.4. DNS Lookup Limits | ||||
SPF implementations MUST limit the number of mechanisms and modifiers | ||||
("terms") that cause any DNS query to at most 10 during SPF | ||||
evaluation. Specifically, the "include", "a", "mx", "ptr", and | ||||
"exists" mechanisms as well as the "redirect" modifier count against | ||||
this limit. The "all", "ip4", and "ip6" mechanisms do not count | ||||
against this limit. If this number is exceeded during a check, a | ||||
permerror MUST be returned. The "exp" modifier does not count | ||||
against this limit because the DNS lookup to fetch the explanation | ||||
string occurs after the SPF record evaluation has been completed. | ||||
When evaluating the "mx" and "ptr" mechanisms, or the %{p} macro, | ||||
there MUST be a limit of no more than 10 MX or PTR RRs looked up and | ||||
checked. If more than 10 "mx" or "ptr" records are returned for this | ||||
further lookup, a permerror MUST be returned. This limit is per | ||||
mechanism or macro in the record and in addition to the lookup limits | ||||
above. | ||||
MTAs or other processors SHOULD impose a limit on the maximum amount | ||||
of elapsed time to evaluate check_host(). Such a limit SHOULD allow | ||||
at least 20 seconds. If such a limit is exceeded, the result of | ||||
authorization SHOULD be "temperror". | ||||
4.7. Default Result | 4.7. Default Result | |||
If none of the mechanisms match and there is no "redirect" modifier, | If none of the mechanisms match and there is no "redirect" modifier, | |||
then the check_host() returns a result of "Neutral", just as if | then the check_host() returns a result of "neutral", just as if | |||
"?all" were specified as the last directive. If there is a | "?all" were specified as the last directive. If there is a | |||
"redirect" modifier, check_host() proceeds as defined in Section 6.1. | "redirect" modifier, check_host() proceeds as defined in Section 6.1. | |||
Note that records SHOULD always use either a "redirect" modifier or | Note that records SHOULD always use either a "redirect" modifier or | |||
an "all" mechanism to explicitly terminate processing. | an "all" mechanism to explicitly terminate processing. Although the | |||
latter has default (specifically "?all"), it aids debugging efforts | ||||
if it is explicitly included. | ||||
For example: | For example: | |||
v=spf1 +mx -all | v=spf1 +mx -all | |||
or | or | |||
v=spf1 +mx redirect=_spf.example.com | v=spf1 +mx redirect=_spf.example.com | |||
4.8. Domain Specification | 4.8. Domain Specification | |||
Several of these mechanisms and modifiers have a <domain-spec> | Several of these mechanisms and modifiers have a domain-spec section. | |||
section. The <domain-spec> string is macro expanded (see Section 8). | The domain-spec string is subject to macro expansion (see Section 8). | |||
The resulting string is the common presentation form of a fully- | The resulting string is the common presentation form of a fully- | |||
qualified DNS name: a series of labels separated by periods. This | qualified DNS name: a series of labels separated by periods. This | |||
domain is called the <target-name> in the rest of this document. | domain is called the <target-name> in the rest of this document. | |||
Note: The result of the macro expansion is not subject to any further | Note: The result of the macro expansion is not subject to any further | |||
escaping. Hence, this facility cannot produce all characters that | escaping. Hence, this facility cannot produce all characters that | |||
are legal in a DNS label (e.g., the control characters). However, | are legal in a DNS label (e.g., the control characters). However, | |||
this facility is powerful enough to express legal host names and | this facility is powerful enough to express legal host names and | |||
common utility labels (such as "_spf") that are used in DNS. | common utility labels (such as "_spf") that are used in DNS. | |||
For several mechanisms, the <domain-spec> is optional. If it is not | For several mechanisms, the <domain-spec> is optional. If it is not | |||
provided, the <domain> is used as the <target-name>. | provided, the <domain> is used as the <target-name>. Domain and | |||
domain-spec are syntactically identical after macro expansion. | ||||
Domain is an input value for check_host() while domain-spec is | ||||
computed by check_host(). | ||||
5. Mechanism Definitions | 5. Mechanism Definitions | |||
This section defines two types of mechanisms. | This section defines two types of mechanisms. | |||
Basic mechanisms contribute to the language framework. They do not | Basic mechanisms contribute to the language framework. They do not | |||
specify a particular type of authorization scheme. | specify a particular type of authorization scheme. | |||
all | all | |||
include | include | |||
Designated sender mechanisms are used to designate a set of <ip> | Designated sender mechanisms are used to designate a set of <ip> | |||
addresses as being permitted or not permitted to use the <domain> for | addresses as being permitted or not permitted to use the <domain> for | |||
sending mail. | sending mail. | |||
a | a | |||
mx | mx | |||
ptr | ptr (deprecated) | |||
ip4 | ip4 | |||
ip6 | ip6 | |||
exists | exists | |||
The following conventions apply to all mechanisms that perform a | The following conventions apply to all mechanisms that perform a | |||
comparison between <ip> and an IP address at any point: | comparison between <ip> and an IP address at any point: | |||
If no CIDR-length is given in the directive, then <ip> and the IP | If no CIDR prefix length is given in the directive, then <ip> and the | |||
address are compared for equality. (Here, CIDR is Classless Inter- | IP address are compared for equality. (Here, CIDR is Classless | |||
Domain Routing.) | Inter-Domain Routing, described in [RFC4632].) | |||
If a CIDR-length is specified, then only the specified number of | If a CIDR prefix length is specified, then only the specified number | |||
high-order bits of <ip> and the IP address are compared for equality. | of high-order bits of <ip> and the IP address are compared for | |||
equality. | ||||
When any mechanism fetches host addresses to compare with <ip>, when | When any mechanism fetches host addresses to compare with <ip>, when | |||
<ip> is an IPv4 address, A records are fetched, when <ip> is an IPv6 | <ip> is an IPv4 address, A records are fetched; when <ip> is an IPv6 | |||
address, AAAA records are fetched. Even if the SMTP connection is | address, AAAA records are fetched. Even if the SMTP connection uses | |||
via IPv6, an IPv4-mapped IPv6 IP address (see [RFC3513], Section | IPv6, an IPv4-mapped IPv6 IP address (see [RFC4291], Section 2.5.5) | |||
2.5.5) MUST still be considered an IPv4 address. | MUST still be considered an IPv4 address and MUST be evaluated using | |||
IPv4 mechanisms (i.e. "ip4" and "a"). | ||||
Several mechanisms rely on information fetched from DNS. For these | Several mechanisms rely on information fetched from the DNS. For | |||
DNS queries, except where noted, if the DNS server returns an error | these DNS queries, except where noted, if the DNS server returns an | |||
(RCODE other than 0 or 3) or the query times out, the mechanism | error (RCODE other than 0 or 3) or the query times out, the mechanism | |||
throws the exception "TempError". If the server returns "domain does | stops and the topmost check_host() returns "temperror". If the | |||
not exist" (RCODE 3), then evaluation of the mechanism continues as | server returns "domain does not exist" (RCODE 3), then evaluation of | |||
if the server returned no error (RCODE 0) and zero answer records. | the mechanism continues as if the server returned no error (RCODE 0) | |||
and zero answer records. | ||||
5.1. "all" | 5.1. "all" | |||
all = "all" | all = "all" | |||
The "all" mechanism is a test that always matches. It is used as the | The "all" mechanism is a test that always matches. It is used as the | |||
rightmost mechanism in a record to provide an explicit default. | rightmost mechanism in a record to provide an explicit default. | |||
For example: | For example: | |||
v=spf1 a mx -all | v=spf1 a mx -all | |||
Mechanisms after "all" will never be tested. Any "redirect" modifier | Mechanisms after "all" will never be tested. Mechanisms listed after | |||
(Section 6.1) has no effect when there is an "all" mechanism. | "all" MUST be ignored. Any "redirect" modifier (Section 6.1) MUST be | |||
ignored when there is an "all" mechanism in the record. | ||||
5.2. "include" | 5.2. "include" | |||
include = "include" ":" domain-spec | include = "include" ":" domain-spec | |||
The "include" mechanism triggers a recursive evaluation of | The "include" mechanism triggers a recursive evaluation of | |||
check_host(). The domain-spec is expanded as per Section 8. Then | check_host(). | |||
check_host() is evaluated with the resulting string as the <domain>. | ||||
The <ip> and <sender> arguments remain the same as in the current | 1. The domain-spec is expanded as per Section 8. | |||
evaluation of check_host(). | ||||
2. Check_host() is evaluated with the resulting string as the | ||||
<domain>. The <ip> and <sender> arguments remain the same as in | ||||
the current evaluation of check_host(). | ||||
3. The recursive evaluation returns either match, not match, or an | ||||
error. If it matches, then the appropriate result for the | ||||
include: mechanism is used (e.g. include or +include gives a | ||||
"pass" result and -include gives "fail). | ||||
4. If there is no match, the parent check_host() resumes processing | ||||
as per the table below, with the previous value of <domain> | ||||
restored. | ||||
In hindsight, the name "include" was poorly chosen. Only the | In hindsight, the name "include" was poorly chosen. Only the | |||
evaluated result of the referenced SPF record is used, rather than | evaluated result of the referenced SPF record is used, rather than | |||
acting as if the referenced SPF record was literally included in the | acting as if the referenced SPF record was literally included in the | |||
first. For example, evaluating a "-all" directive in the referenced | first. For example, evaluating a "-all" directive in the referenced | |||
record does not terminate the overall processing and does not | record does not terminate the overall processing and does not | |||
necessarily result in an overall "Fail". (Better names for this | necessarily result in an overall "fail". (Better names for this | |||
mechanism would have been "if-pass", "on-pass", etc.) | mechanism would have been "if-match", "on-match", etc.) | |||
The "include" mechanism makes it possible for one domain to designate | The "include" mechanism makes it possible for one domain to designate | |||
multiple administratively-independent domains. For example, a vanity | multiple administratively-independent domains. For example, a vanity | |||
domain "example.net" might send mail using the servers of | domain "example.net" might send mail using the servers of | |||
administratively-independent domains example.com and example.org. | administratively-independent domains example.com and example.org. | |||
Example.net could say | Example.net could say | |||
IN TXT "v=spf1 include:example.com include:example.org -all" | IN TXT "v=spf1 include:example.com include:example.org -all" | |||
This would direct check_host() to, in effect, check the records of | This would direct check_host() to, in effect, check the records of | |||
example.com and example.org for a "Pass" result. Only if the host | example.com and example.org for a "pass" result. Only if the host | |||
were not permitted for either of those domains would the result be | were not permitted for either of those domains would the result be | |||
"Fail". | "fail". | |||
Whether this mechanism matches, does not match, or throws an | Whether this mechanism matches, does not match, or returns an | |||
exception depends on the result of the recursive evaluation of | exception depends on the result of the recursive evaluation of | |||
check_host(): | check_host(): | |||
+---------------------------------+---------------------------------+ | +---------------------------------+---------------------------------+ | |||
| A recursive check_host() result | Causes the "include" mechanism | | | A recursive check_host() result | Causes the "include" mechanism | | |||
| of: | to: | | | of: | to: | | |||
+---------------------------------+---------------------------------+ | +---------------------------------+---------------------------------+ | |||
| Pass | match | | | pass | match | | |||
| | | | | | | | |||
| Fail | not match | | | fail | not match | | |||
| | | | | | | | |||
| SoftFail | not match | | | softfail | not match | | |||
| | | | | | | | |||
| Neutral | not match | | | neutral | not match | | |||
| | | | | | | | |||
| TempError | throw TempError | | | temperror | throw temperror | | |||
| | | | | | | | |||
| PermError | throw PermError | | | permerror | throw permerror | | |||
| | | | | | | | |||
| None | throw PermError | | | none | throw permerror | | |||
+---------------------------------+---------------------------------+ | +---------------------------------+---------------------------------+ | |||
The "include" mechanism is intended for crossing administrative | The "include" mechanism is intended for crossing administrative | |||
boundaries. Although it is possible to use includes to consolidate | boundaries. For example, if example.com and example.org were managed | |||
multiple domains that share the same set of designated hosts, domains | by the same entity, and if the permitted set of hosts for both | |||
are encouraged to use redirects where possible, and to minimize the | domains was | |||
number of includes within a single administrative domain. For | ||||
example, if example.com and example.org were managed by the same | ||||
entity, and if the permitted set of hosts for both domains was | ||||
"mx:example.com", it would be possible for example.org to specify | "mx:example.com", it would be possible for example.org to specify | |||
"include:example.com", but it would be preferable to specify | "include:example.com", but it would be preferable to specify | |||
"redirect=example.com" or even "mx:example.com". | "redirect=example.com" or even "mx:example.com". | |||
With the "include" mechanism an administratively external set of | ||||
hosts can be authorized, but determination of sender policy is still | ||||
a function of the original domain's SPF record (as determined by the | ||||
"all" mechanism in that record). The redirect modifier is more | ||||
suitable for consolidating both authorizations and policy into a | ||||
common set to be shared within an ADMD. Redirect is much more like a | ||||
common code element to be shared among records in a single ADMD. It | ||||
is possible to control both authorized hosts and policy for an | ||||
arbitrary number of domains from a single record. | ||||
5.3. "a" | 5.3. "a" | |||
This mechanism matches if <ip> is one of the <target-name>'s IP | This mechanism matches if <ip> is one of the <target-name>'s IP | |||
addresses. | addresses. | |||
A = "a" [ ":" domain-spec ] [ dual-cidr-length ] | a = "a" [ ":" domain-spec ] [ dual-cidr-length ] | |||
An address lookup is done on the <target-name>. The <ip> is compared | An address lookup is done on the <target-name>. The <ip> is compared | |||
to the returned address(es). If any address matches, the mechanism | to the returned address(es). If any address matches, the mechanism | |||
matches. | matches. | |||
5.4. "mx" | 5.4. "mx" | |||
This mechanism matches if <ip> is one of the MX hosts for a domain | This mechanism matches if <ip> is one of the MX hosts for a domain | |||
name. | name. | |||
MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ] | mx = "mx" [ ":" domain-spec ] [ dual-cidr-length ] | |||
check_host() first performs an MX lookup on the <target-name>. Then | check_host() first performs an MX lookup on the <target-name>. Then | |||
it performs an address lookup on each MX name returned. The <ip> is | it performs an address lookup on each MX name returned. The <ip> is | |||
compared to each returned IP address. To prevent Denial of Service | compared to each returned IP address. To prevent Denial of Service | |||
(DoS) attacks, more than 10 MX names MUST NOT be looked up during the | (DoS) attacks, more than 10 MX names MUST NOT be looked up during the | |||
evaluation of an "mx" mechanism (see Section 10). If any address | evaluation of an "mx" mechanism (see Section 10). If any address | |||
matches, the mechanism matches. | matches, the mechanism matches. | |||
Note regarding implicit MXs: If the <target-name> has no MX records, | Note regarding implicit MXs: If the <target-name> has no MX records, | |||
check_host() MUST NOT pretend the target is its single MX, and MUST | check_host() MUST NOT pretend the target is its single MX, and MUST | |||
NOT default to an A lookup on the <target-name> directly. This | NOT default to an A or AAAA lookup on the <target-name> directly. | |||
behavior breaks with the legacy "implicit MX" rule. See [RFC2821], | This behavior diverges from the legacy "implicit MX" rule, (See | |||
Section 5. If such behavior is desired, the publisher should specify | [RFC5321], Section 5. If such behavior is desired, the publisher | |||
an "a" directive. | should specify an "a" directive). | |||
5.5. "ptr" | 5.5. "ptr" (deprecated) | |||
This mechanism tests whether the DNS reverse-mapping for <ip> exists | This mechanism tests whether the DNS reverse-mapping for <ip> exists | |||
and correctly points to a domain name within a particular domain. | and correctly points to a domain name within a particular domain. | |||
This mechanism is deprecated and SHOULD NOT be used. | ||||
PTR = "ptr" [ ":" domain-spec ] | ptr = "ptr" [ ":" domain-spec ] | |||
First, the <ip>'s name is looked up using this procedure: perform a | The <ip>'s name is looked up using this procedure: | |||
DNS reverse-mapping for <ip>, looking up the corresponding PTR record | ||||
in "in-addr.arpa." if the address is an IPv4 one and in "ip6.arpa." | ||||
if it is an IPv6 address. For each record returned, validate the | ||||
domain name by looking up its IP address. To prevent DoS attacks, | ||||
more than 10 PTR names MUST NOT be looked up during the evaluation of | ||||
a "ptr" mechanism (see Section 10). If <ip> is among the returned IP | ||||
addresses, then that domain name is validated. In pseudocode: | ||||
sending-domain_names := ptr_lookup(sending-host_IP); if more than 10 | 1. Perform a DNS reverse-mapping for <ip> | |||
sending-domain_names are found, use at most 10. for each name in | 2. Look up the corresponding PTR record in "in-addr.arpa." if the | |||
(sending-domain_names) { | address is an IPv4 one and in "ip6.arpa." if it is an IPv6 | |||
IP_addresses := a_lookup(name); | address. | |||
if the sending-domain_IP is one of the IP_addresses { | ||||
validated-sending-domain_names += name; | ||||
} } | ||||
Check all validated domain names to see if they end in the | 3. For each record returned, validate the domain name by looking up | |||
<target-name> domain. If any do, this mechanism matches. If no | its IP address. To prevent DoS attacks, more than 10 PTR names | |||
validated domain name can be found, or if none of the validated | MUST NOT be looked up during the evaluation of a "ptr" mechanism | |||
domain names end in the <target-name>, this mechanism fails to match. | (see Section 4.6.4). | |||
If a DNS error occurs while doing the PTR RR lookup, then this | ||||
mechanism fails to match. If a DNS error occurs while doing an A RR | 4. If <ip> is among the returned IP addresses, then that domain name | |||
lookup, then that domain name is skipped and the search continues. | is validated. | |||
Check all validated domain names to see if they either match the | ||||
<target-name> domain or are a subdomain of the <target-name> domain. | ||||
If any do, this mechanism matches. If no validated domain name can | ||||
be found, or if none of the validated domain names match or are a | ||||
subdomain of the <target-name>, this mechanism fails to match. If a | ||||
DNS error occurs while doing the PTR RR lookup, then this mechanism | ||||
fails to match. If a DNS error occurs while doing an A RR lookup, | ||||
then that domain name is skipped and the search continues. | ||||
Pseudocode: | Pseudocode: | |||
sending-domain_names := ptr_lookup(sending-host_IP); | ||||
if more than 10 sending-domain_names are found, use at most 10. | ||||
for each name in (sending-domain_names) { | ||||
IP_addresses := a_lookup(name); | ||||
if the sending-domain_IP is one of the IP_addresses { | ||||
validated-sending-domain_names += name; | ||||
} | ||||
} | ||||
for each name in (validated-sending-domain_names) { | for each name in (validated-sending-domain_names) { | |||
if name ends in <domain-spec>, return match. | if name ends in <domain-spec>, return match. | |||
if name is <domain-spec>, return match. | if name is <domain-spec>, return match. | |||
} | } | |||
return no-match. | return no-match. | |||
This mechanism matches if the <target-name> is either an ancestor of | This mechanism matches if the <target-name> is either a subdomain of | |||
a validated domain name or if the <target-name> and a validated | a validated domain name or if the <target-name> and a validated | |||
domain name are the same. For example: "mail.example.com" is within | domain name are the same. For example: "mail.example.com" is within | |||
the domain "example.com", but "mail.bad-example.com" is not. | the domain "example.com", but "mail.bad-example.com" is not. | |||
Note: Use of this mechanism is discouraged because it is slow, it is | Note: This mechanism has been deprecated because it is slow, it is | |||
not as reliable as other mechanisms in cases of DNS errors, and it | not as reliable as other mechanisms in cases of DNS errors, and it | |||
places a large burden on the arpa name servers. If used, proper PTR | places a large burden on the .arpa name servers. If used, proper PTR | |||
records must be in place for the domain's hosts and the "ptr" | records must be in place for the domain's hosts and the "ptr" | |||
mechanism should be one of the last mechanisms checked. | mechanism should be one of the last mechanisms checked. After many | |||
years of SPF deployment experience it has been concluded it is | ||||
unnecessary and more reliable alternatives used instead. It is, | ||||
however, still in use and part of the SPF protocol, so compliant | ||||
check_host() implementations MUST support it. | ||||
5.6. "ip4" and "ip6" | 5.6. "ip4" and "ip6" | |||
These mechanisms test whether <ip> is contained within a given IP | These mechanisms test whether <ip> is contained within a given IP | |||
network. | network. | |||
IP4 = "ip4" ":" ip4-network [ ip4-cidr-length ] | ip4 = "ip4" ":" ip4-network [ ip4-cidr-length ] | |||
IP6 = "ip6" ":" ip6-network [ ip6-cidr-length ] | ip6 = "ip6" ":" ip6-network [ ip6-cidr-length ] | |||
ip4-cidr-length = "/" 1*DIGIT | ip4-cidr-length = "/" 1*DIGIT | |||
ip6-cidr-length = "/" 1*DIGIT | ip6-cidr-length = "/" 1*DIGIT | |||
dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] | dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] | |||
ip4-network = qnum "." qnum "." qnum "." qnum | ip4-network = qnum "." qnum "." qnum "." qnum | |||
qnum = DIGIT ; 0-9 | qnum = DIGIT ; 0-9 | |||
/ %x31-39 DIGIT ; 10-99 | / %x31-39 DIGIT ; 10-99 | |||
/ "1" 2DIGIT ; 100-199 | / "1" 2DIGIT ; 100-199 | |||
/ "2" %x30-34 DIGIT ; 200-249 | / "2" %x30-34 DIGIT ; 200-249 | |||
/ "25" %x30-35 ; 250-255 | / "25" %x30-35 ; 250-255 | |||
; as per conventional dotted quad notation. e.g., 192.0.2.0 | ; as per conventional dotted quad notation. e.g., 192.0.2.0 | |||
ip6-network = <as per [RFC 3513], section 2.2> | ip6-network = <as per [RFC 4291], section 2.2> | |||
; e.g., 2001:DB8::CD30 | ; e.g., 2001:DB8::CD30 | |||
The <ip> is compared to the given network. If CIDR-length high-order | The <ip> is compared to the given network. If CIDR prefix length | |||
bits match, the mechanism matches. | high-order bits match, the mechanism matches. | |||
If ip4-cidr-length is omitted, it is taken to be "/32". If | If ip4-cidr-length is omitted, it is taken to be "/32". If | |||
ip6-cidr-length is omitted, it is taken to be "/128". It is not | ip6-cidr-length is omitted, it is taken to be "/128". It is not | |||
permitted to omit parts of the IP address instead of using CIDR | permitted to omit parts of the IP address instead of using CIDR | |||
notations. That is, use 192.0.2.0/24 instead of 192.0.2. | notations. That is, use 192.0.2.0/24 instead of 192.0.2. | |||
5.7. "exists" | 5.7. "exists" | |||
This mechanism is used to construct an arbitrary domain name that is | This mechanism is used to construct an arbitrary domain name that is | |||
used for a DNS A record query. It allows for complicated schemes | used for a DNS A record query. It allows for complicated schemes | |||
skipping to change at page 22, line 34 | skipping to change at page 28, line 15 | |||
Domains can use this mechanism to specify arbitrarily complex | Domains can use this mechanism to specify arbitrarily complex | |||
queries. For example, suppose example.com publishes the record: | queries. For example, suppose example.com publishes the record: | |||
v=spf1 exists:%{ir}.%{l1r+-}._spf.%{d} -all | v=spf1 exists:%{ir}.%{l1r+-}._spf.%{d} -all | |||
The <target-name> might expand to | The <target-name> might expand to | |||
"1.2.0.192.someuser._spf.example.com". This makes fine-grained | "1.2.0.192.someuser._spf.example.com". This makes fine-grained | |||
decisions possible at the level of the user and client IP address. | decisions possible at the level of the user and client IP address. | |||
This mechanism enables queries that mimic the style of tests that | This mechanism enables queries that mimic the style of tests that | |||
existing anti-spam DNS blacklists (DNSBL) use. | existing DNS white/black lists (DNSxLs) use, as described in | |||
[RFC5782]. The query will either return NXDOMAIN (no match), any | ||||
valid answer (match), or an error. | ||||
6. Modifier Definitions | 6. Modifier Definitions | |||
Modifiers are name/value pairs that provide additional information. | Modifiers are name/value pairs that provide additional information. | |||
Modifiers always have an "=" separating the name and the value. | Modifiers always have an "=" separating the name and the value. | |||
The modifiers defined in this document ("redirect" and "exp") MAY | The modifiers defined in this document ("redirect" and "exp") MAY | |||
appear anywhere in the record, but SHOULD appear at the end, after | appear anywhere in the record, but SHOULD appear at the end, after | |||
all mechanisms. Ordering of these two modifiers does not matter. | all mechanisms. Ordering of these two modifiers does not matter. | |||
These two modifiers MUST NOT appear in a record more than once each. | These two modifiers MUST NOT appear in a record more than once each. | |||
If they do, then check_host() exits with a result of "PermError". | If they do, then check_host() exits with a result of "permerror". | |||
Unrecognized modifiers MUST be ignored no matter where in a record, | Unrecognized modifiers MUST be ignored no matter where in a record, | |||
or how often. This allows implementations of this document to | or how often. This allows implementations of this document to | |||
gracefully handle records with modifiers that are defined in other | gracefully handle records with modifiers that are defined in other | |||
specifications. | specifications. | |||
6.1. redirect: Redirected Query | 6.1. redirect: Redirected Query | |||
If all mechanisms fail to match, and a "redirect" modifier is | The redirect modifier is intended for consolidating both | |||
present, then processing proceeds as follows: | authorizations and policy into a common set to be shared within a | |||
single ADMD. Redirect is like a common code element to be shared | ||||
among records in a single ADMD. It is possible to control both | ||||
authorized hosts and policy for an arbitrary number of domains from a | ||||
single record. | ||||
redirect = "redirect" "=" domain-spec | redirect = "redirect" "=" domain-spec | |||
If all mechanisms fail to match, and a "redirect" modifier is | ||||
present, then processing proceeds as follows: | ||||
The domain-spec portion of the redirect section is expanded as per | The domain-spec portion of the redirect section is expanded as per | |||
the macro rules in Section 8. Then check_host() is evaluated with | the macro rules in Section 8. Then check_host() is evaluated with | |||
the resulting string as the <domain>. The <ip> and <sender> | the resulting string as the <domain>. The <ip> and <sender> | |||
arguments remain the same as current evaluation of check_host(). | arguments remain the same as in the current evaluation of | |||
check_host(). | ||||
The result of this new evaluation of check_host() is then considered | The result of this new evaluation of check_host() is then considered | |||
the result of the current evaluation with the exception that if no | the result of the current evaluation with the exception that if no | |||
SPF record is found, or if the target-name is malformed, the result | SPF record is found, or if the target-name is malformed, the result | |||
is a "PermError" rather than "None". | is a "permerror" rather than "none". | |||
Note that the newly-queried domain may itself specify redirect | Note that the newly-queried domain can itself specify redirect | |||
processing. | processing. | |||
This facility is intended for use by organizations that wish to apply | This facility is intended for use by organizations that wish to apply | |||
the same record to multiple domains. For example: | the same record to multiple domains. For example: | |||
la.example.com. TXT "v=spf1 redirect=_spf.example.com" | la.example.com. TXT "v=spf1 redirect=_spf.example.com" | |||
ny.example.com. TXT "v=spf1 redirect=_spf.example.com" | ny.example.com. TXT "v=spf1 redirect=_spf.example.com" | |||
sf.example.com. TXT "v=spf1 redirect=_spf.example.com" | sf.example.com. TXT "v=spf1 redirect=_spf.example.com" | |||
_spf.example.com. TXT "v=spf1 mx:example.com -all" | _spf.example.com. TXT "v=spf1 mx:example.com -all" | |||
In this example, mail from any of the three domains is described by | In this example, mail from any of the three domains is described by | |||
the same record. This can be an administrative advantage. | the same record. This can be an administrative advantage. | |||
Note: In general, the domain "A" cannot reliably use a redirect to | Note: In general, the domain "A" cannot reliably use a redirect to | |||
another domain "B" not under the same administrative control. Since | another domain "B" not under the same administrative control. Since | |||
the <sender> stays the same, there is no guarantee that the record at | the <sender> stays the same, there is no guarantee that the record at | |||
domain "B" will correctly work for mailboxes in domain "A", | domain "B" will correctly work for mailboxes in domain "A", | |||
especially if domain "B" uses mechanisms involving localparts. An | especially if domain "B" uses mechanisms involving local-parts. An | |||
"include" directive may be more appropriate. | "include" directive is generally be more appropriate. | |||
For clarity, it is RECOMMENDED that any "redirect" modifier appear as | For clarity, it is RECOMMENDED that any "redirect" modifier appear as | |||
the very last term in a record. | the very last term in a record. | |||
6.2. exp: Explanation | 6.2. exp: Explanation | |||
explanation = "exp" "=" domain-spec | explanation = "exp" "=" domain-spec | |||
If check_host() results in a "Fail" due to a mechanism match (such as | If check_host() results in a "fail" due to a mechanism match (such as | |||
"-all"), and the "exp" modifier is present, then the explanation | "-all"), and the "exp" modifier is present, then the explanation | |||
string returned is computed as described below. If no "exp" modifier | string returned is computed as described below. If no "exp" modifier | |||
is present, then either a default explanation string or an empty | is present, then either a default explanation string or an empty | |||
explanation string may be returned. | explanation string MUST be returned. | |||
The <domain-spec> is macro expanded (see Section 8) and becomes the | The domain-spec is macro expanded (see Section 8) and becomes the | |||
<target-name>. The DNS TXT record for the <target-name> is fetched. | <target-name>. The DNS TXT record for the <target-name> is fetched. | |||
If <domain-spec> is empty, or there are any DNS processing errors | If there are any DNS processing errors (any RCODE other than 0), or | |||
(any RCODE other than 0), or if no records are returned, or if more | if no records are returned, or if more than one record is returned, | |||
than one record is returned, or if there are syntax errors in the | or if there are syntax errors in the explanation string, then proceed | |||
explanation string, then proceed as if no exp modifier was given. | as if no exp modifier was given. | |||
The fetched TXT record's strings are concatenated with no spaces, and | The fetched TXT record's strings are concatenated with no spaces, and | |||
then treated as an <explain-string>, which is macro-expanded. This | then treated as an explain-string, which is macro-expanded. This | |||
final result is the explanation string. Implementations MAY limit | final result is the explanation string. Implementations MAY limit | |||
the length of the resulting explanation string to allow for other | the length of the resulting explanation string to allow for other | |||
protocol constraints and/or reasonable processing limits. Since the | protocol constraints and/or reasonable processing limits. Since the | |||
explanation string is intended for an SMTP response and [RFC2821] | explanation string is intended for an SMTP response and [RFC5321] | |||
Section 2.4 says that responses are in [US-ASCII], the explanation | Section 2.4 says that responses are in [US-ASCII], the explanation | |||
string is also limited to US-ASCII. | string MUST be limited to US-ASCII. | |||
Software evaluating check_host() can use this string to communicate | Software evaluating check_host() can use this string to communicate | |||
information from the publishing domain in the form of a short message | information from the publishing domain in the form of a short message | |||
or URL. Software SHOULD make it clear that the explanation string | or URL. Software SHOULD make it clear that the explanation string | |||
comes from a third party. For example, it can prepend the macro | comes from a third party. For example, it can prepend the macro | |||
string "%{o} explains: " to the explanation, such as shown in Section | string "%{o} explains: " to the explanation, such as shown in | |||
2.5.4. | Section 2.5.4. | |||
Suppose example.com has this record: | Suppose example.com has this record: | |||
v=spf1 mx -all exp=explain._spf.%{d} | v=spf1 mx -all exp=explain._spf.%{d} | |||
Here are some examples of possible explanation TXT records at | Here are some examples of possible explanation TXT records at | |||
explain._spf.example.com: | explain._spf.example.com: | |||
"Mail from example.com should only be sent by its own servers." | "Mail from example.com should only be sent by its own servers." | |||
-- a simple, constant message | -- a simple, constant message | |||
skipping to change at page 25, line 7 | skipping to change at page 32, line 5 | |||
"See http://%{d}/why.html?s=%{S}&i=%{I}" | "See http://%{d}/why.html?s=%{S}&i=%{I}" | |||
-- a complicated example that constructs a URL with the | -- a complicated example that constructs a URL with the | |||
arguments to check_host() so that a web page can be | arguments to check_host() so that a web page can be | |||
generated with detailed, custom instructions | generated with detailed, custom instructions | |||
Note: During recursion into an "include" mechanism, an exp= modifier | Note: During recursion into an "include" mechanism, an exp= modifier | |||
from the <target-name> MUST NOT be used. In contrast, when executing | from the <target-name> MUST NOT be used. In contrast, when executing | |||
a "redirect" modifier, an exp= modifier from the original domain MUST | a "redirect" modifier, an exp= modifier from the original domain MUST | |||
NOT be used. | NOT be used. | |||
7. The Received-SPF Header Field | 7. Recording The Result | |||
It is RECOMMENDED that SMTP receivers record the result of SPF | It is RECOMMENDED that SMTP receivers record the result of SPF | |||
processing in the message header. If an SMTP receiver chooses to do | processing in the message header. There are two methods for doing | |||
so, it SHOULD use the "Received-SPF" header field defined here for | this: the Received-SPF header field defined here and the more generic | |||
each identity that was checked. This information is intended for the | Authentication-Results header field defined in [RFC5451]. Because | |||
recipient. (Information intended for the sender is described in | these fields are generally used within a receiving ADMD, it is a | |||
Section 6.2, Explanation.) | local policy choice which to include. In general, the more broadly | |||
applicable Authentication-Results header field ought to be used, but | ||||
it SHOULD be used in such a way that it conveys the same information | ||||
that the verifier would have provided in a Received-SPF header field | ||||
if that had been used. | ||||
The Received-SPF header field is a trace field (see [RFC2822] Section | If an SMTP receiver chooses to do so, it SHOULD use one of these | |||
header fields for each identity that was checked. This information | ||||
is intended for the recipient. (Information intended for the sender | ||||
is described in Section 6.2, Explanation.) | ||||
7.1. The Received-SPF Header Field | ||||
The Received-SPF header field is a trace field (see [RFC5322] Section | ||||
3.6.7) and SHOULD be prepended to the existing header, above the | 3.6.7) and SHOULD be prepended to the existing header, above the | |||
Received: field that is generated by the SMTP receiver. It MUST | Received: field that is generated by the SMTP receiver. It MUST | |||
appear above all other Received-SPF fields in the message. The | appear above all other Received-SPF fields in the message. The | |||
header field has the following format: | header field has the following format: | |||
header-field = "Received-SPF:" [CFWS] result FWS [comment FWS] | header-field = "Received-SPF:" [CFWS] result FWS [comment FWS] | |||
[ key-value-list ] CRLF | [ key-value-list ] CRLF | |||
result = "Pass" / "Fail" / "SoftFail" / "Neutral" / | result = "pass" / "fail" / "softfail" / "neutral" / | |||
"None" / "TempError" / "PermError" | "none" / "temperror" / "permerror" | |||
key-value-list = key-value-pair *( ";" [CFWS] key-value-pair ) | key-value-list = key-value-pair *( ";" [CFWS] key-value-pair ) | |||
[";"] | [";"] | |||
key-value-pair = key [CFWS] "=" ( dot-atom / quoted-string ) | key-value-pair = key [CFWS] "=" ( dot-atom / quoted-string ) | |||
key = "client-ip" / "envelope-from" / "helo" / | key = "client-ip" / "envelope-from" / "helo" / | |||
"problem" / "receiver" / "identity" / | "problem" / "receiver" / "identity" / | |||
mechanism / "x-" name / name | mechanism / name | |||
identity = "mailfrom" ; for the "MAIL FROM" identity | identity = "mailfrom" ; for the "MAIL FROM" identity | |||
/ "helo" ; for the "HELO" identity | / "helo" ; for the "HELO" identity | |||
/ name ; other identities | / name ; other identities | |||
dot-atom = <unquoted word as per [RFC2822]> | dot-atom = <unquoted word as per [RFC5322]> | |||
quoted-string = <quoted string as per [RFC2822]> | quoted-string = <quoted string as per [RFC5322]> | |||
comment = <comment string as per [RFC2822]> | comment = <comment string as per [RFC5322]> | |||
CFWS = <comment or folding white space as per [RFC2822]> | CFWS = <comment or folding white space as per [RFC5322]> | |||
FWS = <folding white space as per [RFC2822]> | FWS = <folding white space as per [RFC5322]> | |||
CRLF = <standard end-of-line token as per [RFC2822]> | CRLF = <standard end-of-line token as per [RFC2532]> | |||
The header field SHOULD include a "(...)" style <comment> after the | The header field SHOULD include a "(...)" style comment after the | |||
result, conveying supporting information for the result, such as | result, conveying supporting information for the result, such as | |||
<ip>, <sender>, and <domain>. | <ip>, <sender>, and <domain>. | |||
The following key-value pairs are designed for later machine parsing. | The following key-value pairs are designed for later machine parsing. | |||
SPF clients SHOULD give enough information so that the SPF results | SPF verifiers SHOULD give enough information so that the SPF results | |||
can be verified. That is, at least "client-ip", "helo", and, if the | can be verified. That is, at least "client-ip", "helo", and, if the | |||
"MAIL FROM" identity was checked, "envelope-from". | "MAIL FROM" identity was checked, "envelope-from". | |||
client-ip the IP address of the SMTP client | client-ip the IP address of the SMTP client | |||
envelope-from the envelope sender mailbox | envelope-from the envelope sender mailbox | |||
helo the host name given in the HELO or EHLO command | helo the host name given in the HELO or EHLO command | |||
mechanism the mechanism that matched (if no mechanisms matched, | mechanism the mechanism that matched (if no mechanisms matched, | |||
substitute the word "default") | substitute the word "default") | |||
problem if an error was returned, details about the error | problem if an error was returned, details about the error | |||
receiver the host name of the SPF verifier | ||||
receiver the host name of the SPF client | ||||
identity the identity that was checked; see the <identity> ABNF | identity the identity that was checked; see the <identity> ABNF | |||
rule | rule | |||
Other keys may be defined by SPF clients. Until a new key name | Other keys MAY be defined by SPF verifiers. | |||
becomes widely accepted, new key names should start with "x-". | ||||
SPF clients MUST make sure that the Received-SPF header field does | SPF verifiers MUST make sure that the Received-SPF header field does | |||
not contain invalid characters, is not excessively long, and does not | not contain invalid characters, is not excessively long (See | |||
contain malicious data that has been provided by the sender. | [RFC5322] Section 2.1.1), and does not contain malicious data that | |||
has been provided by the sender. | ||||
Examples of various header styles that could be generated are the | Examples of various header field styles that could be generated are | |||
following: | the following: | |||
Received-SPF: Pass (mybox.example.org: domain of | Received-SPF: pass (mybox.example.org: domain of | |||
myname@example.com designates 192.0.2.1 as permitted sender) | myname@example.com designates 192.0.2.1 as permitted sender) | |||
receiver=mybox.example.org; client-ip=192.0.2.1; | receiver=mybox.example.org; client-ip=192.0.2.1; | |||
envelope-from=<myname@example.com>; helo=foo.example.com; | envelope-from="myname@example.com"; helo=foo.example.com; | |||
Received-SPF: Fail (mybox.example.org: domain of | Received-SPF: fail (mybox.example.org: domain of | |||
myname@example.com does not designate | myname@example.com does not designate | |||
192.0.2.1 as permitted sender) | 192.0.2.1 as permitted sender) | |||
identity=mailfrom; client-ip=192.0.2.1; | identity=mailfrom; client-ip=192.0.2.1; | |||
envelope-from=<myname@example.com>; | envelope-from="myname@example.com"; | |||
7.2. SPF Results in the Authentication-Results Header Field | ||||
As mentioned in Section 7, the Authentication-Results header field is | ||||
designed to communicate lists of tests a border MTA did and their | ||||
results. The specified elements of the field provide less | ||||
information than the SPF-Received field: | ||||
Authentication-Results: myhost.example.org; spf=pass | ||||
smtp.mailfrom=example.net | ||||
Received-SPF: pass (myhost.example.org: domain of | ||||
myname@example.com designates 192.0.2.1 as permitted sender) | ||||
receiver=mybox.example.org; client-ip=192.0.2.1; | ||||
envelope-from="myname@example.com"; helo=foo.example.com; | ||||
It is, however, possible to add CFWS in the "reason" part of an | ||||
Authentication-Results header field and provide the equivalent | ||||
information. Receivers SHOULD include the same information they | ||||
would have provided if they had used the Received-SPF field. | ||||
The reason SHOULD include a key-value-list with keys provinding | ||||
information normally included in a Received-SPF header field that is | ||||
not already part of the Authentication-Results header field. That | ||||
is, at least "client-ip", "helo", and, if the "MAIL FROM" identity | ||||
was checked, "envelope-from". Authentication-Results header fields | ||||
can contain results for more than one authentication, so one field | ||||
can provide results for both an "MAIL FROM" check and an "HELO" | ||||
check. | ||||
reasonspec = <reason per [RFC5451]> | ||||
A suitably enhanced Authentication-Results header field might look | ||||
like (for a "MAIL FROM" check in this example): | ||||
Authentication-Results: myhost.example.org; spf=pass | ||||
reason="client-ip=192.0.2.1; smtp.helo=foo.example.com" | ||||
smtp.mailfrom=user@example.net | ||||
8. Macros | 8. Macros | |||
8.1. Macro Definitions | 8.1. Macro Definitions | |||
Many mechanisms and modifiers perform macro expansion on part of the | Many mechanisms and modifiers perform macro expansion on a term. | |||
term. | ||||
domain-spec = macro-string domain-end | domain-spec = macro-string domain-end | |||
domain-end = ( "." toplabel [ "." ] ) / macro-expand | domain-end = ( "." toplabel [ "." ] ) / macro-expand | |||
toplabel = ( *alphanum ALPHA *alphanum ) / | toplabel = ( *alphanum ALPHA *alphanum ) / | |||
( 1*alphanum "-" *( alphanum / "-" ) alphanum ) | ( 1*alphanum "-" *( alphanum / "-" ) alphanum ) | |||
; LDH rule plus additional TLD restrictions | ; LDH rule plus additional TLD restrictions | |||
; (see [RFC3696], Section 2) | ; (see [RFC3696], Section 2 for background) | |||
alphanum = ALPHA / DIGIT | alphanum = ALPHA / DIGIT | |||
explain-string = *( macro-string / SP ) | explain-string = *( macro-string / SP ) | |||
macro-string = *( macro-expand / macro-literal ) | macro-string = *( macro-expand / macro-literal ) | |||
macro-expand = ( "%{" macro-letter transformers *delimiter "}" ) | macro-expand = ( "%{" macro-letter transformers *delimiter "}" ) | |||
/ "%%" / "%_" / "%-" | / "%%" / "%_" / "%-" | |||
macro-literal = %x21-24 / %x26-7E | macro-literal = %x21-24 / %x26-7E | |||
; visible characters except "%" | ; visible characters except "%" | |||
macro-letter = "s" / "l" / "o" / "d" / "i" / "p" / "h" / | macro-letter = "s" / "l" / "o" / "d" / "i" / "p" / "h" / | |||
"c" / "r" / "t" | "c" / "r" / "t" / "v" | |||
transformers = *DIGIT [ "r" ] | transformers = *DIGIT [ "r" ] | |||
delimiter = "." / "-" / "+" / "," / "/" / "_" / "=" | delimiter = "." / "-" / "+" / "," / "/" / "_" / "=" | |||
A literal "%" is expressed by "%%". | A literal "%" is expressed by "%%". | |||
"%_" expands to a single " " space. | "%_" expands to a single " " space. | |||
"%-" expands to a URL-encoded space, viz., "%20". | "%-" expands to a URL-encoded space, viz., "%20". | |||
The following macro letters are expanded in term arguments: | The following macro letters are expanded in term arguments: | |||
s = <sender> | s = <sender> | |||
l = local-part of <sender> | l = local-part of <sender> | |||
o = domain of <sender> | o = domain of <sender> | |||
d = <domain> | d = <domain> | |||
i = <ip> | i = <ip> | |||
p = the validated domain name of <ip> | p = the validated domain name of <ip> (deprecated) | |||
v = the string "in-addr" if <ip> is ipv4, or "ip6" if <ip> is ipv6 | v = the string "in-addr" if <ip> is ipv4, or "ip6" if <ip> is ipv6 | |||
h = HELO/EHLO domain | h = HELO/EHLO domain | |||
The following macro letters are allowed only in "exp" text: | The following macro letters are allowed only in "exp" text: | |||
c = SMTP client IP (easily readable format) | c = SMTP client IP (easily readable format) | |||
r = domain name of host performing the check | r = domain name of host performing the check | |||
t = current timestamp | t = current timestamp | |||
A '%' character not followed by a '{', '%', '-', or '_' character is | A '%' character not followed by a '{', '%', '-', or '_' character is | |||
a syntax error. So | a syntax error. So | |||
-exists:%(ir).sbl.spamhaus.example.org | -exists:%(ir).sbl.spamhaus.example.org | |||
is incorrect and will cause check_host() to yield a "permerror". | ||||
is incorrect and will cause check_host() to return a "PermError". | ||||
Instead, say | Instead, say | |||
-exists:%{ir}.sbl.spamhaus.example.org | -exists:%{ir}.sbl.spamhaus.example.org | |||
Optional transformers are the following: | Optional transformers are the following: | |||
*DIGIT = zero or more digits | *DIGIT = zero or more digits | |||
'r' = reverse value, splitting on dots by default | 'r' = reverse value, splitting on dots by default | |||
If transformers or delimiters are provided, the replacement value for | If transformers or delimiters are provided, the replacement value for | |||
a macro letter is split into parts. After performing any reversal | a macro letter is split into parts. After performing any reversal | |||
operation and/or removal of left-hand parts, the parts are rejoined | operation and/or removal of left-hand parts, the parts are rejoined | |||
skipping to change at page 28, line 31 | skipping to change at page 37, line 22 | |||
*DIGIT = zero or more digits | *DIGIT = zero or more digits | |||
'r' = reverse value, splitting on dots by default | 'r' = reverse value, splitting on dots by default | |||
If transformers or delimiters are provided, the replacement value for | If transformers or delimiters are provided, the replacement value for | |||
a macro letter is split into parts. After performing any reversal | a macro letter is split into parts. After performing any reversal | |||
operation and/or removal of left-hand parts, the parts are rejoined | operation and/or removal of left-hand parts, the parts are rejoined | |||
using "." and not the original splitting characters. | using "." and not the original splitting characters. | |||
By default, strings are split on "." (dots). Note that no special | By default, strings are split on "." (dots). Note that no special | |||
treatment is given to leading, trailing, or consecutive delimiters, | treatment is given to leading, trailing, or consecutive delimiters in | |||
and so the list of parts may contain empty strings. Older | input strings, and so the list of parts might contain empty strings. | |||
implementations of SPF prohibit trailing dots in domain names, so | Some older implementations of SPF prohibit trailing dots in domain | |||
trailing dots should not be published by domain owners, although they | names, so trailing dots SHOULD NOT be published by domain owners, | |||
must be accepted by implementations conforming to this document. | although they MUST be accepted by implementations conforming to this | |||
Macros may specify delimiter characters that are used instead of ".". | document. Macros MAY specify delimiter characters that are used | |||
instead of ".". | ||||
The 'r' transformer indicates a reversal operation: if the client IP | The 'r' transformer indicates a reversal operation: if the client IP | |||
address were 192.0.2.1, the macro %{i} would expand to "192.0.2.1" | address were 192.0.2.1, the macro %{i} would expand to "192.0.2.1" | |||
and the macro %{ir} would expand to "1.2.0.192". | and the macro %{ir} would expand to "1.2.0.192". | |||
The DIGIT transformer indicates the number of right-hand parts to | The DIGIT transformer indicates the number of right-hand parts to | |||
use, after optional reversal. If a DIGIT is specified, the value | use, after optional reversal. If a DIGIT is specified, the value | |||
MUST be nonzero. If no DIGITs are specified, or if the value | MUST be nonzero. If no DIGITs are specified, or if the value | |||
specifies more parts than are available, all the available parts are | specifies more parts than are available, all the available parts are | |||
used. If the DIGIT was 5, and only 3 parts were available, the macro | used. If the DIGIT was 5, and only 3 parts were available, the macro | |||
interpreter would pretend the DIGIT was 3. Implementations MUST | interpreter would pretend the DIGIT was 3. Implementations MUST | |||
support at least a value of 128, as that is the maximum number of | support at least a value of 128, as that is the maximum number of | |||
labels in a domain name. | labels in a domain name. | |||
The "s" macro expands to the <sender> argument. It is an E-Mail | The "s" macro expands to the <sender> argument. It is an email | |||
address with a localpart, an "@" character, and a domain. The "l" | address with a local-part, an "@" character, and a domain. The "l" | |||
macro expands to just the localpart. The "o" macro expands to just | macro expands to just the local-part. The "o" macro expands to just | |||
the domain part. Note that these values remain the same during | the domain part. Note that these values remain the same during | |||
recursive and chained evaluations due to "include" and/or "redirect". | recursive and chained evaluations due to "include" and/or "redirect". | |||
Note also that if the original <sender> had no localpart, the | Note also that if the original <sender> had no local-part, the local- | |||
localpart was set to "postmaster" in initial processing (see Section | part was set to "postmaster" in initial processing (see Section 4.3). | |||
4.3). | ||||
For IPv4 addresses, both the "i" and "c" macros expand to the | For IPv4 addresses, both the "i" and "c" macros expand to the | |||
standard dotted-quad format. | standard dotted-quad format. | |||
For IPv6 addresses, the "i" macro expands to a dot-format address; it | For IPv6 addresses, the "i" macro expands to a dot-format address; it | |||
is intended for use in %{ir}. The "c" macro may expand to any of the | is intended for use in %{ir}. The "c" macro MAY expand to any of the | |||
hexadecimal colon-format addresses specified in [RFC3513], Section | hexadecimal colon-format addresses specified in [RFC4291], Section | |||
2.2. It is intended for humans to read. | 2.2. It is intended for humans to read. | |||
The "p" macro expands to the validated domain name of <ip>. The | The "p" macro expands to the validated domain name of <ip>. The | |||
procedure for finding the validated domain name is defined in Section | procedure for finding the validated domain name is defined in | |||
5.5. If the <domain> is present in the list of validated domains, it | Section 5.5. If the <domain> is present in the list of validated | |||
SHOULD be used. Otherwise, if a subdomain of the <domain> is | domains, it SHOULD be used. Otherwise, if a subdomain of the | |||
present, it SHOULD be used. Otherwise, any name from the list may be | <domain> is present, it SHOULD be used. Otherwise, any name from the | |||
used. If there are no validated domain names or if a DNS error | list MAY be used. If there are no validated domain names or if a DNS | |||
occurs, the string "unknown" is used. | error occurs, the string "unknown" is used. This macro is deprecated | |||
and SHOULD NOT be used. | ||||
The "r" macro expands to the name of the receiving MTA. This SHOULD | The "r" macro expands to the name of the receiving MTA. This SHOULD | |||
be a fully qualified domain name, but if one does not exist (as when | be a fully qualified domain name, but if one does not exist (as when | |||
the checking is done by a MUA) or if policy restrictions dictate | the checking is done by a MUA) or if policy restrictions dictate | |||
otherwise, the word "unknown" SHOULD be substituted. The domain name | otherwise, the word "unknown" SHOULD be substituted. The domain name | |||
may be different from the name found in the MX record that the client | can be different from the name found in the MX record that the client | |||
MTA used to locate the receiving MTA. | MTA used to locate the receiving MTA. | |||
The "t" macro expands to the decimal representation of the | The "t" macro expands to the decimal representation of the | |||
approximate number of seconds since the Epoch (Midnight, January 1, | approximate number of seconds since the Epoch (Midnight, January 1, | |||
1970, UTC). This is the same value as is returned by the POSIX | 1970, UTC) at the time of the evaluation. This is the same value as | |||
time() function in most standards-compliant libraries. | is returned by the POSIX time() function in most standards-compliant | |||
libraries. | ||||
When the result of macro expansion is used in a domain name query, if | When the result of macro expansion is used in a domain name query, if | |||
the expanded domain name exceeds 253 characters (the maximum length | the expanded domain name exceeds 253 characters (the maximum length | |||
of a domain name), the left side is truncated to fit, by removing | of a domain name), the left side is truncated to fit, by removing | |||
successive domain labels until the total length does not exceed 253 | successive domain labels (and their following dots) until the total | |||
characters. | length does not exceed 253 characters. | |||
Uppercased macros expand exactly as their lowercased equivalents, and | Uppercased macros expand exactly as their lowercased equivalents, and | |||
are then URL escaped. URL escaping must be performed for characters | are then URL escaped. URL escaping must be performed for characters | |||
not in the "uric" set, which is defined in [RFC3986]. | not in the "unreserved" set, which is defined in [RFC3986]. | |||
Note: Care must be taken so that macro expansion for legitimate | Note: Care must be taken so that macro expansion for legitimate email | |||
E-Mail does not exceed the 63-character limit on DNS labels. The | does not exceed the 63-character limit on DNS labels. The local-part | |||
localpart of E-Mail addresses, in particular, can have more than 63 | of email addresses, in particular, can have more than 63 characters | |||
characters between dots. | between dots. | |||
Note: Domains should avoid using the "s", "l", "o", or "h" macros in | Note: Domains SHOULD avoid using the "s", "l", "o", or "h" macros in | |||
conjunction with any mechanism directive. Although these macros are | conjunction with any mechanism directive. Although these macros are | |||
powerful and allow per-user records to be published, they severely | powerful and allow per-user records to be published, they severely | |||
limit the ability of implementations to cache results of check_host() | limit the ability of implementations to cache results of check_host() | |||
and they reduce the effectiveness of DNS caches. | and they reduce the effectiveness of DNS caches. | |||
Implementations should be aware that if no directive processed during | Note: If no directive processed during the evaluation of check_host() | |||
the evaluation of check_host() contains an "s", "l", "o", or "h" | contains an "s", "l", "o", or "h" macro, then the results of the | |||
macro, then the results of the evaluation can be cached on the basis | evaluation can be cached on the basis of <domain> and <ip> alone for | |||
of <domain> and <ip> alone for as long as the shortest Time To Live | as long as the shortest Time To Live (TTL) of all the DNS records | |||
(TTL) of all the DNS records involved. | involved. | |||
8.2. Expansion Examples | 8.2. Expansion Examples | |||
The <sender> is strong-bad@email.example.com. | The <sender> is strong-bad@email.example.com. | |||
The IPv4 SMTP client IP is 192.0.2.3. | The IPv4 SMTP client IP is 192.0.2.3. | |||
The IPv6 SMTP client IP is 2001:DB8::CB01. | The IPv6 SMTP client IP is 2001:DB8::CB01. | |||
The PTR domain name of the client IP is mx.example.org. | The PTR domain name of the client IP is mx.example.org. | |||
macro expansion | macro expansion | |||
------- ---------------------------- | ------- ---------------------------- | |||
skipping to change at page 31, line 20 | skipping to change at page 40, line 4 | |||
bad.strong.lp.3.2.0.192.in-addr._spf.example.com | bad.strong.lp.3.2.0.192.in-addr._spf.example.com | |||
%{ir}.%{v}.%{l1r-}.lp._spf.%{d2} | %{ir}.%{v}.%{l1r-}.lp._spf.%{d2} | |||
3.2.0.192.in-addr.strong.lp._spf.example.com | 3.2.0.192.in-addr.strong.lp._spf.example.com | |||
%{d2}.trusted-domains.example.net | %{d2}.trusted-domains.example.net | |||
example.com.trusted-domains.example.net | example.com.trusted-domains.example.net | |||
IPv6: | IPv6: | |||
%{ir}.%{v}._spf.%{d2} 1.0.B.C.0.0.0.0. | %{ir}.%{v}._spf.%{d2} 1.0.B.C.0.0.0.0. | |||
0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.B.D.0.1.0.0.2.ip6._spf.example.com | 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.B.D.0.1.0.0.2.ip6._spf.example.com | |||
9. Implications | 9. Implications | |||
This section outlines the major implications that adoption of this | This section outlines the major implications that adoption of this | |||
document will have on various entities involved in Internet E-Mail. | document will have on various entities involved in Internet email. | |||
It is intended to make clear to the reader where this document | It is intended to make clear to the reader where this document | |||
knowingly affects the operation of such entities. This section is | knowingly affects the operation of such entities. This section is | |||
not a "how-to" manual, or a "best practices" document, and it is not | not a "how-to" manual, or a "best practices" document, and it is not | |||
a comprehensive list of what such entities should do in light of this | a comprehensive list of what such entities should do in light of this | |||
document. | document. | |||
This section is non-normative. | This section is non-normative. [RFC5598] describes the Internet | |||
email architecture. This section is organized based on the different | ||||
segments of the architecture. | ||||
9.1. Sending Domains | 9.1. Sending Domains | |||
Domains that wish to be compliant with this specification will need | Originating ADMDs (ADministrative Management Domains - [RFC5598] | |||
to determine the list of hosts that they allow to use their domain | Section 2.2.1 and Section 2.3) that wish to be compliant with this | |||
name in the "HELO" and "MAIL FROM" identities. It is recognized that | specification will need to determine the list of relays ([RFC5598] | |||
forming such a list is not just a simple technical exercise, but | Section 2.2.2) that they allow to use their domain name in the "HELO" | |||
involves policy decisions with both technical and administrative | and "MAIL FROM" identities when relaying to other ADMDs. It is | |||
considerations. | recognized that forming such a list is not just a simple technical | |||
exercise, but involves policy decisions with both technical and | ||||
administrative considerations. | ||||
It can be helpful to publish records that include a "tracking | 9.1.1. DNS Resource Considerations | |||
Minimizing the DNS resources required for SPF lookups can be done by | ||||
choosing directives that require less DNS information and by placing | ||||
lower-cost mechanisms earlier in the SPF record. | ||||
+----------+--------+-----------------+ | ||||
| term | cost | limit | | ||||
+----------+--------+-----------------+ | ||||
| ip4/ip6 | 0 | - | | ||||
| a | 1 | 10 | | ||||
| include | 1 | 10 | | ||||
| redirect | 1 | 10 | | ||||
| exists | 1 | 10 | | ||||
| mx | 1 + N* | 10 and N* <= 10 | | ||||
| ptr/%{p} | 1 + N* | 10 and N* <= 10 | | ||||
| all | 0 | 1 | | ||||
+----------+--------+-----------------+ | ||||
* N is the number of RRs found during each term evaluation | ||||
Section 4.6.4 specifies the limits receivers have to use. It is | ||||
essential to publish records that do not exceed these requirements. | ||||
It is also required to carefully weight the cost and the | ||||
maintainability of licit solutions. | ||||
For example, consider a domain set up as follows: | ||||
example.com. IN MX 10 mx.example.com. | ||||
IN MX 20 mx2.example.com. | ||||
mx.example.com. IN A 192.0.2.1 | ||||
mx2.example.com. IN A 192.0.2.129 | ||||
Assume the administrative point is to authorize (pass) mx and mx2 | ||||
while failing every other host. Compare the following solutions: | ||||
Best record: | ||||
example.com. IN TXT "v=spf1 ip4:192.0.2.1 ip4:192.0.2.129 -all" | ||||
Good record: | ||||
$ORIGIN example.com. | ||||
@ IN TXT "v=spf1 a:authorized_spf.example.com -all" | ||||
authorized_spf IN A 192.0.2.1 | ||||
IN A 192.0.2.129 | ||||
Expensive record: | ||||
example.com. IN TXT "v=spf1 mx:example.com -all" | ||||
Wasteful, bad record: | ||||
example.com. IN TXT "v=spf1 ip4:192.0.2.0/24 mx -all" | ||||
9.1.2. Administrator's Considerations | ||||
There might be administrative considerations: using "a" over "ip4" or | ||||
"ip6" allows hosts to be renumbered easily. Using "mx" over "a" | ||||
allows the set of mail hosts to be changed easily. Unless such | ||||
changes are common, it is better to use the less resource intensive | ||||
mechanisms like "ip4" and "ip6" over "a" or "a" or "mx". | ||||
In some specific cases, standard advice on record content is | ||||
appropriate. Publishing SPF records for domains that send no mail is | ||||
a well established best practice. The record for a domain that sends | ||||
no mail is: | ||||
www.example.com. IN TXT "v=spf1 -all" | ||||
Publishing SPF records for individual hosts is also best practice. | ||||
The hostname is generally the identity used in the 5321.HELO/.EHLO | ||||
command. In the case of messages with a null 5321.MailFrom, this is | ||||
used as the domain for 5321.MailFrom SPF checks, in addition to being | ||||
used in 5321.HELO/.EHLO based SPF checks. The standard SPF record | ||||
for an individual host that is involved in mail processing is: | ||||
relay.example.com. IN TXT "v=spf1 a -all" | ||||
Validating correct deployment is difficult. [RFC6652] describes one | ||||
mechanism for soliciting feedback on SPF failures. Another approach | ||||
that can be helpful to publish records that include a "tracking | ||||
exists:" mechanism. By looking at the name server logs, a rough list | exists:" mechanism. By looking at the name server logs, a rough list | |||
may then be generated. For example: | can then be generated. For example: | |||
v=spf1 exists:_h.%{h}._l.%{l}._o.%{o}._i.%{i}._spf.%{d} ?all | v=spf1 exists:_h.%{h}._l.%{l}._o.%{o}._i.%{i}._spf.%{d} ?all | |||
9.2. Mailing Lists | Regardless of the method used, understanding the ADMD's outbound mail | |||
architecture is essential to effective deployment. | ||||
9.1.3. Bounces | ||||
As explained in Section 1.3.3, [RFC5321] allows the reverse-path to | ||||
be null, which is typical of some Delivery Status Notification | ||||
[RFC3464], commonly called email bounces. In this case the only | ||||
entity available for performing an SPF check is the "HELO" identity | ||||
defined in Section 1.3.4. SPF functionality is enhanced by | ||||
administrators ensuring this identity is set correctly and has an | ||||
appropriate SPF record. It is normal to have the HELO identity set | ||||
to hostname instead of domain. Zone file generation for significant | ||||
numbers of hosts can be consolidated using the redirect modifier and | ||||
scripted for initial deployment. Specific deployment advice is given | ||||
above in Section Section 9.1.2. | ||||
9.2. Mediators | ||||
Broadly speaking, there are two types of mediating ADMDs that can | ||||
affect SPF deployment of other ADMDs: mailing lists (see [RFC5598] | ||||
Section 5.3) and ReSenders ([RFC5598] Section 5.2). | ||||
9.2.1. Mailing Lists | ||||
Mailing lists must be aware of how they re-inject mail that is sent | Mailing lists must be aware of how they re-inject mail that is sent | |||
to the list. Mailing lists MUST comply with the requirements in | to the list. Mailing lists MUST comply with the requirements in | |||
[RFC2821], Section 3.10, and [RFC1123], Section 5.3.6, that say that | [RFC5321], Section 3.10, and [RFC1123], Section 5.3.6, that say that | |||
the reverse-path MUST be changed to be the mailbox of a person or | the reverse-path MUST be changed to be the mailbox of a person or | |||
other entity who administers the list. Whereas the reasons for | other entity who administers the list. Whereas the reasons for | |||
changing the reverse-path are many and long-standing, SPF adds | changing the reverse-path are many and long-standing, SPF adds | |||
enforcement to this requirement. | enforcement to this requirement. | |||
In practice, almost all mailing list software in use already complies | In practice, almost all mailing list software in use already complies | |||
with this requirement. Mailing lists that do not comply may or may | with this requirement. Mailing lists that do not comply might | |||
not encounter problems depending on how access to the list is | encounter problems depending on how access to the list is restricted. | |||
restricted. Such lists that are entirely internal to a domain (only | Such lists that are entirely internal to a domain (only people in the | |||
people in the domain can send to or receive from the list) are not | domain can send to or receive from the list) are not affected. | |||
affected. | ||||
9.3. Forwarding Services and Aliases | 9.2.2. Forwarding Services and Aliases | |||
Forwarding services take mail that is received at a mailbox and | Forwarding services take mail that is received at a mailbox and | |||
direct it to some external mailbox. At the time of this writing, the | direct it to some external mailbox. At the time of this writing, the | |||
near-universal practice of such services is to use the original "MAIL | near-universal practice of such services is to use the original "MAIL | |||
FROM" of a message when re-injecting it for delivery to the external | FROM" of a message when re-injecting it for delivery to the external | |||
mailbox. [RFC1123] and [RFC2821] describe this action as an "alias" | mailbox. [RFC1123] and [RFC5321] describe this action as an "alias" | |||
rather than a "mail list". This means that the external mailbox's | rather than a "mail list". This means the external mailbox's MTA | |||
MTA sees all such mail in a connection from a host of the forwarding | sees all such mail in a connection from a host of the forwarding | |||
service, and so the "MAIL FROM" identity will not, in general, pass | service, and so the "MAIL FROM" identity will not, in general, pass | |||
authorization. | authorization. | |||
There are three places that techniques can be used to ameliorate this | There are three places that techniques can be used to ameliorate this | |||
problem. | problem. | |||
1. The beginning, when E-Mail is first sent. | 1. The beginning, when email is first sent (Originating ADMDs). | |||
1. "Neutral" results could be given for IP addresses that may be | 1. "Neutral" results could be given for IP addresses that might | |||
forwarders, instead of "Fail" results. For example: | be forwarders, instead of "fail" results. For example: | |||
"v=spf1 mx -exists:%{ir}.sbl.spamhaus.example.org ?all" | "v=spf1 mx -exists:%{ir}.sbl.spamhaus.example.org ?all" | |||
This would cause a lookup on an anti-spam DNS blacklist | This would cause a lookup on an anti-spam DNS blacklist | |||
(DNSBL) and cause a result of "Fail" only for E-Mail coming | (DNSBL) and cause a result of "fail" only for email coming | |||
from listed sources. All other E-Mail, including E-Mail sent | from listed sources. All other email, including email sent | |||
through forwarders, would receive a "Neutral" result. By | through forwarders, would receive a "neutral" result. By | |||
checking the DNSBL after the known good sources, problems with | checking the DNSBL after the known good sources, problems | |||
incorrect listing on the DNSBL are greatly reduced. | with incorrect listing on the DNSBL are greatly reduced. | |||
2. The "MAIL FROM" identity could have additional information in | 2. The "MAIL FROM" identity could have additional information in | |||
the localpart that cryptographically identifies the mail as | the local-part that cryptographically identifies the mail as | |||
coming from an authorized source. In this case, such an SPF | coming from an authorized source. In this case, such an SPF | |||
record could be used: | record could be used: | |||
"v=spf1 mx exists:%{l}._spf_verify.%{d} -all" | "v=spf1 mx exists:%{l}._spf_verify.%{d} -all" | |||
Then, a specialized DNS server can be set up to serve the | Then, a specialized DNS server can be set up to serve the | |||
_spf_verify subdomain that validates the localpart. Although | _spf_verify subdomain that validates the local-part. | |||
this requires an extra DNS lookup, this happens only when the | Although this requires an extra DNS lookup, this happens only | |||
E-Mail would otherwise be rejected as not coming from a known | when the email would otherwise be rejected as not coming from | |||
good source. | a known good source. | |||
Note that due to the 63-character limit for domain labels, | Note that due to the 63-character limit for domain labels, | |||
this approach only works reliably if the localpart signature | this approach only works reliably if the local-part signature | |||
scheme is guaranteed either to only produce localparts with a | scheme is guaranteed either to only produce local-parts with | |||
maximum of 63 characters or to gracefully handle truncated | a maximum of 63 characters or to gracefully handle truncated | |||
localparts. | local-parts. | |||
3. Similarly, a specialized DNS server could be set up that will | 3. Similarly, a specialized DNS server could be set up that will | |||
rate-limit the E-Mail coming from unexpected IP addresses. | rate-limit the email coming from unexpected IP addresses. | |||
"v=spf1 mx exists:%{ir}._spf_rate.%{d} -all" | "v=spf1 mx exists:%{ir}._spf_rate.%{d} -all" | |||
4. SPF allows the creation of per-user policies for special | 4. SPF allows the creation of per-user policies for special | |||
cases. For example, the following SPF record and appropriate | cases. For example, the following SPF record and appropriate | |||
wildcard DNS records can be used: | wildcard DNS records can be used: | |||
"v=spf1 mx redirect=%{l1r+}._at_.%{o}._spf.%{d}" | "v=spf1 mx redirect=%{l1r+}._at_.%{o}._spf.%{d}" | |||
2. The middle, when E-Mail is forwarded. | 2. The middle, when email is forwarded (Mediating ADMDs). | |||
1. Forwarding services can solve the problem by rewriting the | 1. Forwarding services can solve the problem by rewriting the | |||
"MAIL FROM" to be in their own domain. This means that mail | "MAIL FROM" to be in their own domain. This means mail | |||
bounced from the external mailbox will have to be re-bounced | rejected from the external mailbox will have to be forwarded | |||
by the forwarding service. Various schemes to do this exist | back to the original sender by the forwarding service. | |||
though they vary widely in complexity and resource | Various schemes to do this exist though they vary widely in | |||
requirements on the part of the forwarding service. | complexity and resource requirements on the part of the | |||
forwarding service. | ||||
2. Several popular MTAs can be forced from "alias" semantics to | 2. Several popular MTAs can be forced from "alias" semantics to | |||
"mailing list" semantics by configuring an additional alias | "mailing list" semantics by configuring an additional alias | |||
with "owner-" prepended to the original alias name (e.g., an | with "owner-" prepended to the original alias name (e.g., an | |||
alias of "friends: george@example.com, fred@example.org" would | alias of "friends: george@example.com, fred@example.org" | |||
need another alias of the form "owner-friends: localowner"). | would need another alias of the form "owner-friends: | |||
localowner"). | ||||
3. The end, when E-Mail is received. | 3. The end, when email is received (Receiving ADMDs). | |||
1. If the owner of the external mailbox wishes to trust the | 1. If the owner of the external mailbox wishes to trust the | |||
forwarding service, he can direct the external mailbox's MTA | forwarding service, he can direct the external mailbox's MTA | |||
to skip SPF tests when the client host belongs to the | to skip SPF tests when the client host belongs to the | |||
forwarding service. | forwarding service. | |||
2. Tests against other identities, such as the "HELO" identity, | 2. Tests against other identities, such as the "HELO" identity, | |||
may be used to override a failed test against the "MAIL FROM" | MAY be used to override a failed test against the "MAIL FROM" | |||
identity. | identity. | |||
3. For larger domains, it may not be possible to have a complete | 3. For larger domains, it might not be possible to have a | |||
or accurate list of forwarding services used by the owners of | complete or accurate list of forwarding services used by the | |||
the domain's mailboxes. In such cases, whitelists of | owners of the domain's mailboxes. In such cases, whitelists | |||
generally-recognized forwarding services could be employed. | of generally-recognized forwarding services could be | |||
employed. | ||||
9.4. Mail Services | 9.2.3. Mail Services | |||
Service providers that offer mail services to third-party domains, | MSPs (Mail Service Providers - [RFC5598] Section 2.3) that offer mail | |||
such as sending of bulk mail, may want to adjust their setup in light | services to third-party domains, such as sending of bulk mail, might | |||
of the authorization check described in this document. If the "MAIL | want to adjust their configurations in light of the authorization | |||
FROM" identity used for such E-Mail uses the domain of the service | check described in this document. If the domain part of the "MAIL | |||
provider, then the provider needs only to ensure that its sending | FROM" identity used for such email uses the domain of one of the MSPs | |||
host is authorized by its own SPF record, if any. | domain, then the provider needs only to ensure that its sending host | |||
is authorized by its own SPF record, if any. | ||||
If the "MAIL FROM" identity does not use the mail service provider's | If the "MAIL FROM" identity does not use the MSP's domain, then extra | |||
domain, then extra care must be taken. The SPF record format has | care must be taken. The SPF record format has several options for | |||
several options for the third-party domain to authorize the service | the third-party domain to authorize the service provider's MTAs to | |||
provider's MTAs to send mail on its behalf. For mail service | send mail on its behalf. For MSPs, such as ISPs, that have a wide | |||
providers, such as ISPs, that have a wide variety of customers using | variety of customers using the same MTA, steps should be taken to | |||
the same MTA, steps should be taken to prevent cross-customer forgery | prevent cross-customer forgery (see Section 10.4). | |||
(see Section 10.4). | ||||
9.5. MTA Relays | 9.2.4. MTA Relays | |||
The authorization check generally precludes the use of arbitrary MTA | Relays are described in [RFC5598] Section 2.2.2. The authorization | |||
relays between sender and receiver of an E-Mail message. | check generally precludes the use of arbitrary MTA relays between | |||
sender and receiver of an email message. | ||||
Within an organization, MTA relays can be effectively deployed. | Within an organization, MTA relays can be effectively deployed. | |||
However, for purposes of this document, such relays are effectively | However, for purposes of this document, such relays are effectively | |||
transparent. The SPF authorization check is a check between border | transparent. The SPF authorization check is a check between border | |||
MTAs of different domains. | MTAs of different ADMDs. | |||
For mail senders, this means that published SPF records must | For mail senders, this means that published SPF records must | |||
authorize any MTAs that actually send across the Internet. Usually, | authorize any MTAs that actually send across the Internet. Usually, | |||
these are just the border MTAs as internal MTAs simply forward mail | these are just the border MTAs as internal MTAs simply forward mail | |||
to these MTAs for delivery. | to these MTAs for relaying. | |||
Mail receivers will generally want to perform the authorization check | The receiving ADMD will generally want to perform the authorization | |||
at the border MTAs, specifically including all secondary MXs. This | check at the boundary MTAs, including all secondary MXs. Internal | |||
allows mail that fails to be rejected during the SMTP session rather | MTAs (including MTAs that might serve both as boundary MTAs and | |||
than bounced. Internal MTAs then do not perform the authorization | internal relays from secondary MXs when they are processing the | |||
test. To perform the authorization test other than at the border, | relayed mail stream) then do not perform the authorization test. To | |||
the host that first transferred the message to the organization must | perform the authorization test other than at the boundary, the host | |||
be determined, which can be difficult to extract from the message | that first transferred the message to the receiving ADMD must be | |||
header. Testing other than at the border is not recommended. | determined, which can be difficult to extract from the message header | |||
because (a) header fields can be forged or malformed, and (b) there's | ||||
no standard way to encode that information such that it can be | ||||
reliably extracted. Testing other than at the boundary is likely to | ||||
produce unreliable results. | ||||
9.3. Receivers | ||||
SPF results can be used in combination with other methods to | ||||
determine the final local disposition (either positive or negative of | ||||
a message. It can also be considered dispositive on it's own. | ||||
9.3.1. Policy For SPF Pass | ||||
SPF pass results can be used in combination with "white lists" of | ||||
known "good" domains to bypass some or all additional pre-delivery | ||||
email checks. Exactly which checks and how to determine appropriate | ||||
white list entries has to be based on local conditions and | ||||
requirements. | ||||
9.3.2. Policy For SPF Fail | ||||
SPF fail results can be used to reject messages during the SMTP | ||||
transaction based on either "MAIL FROM" or "HELO" identity results. | ||||
This reduces resource requirements for various content filtering | ||||
methods and conserves bandwidth since rejection can be done before | ||||
the SMTP content is transferred. It also gives immediate feedback to | ||||
the sender who might then be able to resolve the issue. Due to some | ||||
of the issues described above in this section (Section 9), SPF based | ||||
rejection does present some risk of rejecting legitimate email when | ||||
rejecting based on "MAIL FROM" results. | ||||
SPF fail results can also be used as one input into a larger set of | ||||
evaluations which might, based on the overall evaluation result in | ||||
the email being marked negatively in some way (this might be via | ||||
delivery to a special spam folder, modifying subject lines, or other | ||||
locally determined means). Developing the details of such an | ||||
approach have to be based on local conditions and requirements. | ||||
Using SPF results in this way does not have the advantages of | ||||
resource conservation and immediate feedback to the sender associated | ||||
with SMTP rejection, but could produce fewer undesireable rejections | ||||
in a well designed system. | ||||
Either general approach can be used as they both leave a clear | ||||
disposition of emails. They are either delivered in some manner or | ||||
the sender is notified of the failure. Other dispositions such as | ||||
"dropping" or deleting email after acceptance are inappropriate | ||||
because they leave uncertainty and reduce the overall reliabilility | ||||
and utility of email across the Internet. | ||||
9.3.3. Policy For SPF Permerror | ||||
The "permerror" result (see Section 2.5.7) indicates the SPF | ||||
processing module at the receiver determined that the retrieved SPF | ||||
policy record could not be interpreted. This gives no true | ||||
indication about the authorized use of the data found in the | ||||
envelope. | ||||
As with all results, implementers have a choice to make regarding | ||||
what to do with a message that yields this result. SMTP allows only | ||||
a few basic options. | ||||
Rejection of the message is an option, in that it is the one thing a | ||||
receiver can do to draw attention to the difficulty encountered while | ||||
protecting itself from messages that do not have a definite SPF | ||||
result of some kind. However, if the SPF implementation is defective | ||||
and returns spurious "permerror" results, only the sender is actively | ||||
notified of the defect (in the form of rejected mail), and not the | ||||
receiver making use of SPF. | ||||
The less intrusive handling choice is to deliver the message, perhaps | ||||
with some kind of annotation of the difficulty encountered and/or | ||||
logging of a similar nature. However, this will not be desirable to | ||||
operators that wish to implement SPF checking as strictly as | ||||
possible, nor is this sort of passive problem reporting typically | ||||
effective. | ||||
There is of course the option placing this choice in the hands of the | ||||
operator rather than the implementer since this kind of choice is | ||||
often a matter of local policy rather than a condition with a | ||||
universal solution, but this adds one more piece of complexity to an | ||||
already non-trivial environment. | ||||
Both implementers and operators need to be cautious of all choices | ||||
and outcomes when handling SPF results. | ||||
10. Security Considerations | 10. Security Considerations | |||
10.1. Processing Limits | 10.1. Processing Limits | |||
As with most aspects of E-Mail, there are a number of ways that | As with most aspects of email, there are a number of ways that | |||
malicious parties could use the protocol as an avenue for a | malicious parties could use the protocol as an avenue for a | |||
Denial-of-Service (DoS) attack. The processing limits outlined here | Denial-of-Service (DoS) attack. The processing limits outlined in | |||
are designed to prevent attacks such as the following: | Section 4.6.4 are designed to prevent attacks such as the following: | |||
o A malicious party could create an SPF record with many references | o A malicious party could create an SPF record with many references | |||
to a victim's domain and send many E-Mails to different SPF | to a victim's domain and send many emails to different SPF | |||
clients; those SPF clients would then create a DoS attack. In | verifiers; those SPF verifiers would then create a DoS attack. In | |||
effect, the SPF clients are being used to amplify the attacker's | effect, the SPF verifiers are being used to amplify the attacker's | |||
bandwidth by using fewer bytes in the SMTP session than are used | bandwidth by using fewer bytes in the SMTP session than are used | |||
by the DNS queries. Using SPF clients also allows the attacker to | by the DNS queries. Using SPF clients also allows the attacker to | |||
hide the true source of the attack. | hide the true source of the attack. | |||
o Whereas implementations of check_host() are supposed to limit the | o Whereas implementations of check_host() are supposed to limit the | |||
number of DNS lookups, malicious domains could publish records | number of DNS lookups, malicious domains could publish records | |||
that exceed these limits in an attempt to waste computation effort | that exceed these limits in an attempt to waste computation effort | |||
at their targets when they send them mail. Malicious domains | at their targets when they send them mail. Malicious domains | |||
could also design SPF records that cause particular | could also design SPF records that cause particular | |||
implementations to use excessive memory or CPU usage, or to | implementations to use excessive memory or CPU usage, or to | |||
trigger bugs. | trigger bugs. | |||
o Malicious parties could send a large volume of mail purporting to | o Malicious parties could send a large volume of mail purporting to | |||
come from the intended target to a wide variety of legitimate mail | come from the intended target to a wide variety of legitimate mail | |||
hosts. These legitimate machines would then present a DNS load on | hosts. These legitimate machines would then present a DNS load on | |||
the target as they fetched the relevant records. | the target as they fetched the relevant records. | |||
Of these, the case of a third party referenced in the SPF record is | Of these, the case of a third party referenced in the SPF record is | |||
the easiest for a DoS attack to effectively exploit. As a result, | the easiest for a DoS attack to effectively exploit. As a result, | |||
limits that may seem reasonable for an individual mail server can | limits that might seem reasonable for an individual mail server can | |||
still allow an unreasonable amount of bandwidth amplification. | still allow an unreasonable amount of bandwidth amplification. | |||
Therefore, the processing limits need to be quite low. | Therefore, the processing limits need to be quite low. | |||
SPF implementations MUST limit the number of mechanisms and modifiers | 10.2. SPF-Authorized Email May Contain Other False Identities | |||
that do DNS lookups to at most 10 per SPF check, including any | ||||
lookups caused by the use of the "include" mechanism or the | ||||
"redirect" modifier. If this number is exceeded during a check, a | ||||
PermError MUST be returned. The "include", "a", "mx", "ptr", and | ||||
"exists" mechanisms as well as the "redirect" modifier do count | ||||
against this limit. The "all", "ip4", and "ip6" mechanisms do not | ||||
require DNS lookups and therefore do not count against this limit. | ||||
The "exp" modifier does not count against this limit because the DNS | ||||
lookup to fetch the explanation string occurs after the SPF record | ||||
has been evaluated. | ||||
When evaluating the "mx" and "ptr" mechanisms, or the %{p} macro, | ||||
there MUST be a limit of no more than 10 MX or PTR RRs looked up and | ||||
checked. | ||||
SPF implementations SHOULD limit the total amount of data obtained | ||||
from the DNS queries. For example, when DNS over TCP or EDNS0 are | ||||
available, there may need to be an explicit limit to how much data | ||||
will be accepted to prevent excessive bandwidth usage or memory usage | ||||
and DoS attacks. | ||||
MTAs or other processors MAY also impose a limit on the maximum | ||||
amount of elapsed time to evaluate check_host(). Such a limit SHOULD | ||||
allow at least 20 seconds. If such a limit is exceeded, the result | ||||
of authorization SHOULD be "TempError". | ||||
Domains publishing records SHOULD try to keep the number of "include" | ||||
mechanisms and chained "redirect" modifiers to a minimum. Domains | ||||
SHOULD also try to minimize the amount of other DNS information | ||||
needed to evaluate a record. This can be done by choosing directives | ||||
that require less DNS information and placing lower-cost mechanisms | ||||
earlier in the SPF record. | ||||
For example, consider a domain set up as follows: | ||||
example.com. IN MX 10 mx.example.com. | ||||
mx.example.com. IN A 192.0.2.1 | ||||
a.example.com. IN TXT "v=spf1 mx:example.com -all" | ||||
b.example.com. IN TXT "v=spf1 a:mx.example.com -all" | ||||
c.example.com. IN TXT "v=spf1 ip4:192.0.2.1 -all" | ||||
Evaluating check_host() for the domain "a.example.com" requires the | ||||
MX records for "example.com", and then the A records for the listed | ||||
hosts. Evaluating for "b.example.com" requires only the A records. | ||||
Evaluating for "c.example.com" requires none. | ||||
However, there may be administrative considerations: using "a" over | ||||
"ip4" allows hosts to be renumbered easily. Using "mx" over "a" | ||||
allows the set of mail hosts to be changed easily. | ||||
10.2. SPF-Authorized E-Mail May Contain Other False Identities | ||||
The "MAIL FROM" and "HELO" identity authorizations must not be | The "MAIL FROM" and "HELO" identity authorizations must not be | |||
construed to provide more assurance than they do. It is entirely | construed to provide more assurance than they do. It is entirely | |||
possible for a malicious sender to inject a message using his own | possible for a malicious sender to inject a message using his own | |||
domain in the identities used by SPF, to have that domain's SPF | domain in the identities used by SPF, to have that domain's SPF | |||
record authorize the sending host, and yet the message can easily | record authorize the sending host, and yet the message can easily | |||
list other identities in its header. Unless the user or the MUA | list other identities in its header. Unless the user or the MUA | |||
takes care to note that the authorized identity does not match the | takes care to note that the authorized identity does not match the | |||
other more commonly-presented identities (such as the From: header | other more commonly-presented identities (such as the From: header | |||
field), the user may be lulled into a false sense of security. | field), the user might be lulled into a false sense of security. | |||
10.3. Spoofed DNS and IP Data | 10.3. Spoofed DNS and IP Data | |||
There are two aspects of this protocol that malicious parties could | There are two aspects of this protocol that malicious parties could | |||
exploit to undermine the validity of the check_host() function: | exploit to undermine the validity of the check_host() function: | |||
o The evaluation of check_host() relies heavily on DNS. A malicious | o The evaluation of check_host() relies heavily on DNS. A malicious | |||
attacker could attack the DNS infrastructure and cause | attacker could attack the DNS infrastructure and cause | |||
check_host() to see spoofed DNS data, and then return incorrect | check_host() to see spoofed DNS data, and then return incorrect | |||
results. This could include returning "Pass" for an <ip> value | results. This could include returning "pass" for an <ip> value | |||
where the actual domain's record would evaluate to "Fail". See | where the actual domain's record would evaluate to "fail". See | |||
[RFC3833] for a description of DNS weaknesses. | [RFC3833] for a description of DNS weaknesses. | |||
o The client IP address, <ip>, is assumed to be correct. A | o The client IP address, <ip>, is assumed to be correct. In a | |||
malicious attacker could spoof TCP sequence numbers to make mail | modern, correctly configured system the risk of this not being | |||
appear to come from a permitted host for a domain that the | true is nil. | |||
attacker is impersonating. | ||||
10.4. Cross-User Forgery | 10.4. Cross-User Forgery | |||
By definition, SPF policies just map domain names to sets of | By definition, SPF policies just map domain names to sets of | |||
authorized MTAs, not whole E-Mail addresses to sets of authorized | authorized MTAs, not whole email addresses to sets of authorized | |||
users. Although the "l" macro (Section 8) provides a limited way to | users. Although the "l" macro (Section 8) provides a limited way to | |||
define individual sets of authorized MTAs for specific E-Mail | define individual sets of authorized MTAs for specific email | |||
addresses, it is generally impossible to verify, through SPF, the use | addresses, it is generally impossible to verify, through SPF, the use | |||
of specific E-Mail addresses by individual users of the same MTA. | of specific email addresses by individual users of the same MTA. | |||
It is up to mail services and their MTAs to directly prevent | It is up to mail services and their MTAs to directly prevent | |||
cross-user forgery: based on SMTP AUTH ([RFC2554]), users should be | cross-user forgery: based on SMTP AUTH ([RFC4954]), users should be | |||
restricted to using only those E-Mail addresses that are actually | restricted to using only those email addresses that are actually | |||
under their control (see [RFC4409], Section 6.1). Another means to | under their control (see [RFC6409], Section 6.1). Another means to | |||
verify the identity of individual users is message cryptography such | verify the identity of individual users is message cryptography such | |||
as PGP ([RFC2440]) or S/MIME ([RFC3851]). | as PGP ([RFC4880]) or S/MIME ([RFC5751]). | |||
10.5. Untrusted Information Sources | 10.5. Untrusted Information Sources | |||
SPF uses information supplied by third parties, such as the "HELO" | An SPF compliant receiver gathers information from the SMTP commands | |||
domain name, the "MAIL FROM" address, and SPF records. This | it receives and from the published DNS records of the sending domain | |||
information is then passed to the receiver in the Received-SPF: trace | holder, (e.g., "HELO" domain name, the "MAIL FROM" address from the | |||
fields and possibly returned to the client MTA in the form of an SMTP | envelope, and SPF DNS records published by the domain holder). | |||
rejection message. This information must be checked for invalid | ||||
characters and excessively long lines. | ||||
When the authorization check fails, an explanation string may be | 10.5.1. Recorded Results | |||
This information, passed to the receiver in the Received-SPF: or | ||||
Authentication-Results: trace fields, may be returned to the client | ||||
MTA as an SMTP rejection message. If such an SMTP rejection message | ||||
is generated, the information from the trace fields must be checked | ||||
for such problems as invalid characters and excessively long lines. | ||||
10.5.2. External Explanations | ||||
When the authorization check fails, an explanation string could be | ||||
included in the reject response. Both the sender and the rejecting | included in the reject response. Both the sender and the rejecting | |||
receiver need to be aware that the explanation was determined by the | receiver need to be aware that the explanation was determined by the | |||
publisher of the SPF record checked and, in general, not the | publisher of the SPF record checked and, in general, not the | |||
receiver. The explanation may contain malicious URLs, or it may be | receiver. The explanation can contain malicious URLs, or it might be | |||
offensive or misleading. | offensive or misleading. | |||
This is probably less of a concern than it may initially seem since | Explanations returned to sender domains due to "exp" modifiers, | |||
such messages are returned to the sender, and the explanation strings | (Section 6.2), were generated by the sender policy published by the | |||
come from the sender policy published by the domain in the identity | domain holders themselves. As long as messages are only returned | |||
claimed by that very sender. As long as the DSN is not redirected to | with non-delivery notification ([RFC3464]) to domains publishing the | |||
someone other than the actual sender, the only people who see | explanation strings from their own DNS SPF records, the only affected | |||
malicious explanation strings are people whose messages claim to be | parties are the original publishers of the domain's SPF records. | |||
from domains that publish such strings in their SPF records. In | ||||
practice, DSNs can be misdirected, such as when an MTA accepts an | In practice, such non-delivery notifications can be misdirected, such | |||
E-Mail and then later generates a DSN to a forged address, or when an | as when an MTA accepts an email and only later generates the | |||
E-Mail forwarder does not direct the DSN back to the original sender. | notification to a forged address, or when an email forwarder does not | |||
direct the bounce back to the original sender. | ||||
10.5.3. Macro Expansion | ||||
Macros (Section 8) allow senders to inject arbitrary text (any non- | ||||
null [US-ASCII] character) into receiver DNS queries. It is necesary | ||||
to be prepared for hostile or unexpected content. | ||||
10.6. Privacy Exposure | 10.6. Privacy Exposure | |||
Checking SPF records causes DNS queries to be sent to the domain | Checking SPF records causes DNS queries to be sent to the domain | |||
owner. These DNS queries, especially if they are caused by the | owner. These DNS queries, especially if they are caused by the | |||
"exists" mechanism, can contain information about who is sending | "exists" mechanism, can contain information about who is sending | |||
E-Mail and likely to which MTA the E-Mail is being sent. This can | email and likely to which MTA the email is being sent. This can | |||
introduce some privacy concerns, which may be more or less of an | introduce some privacy concerns, which are more or less of an issue | |||
issue depending on local laws and the relationship between the domain | depending on local laws and the relationship between the domain owner | |||
owner and the person sending the E-Mail. | and the person sending the email. | |||
11. Contributors and Acknowledgements | 11. Contributors and Acknowledgements | |||
This document is largely based on the work of Meng Weng Wong and Mark | This document is largely based on the work of Meng Weng Wong, Mark | |||
Lentczner. Although, as this section acknowledges, many people have | Lentczner, and Wayne Schlitt. Although, as this section | |||
contributed to this document, a very large portion of the writing and | acknowledges, many people have contributed to this document, a very | |||
editing are due to Meng and Mark. | large portion of the writing and editing are due to Meng, Mark, and | |||
Wayne. | ||||
This design owes a debt of parentage to [RMX] by Hadmut Danisch and | This design owes a debt of parentage to [RMX] by Hadmut Danisch and | |||
to [DMP] by Gordon Fecyk. The idea of using a DNS record to check | to [DMP] by Gordon Fecyk. The idea of using a DNS record to check | |||
the legitimacy of an E-Mail address traces its ancestry further back | the legitimacy of an email address traces its ancestry further back | |||
through messages on the namedroppers mailing list by Paul Vixie | through messages on the namedroppers mailing list by Paul Vixie | |||
[Vixie] (based on suggestion by Jim Miller) and by David Green | [Vixie] (based on suggestion by Jim Miller) and by David Green | |||
[Green]. | [Green]. | |||
Philip Gladstone contributed the concept of macros to the | Philip Gladstone contributed the concept of macros to the | |||
specification, multiplying the expressiveness of the language and | specification, multiplying the expressiveness of the language and | |||
making per-user and per-IP lookups possible. | making per-user and per-IP lookups possible. | |||
The authors would also like to thank the literally hundreds of | The authors of both this document and [RFC4408] would also like to | |||
individuals who have participated in the development of this design. | thank the literally hundreds of individuals who have participated in | |||
They are far too numerous to name, but they include the following: | the development of this design. They are far too numerous to name, | |||
but they include the following: | ||||
The participants in the SPFbis working group. | ||||
The folks on the spf-discuss mailing list. | The folks on the spf-discuss mailing list. | |||
The folks on the SPAM-L mailing list. | The folks on the SPAM-L mailing list. | |||
The folks on the IRTF ASRG mailing list. | The folks on the IRTF ASRG mailing list. | |||
The folks on the IETF MARID mailing list. | The folks on the IETF MARID mailing list. | |||
The folks on #perl. | The folks on #perl. | |||
12. IANA Considerations | 12. IANA Considerations | |||
12.1. The SPF DNS Record Type | 12.1. The SPF DNS Record Type | |||
The IANA has assigned a new Resource Record Type and Qtype from the | Per [RFC4408], the IANA assigned the Resource Record Type and Qtype | |||
DNS Parameters Registry for the SPF RR type with code 99. | from the DNS Parameters Registry for the SPF RR type with code 99. | |||
The format of this type is identical to the TXT RR [RFC1035]. The | ||||
character content of the record is encoded as [US-ASCII]. Use of | ||||
this record type is obsolete for SPF Version 1. | ||||
IANA is requested to add an annotation to the SPF RRTYPE saying | ||||
"(OBSOLETE - use TXT)" in the DNS Parameters registry. | ||||
[NOTE TO RFC EDITOR: (to be changed to " ... has added ..." upon | ||||
publication)] | ||||
12.2. The Received-SPF Mail Header Field | 12.2. The Received-SPF Mail Header Field | |||
Per [RFC3864], the "Received-SPF:" header field is added to the IANA | Per [RFC3864], the "Received-SPF:" header field is added to the IANA | |||
Permanent Message Header Field Registry. The following is the | Permanent Message Header Field Registry. The following is the | |||
registration template: | registration template: | |||
Header field name: Received-SPF | Header field name: Received-SPF | |||
Applicable protocol: mail ([RFC2822]) | Applicable protocol: mail ([RFC5322]) | |||
Status: Experimental | Status: Standards Track | |||
Author/Change controller: IETF | Author/Change controller: IETF | |||
Specification document(s): RFC 4408 | Specification document(s): RFC XXXX | |||
Related information: | [NOTE TO RFC EDITOR: (this document)] | |||
Requesting SPF Council review of any proposed changes and | ||||
additions to this field are recommended. For information about | 12.3. SPF Modifier Registration | |||
the SPF Council see http://www.openspf.org/Council | ||||
[RFC6652] created a new SPF Modifier Registration. IANA is requested | ||||
to change the reference for the exp and redirect modifiers from | ||||
[RFC4408] to this document. Their status should not be changed. | ||||
13. References | 13. References | |||
13.1. Normative References | 13.1. Normative References | |||
[RFC1035] Mockapetris, P., "Domain names - implementation and | [RFC1035] Mockapetris, P., "Domain names - implementation and | |||
specification", STD 13, RFC 1035, November 1987. | specification", STD 13, RFC 1035, November 1987. | |||
[RFC1123] Braden, R., "Requirements for Internet Hosts - Application | [RFC1123] Braden, R., "Requirements for Internet Hosts - Application | |||
and Support", STD 3, RFC 1123, October 1989. | and Support", STD 3, RFC 1123, October 1989. | |||
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate | |||
Requirement Levels", BCP 14, RFC 2119, March 1997. | Requirement Levels", BCP 14, RFC 2119, March 1997. | |||
[RFC2821] Klensin, J., "Simple Mail Transfer Protocol", RFC 2821, | [RFC3463] Vaudreuil, G., "Enhanced Mail System Status Codes", | |||
April 2001. | RFC 3463, January 2003. | |||
[RFC2822] Resnick, P., "Internet Message Format", RFC 2822, April | ||||
2001. | ||||
[RFC3464] Moore, K. and G. Vaudreuil, "An Extensible Message Format | ||||
for Delivery Status Notifications", RFC 3464, January | ||||
2003. | ||||
[RFC3513] Hinden, R. and S. Deering, "Internet Protocol Version 6 | ||||
(IPv6) Addressing Architecture", RFC 3513, April 2003. | ||||
[RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration | [RFC3864] Klyne, G., Nottingham, M., and J. Mogul, "Registration | |||
Procedures for Message Header Fields", BCP 90, RFC 3864, | Procedures for Message Header Fields", BCP 90, RFC 3864, | |||
September 2004. | September 2004. | |||
[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform | [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform | |||
Resource Identifier (URI): Generic Syntax", STD 66, RFC | Resource Identifier (URI): Generic Syntax", STD 66, | |||
3986, January 2005. | RFC 3986, January 2005. | |||
[RFC4234] Crocker, D. and P. Overell, "Augmented BNF for Syntax | [RFC4291] Hinden, R. and S. Deering, "IP Version 6 Addressing | |||
Specifications: ABNF", RFC 4234, October 2005. | Architecture", RFC 4291, February 2006. | |||
[US-ASCII] American National Standards Institute (formerly United | [RFC5234] Crocker, D. and P. Overell, "Augmented BNF for Syntax | |||
Specifications: ABNF", STD 68, RFC 5234, January 2008. | ||||
[RFC5321] Klensin, J., "Simple Mail Transfer Protocol", RFC 5321, | ||||
October 2008. | ||||
[RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322, | ||||
October 2008. | ||||
[RFC5451] Kucherawy, M., "Message Header Field for Indicating | ||||
Message Authentication Status", RFC 5451, April 2009. | ||||
[RFC5598] Crocker, D., "Internet Mail Architecture", RFC 5598, | ||||
July 2009. | ||||
[RFC5890] Klensin, J., "Internationalized Domain Names for | ||||
Applications (IDNA): Definitions and Document Framework", | ||||
RFC 5890, August 2010. | ||||
[US-ASCII] | ||||
American National Standards Institute (formerly United | ||||
States of America Standards Institute), "USA Code for | States of America Standards Institute), "USA Code for | |||
Information Interchange, X3.4", 1968. | Information Interchange, X3.4", 1968. | |||
ANSI X3.4-1968 has been replaced by newer versions with slight | ANSI X3.4-1968 has been replaced by newer versions with | |||
modifications, but the 1968 version remains definitive for | slight modifications, but the 1968 version remains | |||
the Internet. | definitive for the Internet. | |||
13.2 Informative References | 13.2. Informative References | |||
[DMP] Fecyk, G., "Designated Mailers Protocol". | ||||
Work In Progress | ||||
[Green] Green, D., "Domain-Authorized SMTP Mail", 2002. | ||||
[RFC1034] Mockapetris, P., "Domain names - concepts and facilities", | [RFC1034] Mockapetris, P., "Domain names - concepts and facilities", | |||
STD 13, RFC 1034, November 1987. | STD 13, RFC 1034, November 1987. | |||
[RFC1983] Malkin, G., "Internet Users' Glossary", RFC 1983, August | [RFC1983] Malkin, G., "Internet Users' Glossary", RFC 1983, | |||
1996. | August 1996. | |||
[RFC2440] Callas, J., Donnerhacke, L., Finney, H., and R. Thayer, | [RFC2308] Andrews, M., "Negative Caching of DNS Queries (DNS | |||
"OpenPGP Message Format", RFC 2440, November 1998. | NCACHE)", RFC 2308, March 1998. | |||
[RFC2554] Myers, J., "SMTP Service Extension for Authentication", | [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for | |||
RFC 2554, March 1999. | specifying the location of services (DNS SRV)", RFC 2782, | |||
February 2000. | ||||
[RFC3464] Moore, K. and G. Vaudreuil, "An Extensible Message Format | ||||
for Delivery Status Notifications", RFC 3464, | ||||
January 2003. | ||||
[RFC3696] Klensin, J., "Application Techniques for Checking and | [RFC3696] Klensin, J., "Application Techniques for Checking and | |||
Transformation of Names", RFC 3696, February 2004. | Transformation of Names", RFC 3696, February 2004. | |||
[RFC3833] Atkins, D. and R. Austein, "Threat Analysis of the Domain | [RFC3833] Atkins, D. and R. Austein, "Threat Analysis of the Domain | |||
Name System (DNS)", RFC 3833, August 2004. | Name System (DNS)", RFC 3833, August 2004. | |||
[RFC3851] Ramsdell, B., "Secure/Multipurpose Internet Mail | [RFC3834] Moore, K., "Recommendations for Automatic Responses to | |||
Extensions (S/MIME) Version 3.1 Message Specification", | Electronic Mail", RFC 3834, August 2004. | |||
RFC 3851, July 2004. | ||||
[RFC4409] Gellens, R. and J. Klensin, "Message Submission for Mail", | [RFC4408] Wong, M. and W. Schlitt, "Sender Policy Framework (SPF) | |||
RFC 4409, April 2006. | for Authorizing Use of Domains in E-Mail, Version 1", | |||
RFC 4408, April 2006. | ||||
[RMX] Danish, H., "The RMX DNS RR Type for light weight sender | [RFC4632] Fuller, V. and T. Li, "Classless Inter-domain Routing | |||
authentication", Work In Progress | (CIDR): The Internet Address Assignment and Aggregation | |||
Plan", BCP 122, RFC 4632, August 2006. | ||||
[DMP] Fecyk, G., "Designated Mailers Protocol", Work In Progress | [RFC4880] Callas, J., Donnerhacke, L., Finney, H., Shaw, D., and R. | |||
Thayer, "OpenPGP Message Format", RFC 4880, November 2007. | ||||
[Vixie] Vixie, P., "Repudiating MAIL FROM", 2002. | [RFC4954] Siemborski, R. and A. Melnikov, "SMTP Service Extension | |||
for Authentication", RFC 4954, July 2007. | ||||
[Green] Green, D., "Domain-Authorized SMTP Mail", 2002. | [RFC5751] Ramsdell, B. and S. Turner, "Secure/Multipurpose Internet | |||
Mail Extensions (S/MIME) Version 3.2 Message | ||||
Specification", RFC 5751, January 2010. | ||||
[RFC5782] Levine, J., "DNS Blacklists and Whitelists", RFC 5782, | ||||
February 2010. | ||||
[RFC6409] Gellens, R. and J. Klensin, "Message Submission for Mail", | ||||
STD 72, RFC 6409, November 2011. | ||||
[RFC6647] Kucherawy, M. and D. Crocker, "Email Greylisting: An | ||||
Applicability Statement for SMTP", RFC 6647, June 2012. | ||||
[RFC6652] Kitterman, S., "Sender Policy Framework (SPF) | ||||
Authentication Failure Reporting Using the Abuse Reporting | ||||
Format", RFC 6652, June 2012. | ||||
[RFC6686] Kucherawy, M., "Resolution of the Sender Policy Framework | ||||
(SPF) and Sender ID Experiments", RFC 6686, July 2012. | ||||
[RMX] Danisch, H., "The RMX DNS RR Type for light weight sender | ||||
authentication". | ||||
Work In Progress | ||||
[Vixie] Vixie, P., "Repudiating MAIL FROM", 2002. | ||||
Appendix A. Collected ABNF | Appendix A. Collected ABNF | |||
This section is normative and any discrepancies with the ABNF | This section is normative and any discrepancies with the ABNF | |||
fragments in the preceding text are to be resolved in favor of this | fragments in the preceding text are to be resolved in favor of this | |||
grammar. | grammar. | |||
See [RFC4234] for ABNF notation. Please note that as per this ABNF | See [RFC5234] for ABNF notation. Please note that as per this ABNF | |||
definition, literal text strings (those in quotes) are case- | definition, literal text strings (those in quotes) are case- | |||
insensitive. Hence, "mx" matches "mx", "MX", "mX", and "Mx". | insensitive. Hence, "mx" matches "mx", "MX", "mX", and "Mx". | |||
record = version terms *SP | record = version terms *SP | |||
version = "v=spf1" | version = "v=spf1" | |||
terms = *( 1*SP ( directive / modifier ) ) | terms = *( 1*SP ( directive / modifier ) ) | |||
directive = [ qualifier ] mechanism | directive = [ qualifier ] mechanism | |||
qualifier = "+" / "-" / "?" / "~" | qualifier = "+" / "-" / "?" / "~" | |||
skipping to change at page 42, line 38 | skipping to change at page 57, line 38 | |||
MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ] | MX = "mx" [ ":" domain-spec ] [ dual-cidr-length ] | |||
PTR = "ptr" [ ":" domain-spec ] | PTR = "ptr" [ ":" domain-spec ] | |||
IP4 = "ip4" ":" ip4-network [ ip4-cidr-length ] | IP4 = "ip4" ":" ip4-network [ ip4-cidr-length ] | |||
IP6 = "ip6" ":" ip6-network [ ip6-cidr-length ] | IP6 = "ip6" ":" ip6-network [ ip6-cidr-length ] | |||
exists = "exists" ":" domain-spec | exists = "exists" ":" domain-spec | |||
modifier = redirect / explanation / unknown-modifier | modifier = redirect / explanation / unknown-modifier | |||
redirect = "redirect" "=" domain-spec | redirect = "redirect" "=" domain-spec | |||
explanation = "exp" "=" domain-spec | explanation = "exp" "=" domain-spec | |||
unknown-modifier = name "=" macro-string | unknown-modifier = name "=" macro-string | |||
; where name is not any known modifier | ||||
ip4-cidr-length = "/" 1*DIGIT | ip4-cidr-length = "/" 1*DIGIT | |||
ip6-cidr-length = "/" 1*DIGIT | ip6-cidr-length = "/" 1*DIGIT | |||
dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] | dual-cidr-length = [ ip4-cidr-length ] [ "/" ip6-cidr-length ] | |||
ip4-network = qnum "." qnum "." qnum "." qnum | ip4-network = qnum "." qnum "." qnum "." qnum | |||
qnum = DIGIT ; 0-9 | qnum = DIGIT ; 0-9 | |||
/ %x31-39 DIGIT ; 10-99 | / %x31-39 DIGIT ; 10-99 | |||
/ "1" 2DIGIT ; 100-199 | / "1" 2DIGIT ; 100-199 | |||
/ "2" %x30-34 DIGIT ; 200-249 | / "2" %x30-34 DIGIT ; 200-249 | |||
/ "25" %x30-35 ; 250-255 | / "25" %x30-35 ; 250-255 | |||
; conventional dotted quad notation. e.g., 192.0.2.0 | ; conventional dotted quad notation. e.g., 192.0.2.0 | |||
ip6-network = <as per [RFC 3513], section 2.2> | ip6-network = <as per [RFC 4291], section 2.2> | |||
; e.g., 2001:DB8::CD30 | ; e.g., 2001:DB8::CD30 | |||
domain-spec = macro-string domain-end | domain-spec = macro-string domain-end | |||
domain-end = ( "." toplabel [ "." ] ) / macro-expand | domain-end = ( "." toplabel [ "." ] ) / macro-expand | |||
toplabel = ( *alphanum ALPHA *alphanum ) / | toplabel = ( *alphanum ALPHA *alphanum ) / | |||
( 1*alphanum "-" *( alphanum / "-" ) alphanum ) | ( 1*alphanum "-" *( alphanum / "-" ) alphanum ) | |||
; LDH rule plus additional TLD restrictions | ; LDH rule plus additional TLD restrictions | |||
; (see [RFC3696], Section 2) | ; (see [RFC3696], Section 2 for background) | |||
alphanum = ALPHA / DIGIT | alphanum = ALPHA / DIGIT | |||
explain-string = *( macro-string / SP ) | explain-string = *( macro-string / SP ) | |||
macro-string = *( macro-expand / macro-literal ) | macro-string = *( macro-expand / macro-literal ) | |||
macro-expand = ( "%{" macro-letter transformers *delimiter "}" ) | macro-expand = ( "%{" macro-letter transformers *delimiter "}" ) | |||
/ "%%" / "%_" / "%-" | / "%%" / "%_" / "%-" | |||
macro-literal = %x21-24 / %x26-7E | macro-literal = %x21-24 / %x26-7E | |||
; visible characters except "%" | ; visible characters except "%" | |||
macro-letter = "s" / "l" / "o" / "d" / "i" / "p" / "h" / | macro-letter = "s" / "l" / "o" / "d" / "i" / "p" / "h" / | |||
"c" / "r" / "t" | "c" / "r" / "t" / "v" | |||
transformers = *DIGIT [ "r" ] | transformers = *DIGIT [ "r" ] | |||
delimiter = "." / "-" / "+" / "," / "/" / "_" / "=" | delimiter = "." / "-" / "+" / "," / "/" / "_" / "=" | |||
name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." ) | name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." ) | |||
header-field = "Received-SPF:" [CFWS] result FWS [comment FWS] | header-field = "Received-SPF:" [CFWS] result FWS [comment FWS] | |||
[ key-value-list ] CRLF | [ key-value-list ] CRLF | |||
result = "Pass" / "Fail" / "SoftFail" / "Neutral" / | result = "pass" / "fail" / "softfail" / "neutral" / | |||
"None" / "TempError" / "PermError" | "none" / "temperror" / "permerror" | |||
key-value-list = key-value-pair *( ";" [CFWS] key-value-pair ) | key-value-list = key-value-pair *( ";" [CFWS] key-value-pair ) | |||
[";"] | [";"] | |||
key-value-pair = key [CFWS] "=" ( dot-atom / quoted-string ) | key-value-pair = key [CFWS] "=" ( dot-atom / quoted-string ) | |||
key = "client-ip" / "envelope-from" / "helo" / | key = "client-ip" / "envelope-from" / "helo" / | |||
"problem" / "receiver" / "identity" / | "problem" / "receiver" / identity / | |||
mechanism / "x-" name / name | mechanism / name | |||
identity = "mailfrom" ; for the "MAIL FROM" identity | identity = "mailfrom" ; for the "MAIL FROM" identity | |||
/ "helo" ; for the "HELO" identity | / "helo" ; for the "HELO" identity | |||
/ name ; other identities | / name ; other identities | |||
dot-atom = <unquoted word as per [RFC2822]> | ALPHA = <A-Z / a-z as per [RFC5234]> | |||
quoted-string = <quoted string as per [RFC2822]> | DIGIT = <0-9 as per [RFC5234]> | |||
comment = <comment string as per [RFC2822]> | SP = <space character as per [RFC5234]> | |||
CFWS = <comment or folding white space as per [RFC2822]> | domain = <fully qualified domain as per [RFC5321]> | |||
FWS = <folding white space as per [RFC2822]> | dot-atom = <unquoted word as per [RFC5322]> | |||
CRLF = <standard end-of-line token as per [RFC2822]> | quoted-string = <quoted string as per [RFC5322]> | |||
comment = <comment string as per [RFC5322]> | ||||
CFWS = <comment or folding white space as per [RFC5322]> | ||||
FWS = <folding white space as per [RFC5322]> | ||||
CRLF = <standard end-of-line token as per [RFC5322]> | ||||
authserv-id = <authserv-id per [RFC5451]> | ||||
reasonspec = <reason per [RFC5451]> | ||||
Appendix B. Extended Examples | Appendix B. Extended Examples | |||
These examples are based on the following DNS setup: | These examples are based on the following DNS setup: | |||
; A domain with two mail servers, two hosts | ; A domain with two mail servers, two hosts | |||
; and two servers at the domain name | ; and two servers at the domain name | |||
$ORIGIN example.com. | $ORIGIN example.com. | |||
@ MX 10 mail-a | @ MX 10 mail-a | |||
MX 20 mail-b | MX 20 mail-b | |||
skipping to change at page 44, line 46 | skipping to change at page 60, line 46 | |||
; A rogue reverse IP domain that claims to be | ; A rogue reverse IP domain that claims to be | |||
; something it's not | ; something it's not | |||
$ORIGIN 0.0.10.in-addr.arpa. | $ORIGIN 0.0.10.in-addr.arpa. | |||
4 PTR bob.example.com. | 4 PTR bob.example.com. | |||
B.1. Simple Examples | B.1. Simple Examples | |||
These examples show various possible published records for | These examples show various possible published records for | |||
example.com and which values if <ip> would cause check_host() to | example.com and which values if <ip> would cause check_host() to | |||
return "Pass". Note that <domain> is "example.com". | return "pass". Note that <domain> is "example.com". | |||
v=spf1 +all | v=spf1 +all | |||
-- any <ip> passes | -- any <ip> passes | |||
v=spf1 a -all | v=spf1 a -all | |||
-- hosts 192.0.2.10 and 192.0.2.11 pass | -- hosts 192.0.2.10 and 192.0.2.11 pass | |||
v=spf1 a:example.org -all | v=spf1 a:example.org -all | |||
-- no sending hosts pass since example.org has no A records | -- no sending hosts pass since example.org has no A records | |||
v=spf1 mx -all | v=spf1 mx -all | |||
-- sending hosts 192.0.2.129 and 192.0.2.130 pass | -- sending hosts 192.0.2.129 and 192.0.2.130 pass | |||
v=spf1 mx:example.org -all | v=spf1 mx:example.org -all | |||
-- sending host 192.0.2.140 passes | -- sending host 192.0.2.140 passes | |||
v=spf1 mx mx:example.org -all | v=spf1 mx mx:example.org -all | |||
skipping to change at page 46, line 10 | skipping to change at page 62, line 12 | |||
These records allow a set of domains that all use the same mail | These records allow a set of domains that all use the same mail | |||
system to make use of that mail system's record. In this way, only | system to make use of that mail system's record. In this way, only | |||
the mail system's record needs to be updated when the mail setup | the mail system's record needs to be updated when the mail setup | |||
changes. These domains' records never have to change. | changes. These domains' records never have to change. | |||
B.3. DNSBL Style Example | B.3. DNSBL Style Example | |||
Imagine that, in addition to the domain records listed above, there | Imagine that, in addition to the domain records listed above, there | |||
are these: | are these: | |||
$ORIGIN _spf.example.com. mary.mobile-users A | $ORIGIN _spf.example.com. | |||
127.0.0.2 fred.mobile-users A 127.0.0.2 | mary.mobile-users A 127.0.0.2 | |||
fred.mobile-users A 127.0.0.2 | ||||
15.15.168.192.joel.remote-users A 127.0.0.2 | 15.15.168.192.joel.remote-users A 127.0.0.2 | |||
16.15.168.192.joel.remote-users A 127.0.0.2 | 16.15.168.192.joel.remote-users A 127.0.0.2 | |||
The following records describe users at example.com who mail from | The following records describe users at example.com who mail from | |||
arbitrary servers, or who mail from personal servers. | arbitrary servers, or who mail from personal servers. | |||
example.com: | example.com: | |||
v=spf1 mx | v=spf1 mx | |||
include:mobile-users._spf.%{d} | include:mobile-users._spf.%{d} | |||
skipping to change at page 47, line 5 | skipping to change at page 63, line 5 | |||
"-include:ip4._spf.%{d} " | "-include:ip4._spf.%{d} " | |||
"-include:ptr._spf.%{d} " | "-include:ptr._spf.%{d} " | |||
"+all" ) | "+all" ) | |||
ip4._spf.example.com. SPF "v=spf1 -ip4:192.0.2.0/24 +all" | ip4._spf.example.com. SPF "v=spf1 -ip4:192.0.2.0/24 +all" | |||
ptr._spf.example.com. SPF "v=spf1 -ptr +all" | ptr._spf.example.com. SPF "v=spf1 -ptr +all" | |||
This example shows how the "-include" mechanism can be useful, how an | This example shows how the "-include" mechanism can be useful, how an | |||
SPF record that ends in "+all" can be very restrictive, and the use | SPF record that ends in "+all" can be very restrictive, and the use | |||
of De Morgan's Law. | of De Morgan's Law. | |||
Authors' Addresses | Appendix C. Change History | |||
Meng Weng Wong | Changes since RFC 4408 (to be removed prior to publication) | |||
Singapore | ||||
EMail: mengwong+spf@pobox.com | Moved to standards track | |||
Wayne Schlitt | Authors updated | |||
4615 Meredeth #9 | ||||
Lincoln Nebraska, NE 68506 | ||||
United States of America | ||||
EMail: wayne@schlitt.net | IESG Note regarding experimental use replaced with discussion of | |||
URI: http://www.schlitt.net/spf/ | results | |||
Full Copyright Statement | Process errata: | |||
Copyright (C) The Internet Society (2006). | Add %v macro to ABNF grammar | |||
This document is subject to the rights, licenses and restrictions | Replace "uric" by "unreserved" | |||
contained in BCP 78, and except as set forth therein, the authors | ||||
retain all their rights. | ||||
This document and the information contained herein are provided on an | Recommend an SMTP reply code for optional permerror rejections | |||
"AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS | ||||
OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET | ||||
ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, | ||||
INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE | ||||
INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED | ||||
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. | ||||
Intellectual Property | Correct syntax in Received-SPF examples | |||
The IETF takes no position regarding the validity or scope of any | Fix unknown-modifier clause is too greedy in ABNF | |||
Intellectual Property Rights or other rights that might be claimed to | ||||
pertain to the implementation or use of the technology described in | ||||
this document or the extent to which any license under such rights | ||||
might or might not be available; nor does it represent that it has | ||||
made any independent effort to identify any such rights. Information | ||||
on the procedures with respect to rights in RFC documents can be | ||||
found in BCP 78 and BCP 79. | ||||
Copies of IPR disclosures made to the IETF Secretariat and any | Correct use of empty domain-spec on exp modifier | |||
assurances of licenses to be made available, or the result of an | ||||
attempt made to obtain a general license or permission for the use of | ||||
such proprietary rights by implementers or users of this | ||||
specification can be obtained from the IETF on-line IPR repository at | ||||
http://www.ietf.org/ipr. | ||||
The IETF invites any interested party to bring to its attention any | Fix minor typo errata | |||
copyrights, patents or patent applications, or other proprietary | ||||
rights that may cover technology that may be required to implement | ||||
this standard. Please address the information to the IETF at | ||||
ietf-ipr@ietf.org. | ||||
Acknowledgement | Convert to spfbis working group draft, | |||
draft-ietf-spfbis-4408bis-00 | ||||
Funding for the RFC Editor function is provided by the IETF | Addressed Ticket #1, RFC 4408 Section 2.5.6 - Temporary errors by | |||
Administrative Support Activity (IASA). | giving the option to turn repeated SERVFAIL into permerror and | |||
adding RFC 2308 reference. | ||||
Clarified text about IPv4 mapped addresses to resolve test suite | ||||
ambiguity | ||||
Clarified ambiguity about result when more than 10 "mx" or "ptr" | ||||
records are returned for lookup to specify permerror. This | ||||
resolves one of the test suite ambiguities | ||||
Made all references to result codes lower case per issue #7 | ||||
Adjusted section 2.2 Requirement to check mail from per issue #15 | ||||
Added missing "v" element in macro-letter in the collected ABNF | ||||
per issue #16 - section 8.1 was already fixed in the pre-WG draft | ||||
Marked ptr and "p" macro deprecated/SHOULD NOT use per issue #27 | ||||
Expunged lower case may from the draft per issue #8 | ||||
Expunged "x-" name as an obsolete concept | ||||
Updated obslete references: RFC2821 to RFC5321, RFC2822 to | ||||
RFC5322, and RFC4234 to RFC5234 | ||||
Refer to RFC6647 to describe greylisting instead of trying to | ||||
describe it directly. | ||||
Updated informative references to the current versions. | ||||
Added definition for deprecated since there are questions. | ||||
Start to rework section 9 with some RFC5598 terms. | ||||
Added mention of RFC 6552 feedback reports in section 9. | ||||
Added draft-ietf-spfbis-experiment as an informational reference. | ||||
Drop Type SPF. | ||||
Try and clarify informational nature of RFC3696 | ||||
Fix ABNF nits and add missing definitions per Bill's ABNF checker. | ||||
Make DNS lookup time limit SHOULD instead of MAY. | ||||
Reorganize and clarify processing limits. Move hard limits to new | ||||
section 4.6.4, Evaluation Limits. Move advice to non-normative | ||||
section 9. | ||||
Removed paragraph in section 10.1 about limiting total data | ||||
volumes as it is unused (and removable per the charter) and serves | ||||
no purpose (it isn't something that actually can be implemented in | ||||
any reasonable way). | ||||
Added text and figures from Alessandro Vesely in section 9.1 to | ||||
better explain DNS resource limits. | ||||
Multiple editorial fixes from Murray Kucherawy's review. | ||||
Also based on Murray's review, reworked SMTP identity definitions | ||||
and made RFC 5598 a normative reference instead of informative. | ||||
This is a downref that will have to be mentioned in the last call. | ||||
Added RFC 3834 as an informative reference about backscatter. | ||||
Added IDN requirements and normative reference to RFC 5890 to deal | ||||
with the question "like DKIM did it.: | ||||
Added informative reference to RFC 4632 for CIDR and use CIDR | ||||
prefix length instead of CIDR-length to match its terminology. | ||||
Added RFC 5782 informative reference on DNSxLs to support | ||||
improving the exists description. | ||||
Added text on creating a Authentication-Results header field that | ||||
matches the Received-SPF header field information and added a | ||||
normative reference to RFC 5451. | ||||
Added informative reference to RFC 2782 due to SRV mention. | ||||
Added informative reference to RFC 3464 due to DSN mention. | ||||
Added informative reference to RFC 5617 for it's DNS wildcard use. | ||||
Added informative reference to RFC 5782 to enhance the explanation | ||||
of how the exists mechanism works. Clarified the intended match/ | ||||
no-match method. | ||||
Added new sections on Receiver policy for SPF pass, fail, and | ||||
permerror. | ||||
Added new section 9 discussion on treatment of bounces and the | ||||
significance of HELO records. | ||||
Added request to IANA to update the SPF modifier registry. | ||||
Author's Address | ||||
Scott Kitterman | ||||
Kitterman Technical Services | ||||
3611 Scheel Dr | ||||
Ellicott City, MD 21042 | ||||
United States of America | ||||
Email: scott@kitterman.com | ||||
End of changes. 291 change blocks. | ||||
838 lines changed or deleted | 1231 lines changed or added | |||
This html diff was produced by rfcdiff 1.33. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |