Skip to content

Split View: DMARC가 11년 만에 표준이 되다 — RFC 9989의 트리 워크, pct 폐지, 그리고 p=reject 경고

|

DMARC가 11년 만에 표준이 되다 — RFC 9989의 트리 워크, pct 폐지, 그리고 p=reject 경고

들어가며 — 모두가 쓰는데 표준은 아니었던 프로토콜

이상한 사실 하나에서 시작합니다. Gmail과 Yahoo가 2024년부터 대량 발신자에게 DMARC를 사실상 강제해 왔고, 은행과 정부 기관이 도입 현황을 감사받고, 이메일 보안 스타트업 생태계 하나가 그 위에 세워져 있는데 — 정작 DMARC를 정의한 RFC 7489IETF 표준이 아니었습니다. 2015년 3월에 나온 이 문서는 IETF 워킹그룹 합의를 거치지 않은 Independent Submission이고, 분류도 Informational입니다. 문서 지위만 보면 "누군가 이렇게 하고 있다더라"를 기록한 문서 위에서 전 세계 이메일 인증이 11년을 굴러온 셈입니다.

2026년 5월, 이 상태가 끝났습니다. IETF DMARC 워킹그룹의 소위 DMARCbis 작업이 RFC 9989로 발행되면서 DMARC는 Standards Track 문서가 됐고, RFC 7489와 (PSD DMARC를 다뤘던 실험 문서) RFC 9091을 폐기(obsolete)했습니다. datatracker 기준으로 드래프트 리비전 41번, 본문 83쪽짜리 결과물입니다.

"표준 됐다니 축하할 일이네" 하고 넘기기에는, 이번 개정이 실제로 프로토콜의 동작을 바꿉니다. 조직 도메인을 찾는 알고리즘이 통째로 교체됐고, 태그 몇 개가 사라지고 생겼으며, 무엇보다 그동안 커뮤니티의 암묵지였던 운영 원칙들이 MUST와 SHOULD NOT의 언어로 처음 못 박혔습니다. 하나씩 보겠습니다. (SMTP와 DNS 자체가 낯설다면 DNS와 이메일 프로토콜 기초 정리를 먼저 봐도 좋습니다.)

무엇이 나왔나 — 세 문서로 쪼개진 DMARC

RFC 7489 하나였던 스펙이 세 문서로 분리됐습니다. 전부 2026년 5월에 함께 발행됐고, 전부 Standards Track입니다.

  • RFC 9989 — DMARC 본체. 정책 레코드 문법, 정렬(alignment) 평가, 정책 발견. RFC 7489와 RFC 9091을 폐기합니다. 편집자는 Valimail의 T. Herr와 Standcore의 J. Levine.
  • RFC 9990 — 집계 리포트(aggregate reporting). XML 리포트 포맷과 전송 방식이 이쪽으로 분리됐습니다.
  • RFC 9991 — 실패 리포트(failure reporting). RFC 6591을 갱신합니다.

리포트 스펙이 분리된 것은 단순한 문서 정리가 아니라 앞으로 리포트 포맷을 본체와 독립적으로 진화시키겠다는 구조 변경입니다. 참고로 RFC 7489에 11년간 쌓인 정오표(errata) 15건이 각각 어떻게 처리됐는지도 RFC 9989 부록 C.9에 항목별로 기록돼 있습니다.

안 바뀐 것부터 — 당신의 레코드는 그대로 유효하다

실무자에게 가장 중요한 사실은 이것입니다. 버전 문자열이 그대로입니다. RFC 9989의 v 태그 정의는 여전히 유일한 유효값으로 v=DMARC1을 명시합니다(대소문자 구분, 레코드의 첫 태그여야 함). 한때 커뮤니티에서 돌던 "DMARC2가 온다"는 이야기는 실현되지 않았습니다. 지금 DNS에 있는 레코드는 새 스펙에서도 그대로 유효하고, 마이그레이션 이벤트 같은 것은 없습니다.

이게 가능한 이유는 스펙의 확장 규칙에 있습니다 — 알 수 없는 태그는 무시해야 하므로(MUST), 새 태그 추가는 버전 승급을 요구하지 않습니다. 뒤에서 볼 t, np, psd 태그가 전부 v=DMARC1 안에서 추가된 이유입니다. 반대로 pct처럼 폐지된 태그는 신형 수신자에게 "알 수 없는 태그"가 되어 조용히 무시됩니다.

가장 큰 변화 — PSL이 빠지고 DNS 트리 워크가 들어왔다

RFC 7489에서 조직 도메인(Organizational Domain)을 판별하는 방법은 Public Suffix List(PSL)였습니다. 이 방식의 문제는 RFC 7489 스스로도 알고 있었습니다 — 어떤 PSL을 쓰라고 강제하지 않았고(publicsuffix.org를 제안만 함), 갱신 주기 지침도 없었으며, 수신자마다 다른 PSL을 쓰면 상호운용성 문제가 생긴다는 것을 인정하면서 "더 신뢰할 수 있는 방법이 생기면 교체돼야 한다"고 적어 뒀습니다. IETF 바깥에서 자원봉사로 관리되는 목록 파일이 전 세계 이메일 정책 판별의 기준점이라는 것은 늘 불편한 의존성이었습니다.

RFC 9989는 이것을 DNS 트리 워크로 교체했습니다. 외부 목록 대신, DNS 계층을 직접 걸어 올라가며 DMARC 레코드를 찾는 방식입니다.

동작은 이렇습니다. 먼저 _dmarc.를 붙인 발신자 도메인(RFC5322.From의 도메인)에서 TXT 레코드를 조회하고, 없으면 라벨을 하나씩 벗겨 가며 위로 올라갑니다. DoS 방지를 위해 쿼리 수에 상한이 있습니다 — 최대 8쿼리. 라벨이 8개를 넘는 도메인은 중간을 건너뛰고 오른쪽 7개 라벨 지점으로 점프합니다. RFC의 예시를 그대로 옮기면, 라벨 13개짜리 도메인의 전체 트리 워크는 다음 8번의 조회로 끝납니다.

발신 도메인: a.b.c.d.e.f.g.h.i.j.mail.example.com

1. _dmarc.a.b.c.d.e.f.g.h.i.j.mail.example.com   (원래 도메인)
2. _dmarc.g.h.i.j.mail.example.com               (오른쪽 7개 라벨로 점프)
3. _dmarc.h.i.j.mail.example.com
4. _dmarc.i.j.mail.example.com
5. _dmarc.j.mail.example.com
6. _dmarc.mail.example.com
7. _dmarc.example.com
8. _dmarc.com

상한을 8로 정한 근거도 문서에 있습니다 — 발행 시점 관측 데이터상 실사용 발신 도메인은 라벨 7개까지 존재했고, 여유분 하나를 더한 값입니다.

걸어 올라가며 찾은 레코드들 중에서 조직 도메인을 고르는 규칙은 새 psd 태그와 엮여 있습니다. 요약하면 이렇습니다.

  • 유효한 레코드에 psd=n이 있으면 그 도메인이 조직 도메인. 끝.
  • 걷다가 만난 레코드에 psd=y가 있으면(공용 접미사 도메인이라는 선언) 그 한 라벨 아래 도메인이 조직 도메인.
  • 둘 다 없으면, 유효한 레코드가 발견된 이름 중 라벨 수가 가장 적은 것이 조직 도메인.

이 설계 덕에 RFC 9091이 실험적으로 시도했던 PSD DMARC(공용 접미사 수준의 정책, 예컨대 국가 TLD 운영자가 산하 비존재 도메인 사칭을 막는 것)가 별도 레지스트리 없이 본체에 흡수됐습니다. RFC 9989는 9091에 대해 "작성된 대로 구현되지 않았다"는 실험 결과를 담담히 기록하고 폐기 처리합니다.

전환기의 함정도 스펙에 명시돼 있습니다. RFC 7489 구현(PSL 기반) 수신자와 RFC 9989 구현(트리 워크) 수신자는 같은 메일에 대해 다른 조직 도메인, 따라서 다른 정책과 다른 정렬 판정에 도달할 수 있습니다. 스펙이 제시하는 회피책은 두 가지입니다 — 실제로 발신에 쓰는 모든 도메인에 명시적 DMARC 레코드를 게시할 것, 그리고 strict 정렬을 쓸 것. 발신 도메인 자체에 레코드가 있으면 어느 쪽 수신자든 걷기 전에 첫 쿼리에서 끝나므로 알고리즘 차이가 드러나지 않습니다.

태그 정리 — pct는 왜 죽었나

이번 개정에서 태그 세 개가 추가되고(np, psd, t) 세 개가 제거됐습니다(pct, rf, ri).

pct 폐지의 사연이 재미있습니다. 원래 의도는 "정책을 메일의 N%에만 적용해 달라"는 점진 전환 장치였는데, RFC 9989의 부록 A.6이 기록한 운영 경험은 이렇습니다 — 0과 100 말고는 정확히 적용되는 일이 드물었고, 구현마다 편차가 컸습니다. 그런데 그중 pct=0만은 전혀 다른 용도로 살아남았습니다. 일부 중개자(메일링 리스트 등)와 메일박스 제공자들이 pct=0을 "이 도메인이 곧 정책을 켤 예정"이라는 신호로 읽고, DMARC 실패를 피하도록 From 헤더를 재작성하는 트리거로 쓰기 시작한 겁니다. 도메인 소유자 입장에서는 pct=0을 켜기 전후의 집계 리포트를 비교하면 "From을 재작성하지 않는 중개자를 거치는 트래픽이 얼마나 되는지"를 추정할 수 있었고, 이는 enforcement로 넘어가도 되는지 판단하는 데 실제로 유용했습니다.

그래서 RFC 9989는 유효값이 사실상 둘뿐인 백분율 태그를 유지하는 대신, 그 살아남은 기능만 추려 t 태그(testing)로 대체했습니다. t=ypct=0에, 기본값인 t=npct=100에 대응합니다. t=y의 의미는 명확히 정의돼 있습니다 — 검증자에게 선언된 정책을 그대로 적용하지 말고 한 단계 낮춰 적용해 달라는 요청입니다. p=rejectt=y면 quarantine처럼, p=quarantinet=y면 none처럼 다뤄지고, 리포트 생성에는 영향을 주지 않습니다.

np 태그는 RFC 9091에서 수입된 것으로, 존재하지 않는 서브도메인(NXDOMAIN, RFC 8020 의미론 기준)에 대한 정책입니다. 폴백 순서는 np가 없으면 sp, sp도 없으면 p입니다. 실무적으로 이것은 서브도메인 사칭 방어에 바로 쓸 수 있는 도구입니다 — 실존 서브도메인은 sp=none으로 관찰하면서, 아예 존재하지 않는 이름의 사칭만 np=reject로 즉시 차단하는 조합이 가능해집니다.

_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine; t=y; sp=none; np=reject; rua=mailto:dmarc-rpt@example.com"

rf(실패 리포트 포맷)와 ri(리포트 간격) 태그는 제거됐고, 리포트 URI에 최대 크기를 지정하는 문법도 사라졌습니다(구형 문법은 무시 대상). 리포트 관련 세부는 이제 RFC 9990/9991의 영역입니다.

표준이 처음으로 못 박은 운영 원칙들

제 생각에 이번 개정의 진짜 무게는 알고리즘보다 여기에 있습니다. 지난 10년간 "다들 그렇게 하는" 암묵지였던 것들이 처음으로 규범 언어(MUST/SHOULD)가 됐습니다. RFC 9989의 7.4절과 8절에서 발췌합니다.

첫째, p=reject 도메인은 SPF에만 의존해서는 안 됩니다(MUST NOT). DKIM 서명은 의무입니다(MUST). 이유는 포워딩입니다. 졸업생 메일 릴레이나 역할 기반 별칭처럼 메일을 중계하는 흐름에서 SPF는 거의 확실히 깨집니다 — 최종 수신자가 보는 발신 IP는 중계자의 것이니까요. 반면 DKIM 서명은 본문이 변형되지 않는 한 중계를 살아남습니다. SPF만으로 DMARC를 통과시키던 도메인이 p=reject를 켜면, 정상적인 중계 메일이 조용히 버려집니다.

둘째, 일반 사용자가 메일을 쓰는 도메인은 p=reject를 게시하지 말아야 합니다(SHOULD NOT). 직원·구성원이 인터넷 메일링 리스트에 글을 쓸 수 있는 도메인이라면, p=reject는 리스트와 구독자들에게 실질적 피해를 줍니다. 꼭 가려면 스펙이 절차까지 정해 줍니다 — p=none으로 최소 한 달, 이어서 p=quarantine으로 같은 기간을 두고 집계 리포트의 처분 결과를 비교한 뒤에 판단하라는 것입니다. 은행처럼 기계 발송 트랜잭션 메일만 나가는 도메인과, 사람이 자유롭게 메일을 쓰는 도메인은 다른 정책이 맞다는 이야기이기도 합니다.

셋째, 수신자는 p=reject라는 이유만으로 메일을 거부해서는 안 됩니다(MUST NOT). 다른 근거 분석 없이 DMARC 실패만 있다면 p=quarantine처럼 다루라고(MUST) 명시합니다. 발신 도메인의 정책 선언은 수신자에게 명령이 아니라 참고 입력이라는 것 — Gmail 같은 대형 수신자들이 실제로 해 온 방식이 표준 문장이 된 셈입니다.

그 외에 "완전한 DMARC 참여"의 체크리스트를 정의한 8절도 볼만합니다. 도메인 소유자는 정렬된 SPF 정렬된 DKIM을 둘 다 갖추고, 집계 리포트 수신함을 만들어 실제로 분석하고, 발신 도메인과 조직 도메인 양쪽에 레코드를 게시해야 합니다. 수신자는 집계 리포트를 최소 하루 단위로 보내야 합니다(SHOULD).

RFC가 스스로 인정하는 것 — 메일링 리스트 문제는 못 풀었다

7.4절에는 표준 문서에서 보기 드문 수준의 솔직한 문단이 있습니다. 요지를 옮기면 — 위의 조언에도 불구하고, 간접 메일 흐름에 완화 조치를 적용하는 수신자는 현실에서 거의 없고, 자기 사용자들의 간접 메일에 미칠 영향을 고려하는 조직도 거의 없으며, 이 문서의 어떤 조언도 그 현실을 바꿀 것 같지 않다는 것입니다. 그 결과 From을 수정하지 않고 메일링 리스트를 거친 메일은 p=reject 때문에 빈번히 거부되고 있고, 지난 10년간 리스트 소프트웨어들은 전부 From 재작성 우회책을 채택해 이제 그것이 기정사실이 됐다고 기록합니다.

그럼 From 재작성 없이 리스트를 살리는 기술은 어디까지 왔나. RFC 9989가 직접 거명하는 후보가 ARC(Authenticated Received Chain, RFC 8617)인데, 평가는 냉정합니다 — "none of the methods have become widely used" (아직 어떤 방법도 널리 쓰이지 못했다). 실제로 RFC 8617은 2019년 이후 지금도 Experimental 지위 그대로입니다. 널리 채택되는 날이 오면 그때 문서를 갱신하겠다는 문장으로 이 절은 끝납니다. 요컨대 DMARC의 가장 오래된 부작용은 표준화 이후에도 열린 문제로 남아 있고, 표준 스스로가 그렇게 말합니다.

SPF -all의 사각지대 — 리포트에 안 잡히는 거부

7.1절이 지적하는 운영 함정 하나는 따로 언급할 가치가 있습니다. SPF는 SMTP 트랜잭션 초반, 본문 전송 전에 평가될 수 있습니다. 그래서 SPF 레코드를 하드 페일(-all)로 끝내는 도메인의 메일은 DMARC 처리가 시작되기도 전에 거부될 수 있습니다. 문제는 두 겹입니다.

  • 정렬된 DKIM 서명이 있어서 DMARC로는 통과했을 메일이, SPF 단계에서 먼저 잘려 나갈 수 있습니다.
  • 이렇게 DATA 단계 이전에 거부된 메일은 From 도메인이 드러나기 전이므로 집계 리포트에 아예 나타나지 않습니다.

DMARC 집계 리포트로 발신 현황을 관제하고 있다면, -all로 인한 조기 거부는 그 관제망의 바깥에서 일어난다는 뜻입니다. "리포트가 깨끗하다"와 "메일이 다 들어가고 있다"가 다른 명제가 되는 지점이라, -all을 쓰는 도메인은 이 사각지대를 알고 있어야 합니다. 소프트 페일(~all)과 DKIM 정렬 확보 위에서 DMARC 정책으로 거부를 통제하는 쪽이 가시성 면에서는 낫습니다.

구현은 어디까지 왔나

발행 두 달째인 지금은 명백히 전환기입니다. 확인 가능한 지점 몇 개만 짚습니다.

  • OpenDMARC는 2026-05-27에 RFC 9989/9990/9991 대비 격차 분석 이슈를 열어 추적 중이고, 조직 도메인 탐색을 구형 7489 워크·PSL·9989 트리 워크·자동 중에서 고르게 하는 walk_mode 선택 기능 PR이 2026-06-21에 develop 브랜치에 병합됐습니다. 즉 참조급 오픈소스 구현에서도 트리 워크는 이제 막 개발 브랜치에 들어간 단계입니다.
  • 네덜란드 정부 계열 진단 도구 Internet.nlPSL을 트리 워크로 교체하는 이슈를 열어 둔 상태입니다.
  • Gmail의 발신자 가이드라인은 이 글 작성 시점 기준 여전히 2024년 체제 그대로입니다 — 하루 5,000통 이상을 Gmail 계정으로 보내는 발신자는 SPF와 DKIM을 둘 다 설정하고 DMARC를 게시해야 하며, 정책은 none이어도 됩니다(공식 문서). 페이지 어디에도 RFC 9989 언급은 없습니다.

대형 메일박스 제공자들이 내부적으로 트리 워크로 전환했는지는 공개된 자료가 없어서 여기서 단정하지 않겠습니다. 분명한 것은, 당분간 인터넷에는 PSL 기준 수신자와 트리 워크 기준 수신자가 공존한다는 사실이고, 그래서 위에서 말한 회피책 — 발신에 쓰는 모든 도메인에 명시적 레코드 게시 — 이 전환기의 실질적 방어가 됩니다.

실무 체크리스트 — 지금 할 일과 안 해도 되는 일

안 해도 되는 일부터. 레코드의 v=DMARC1은 그대로 둡니다. DMARC2로의 마이그레이션 같은 것은 존재하지 않습니다. 기존 배포는 계속 동작합니다.

할 일은 이 정도입니다.

  1. DKIM 정렬을 먼저 확보하세요. p=reject이거나 그리로 갈 계획이라면, 모든 발신 경로가 정렬된 DKIM 서명을 달고 있는지부터 확인해야 합니다. SPF 단독 통과에 기대는 p=reject는 이제 명시적인 표준 위반(MUST NOT)입니다.
  2. 레코드에서 pct, rf, ri를 정리하세요. 신형 수신자는 어차피 무시하지만, 구형 수신자는 pct를 계속 해석하므로 두 부류가 다르게 동작하는 원인이 됩니다. 점진 전환 신호가 필요하면 t=y로 옮기세요 — 단, 구형 수신자는 반대로 t를 모른다는 것까지 감안해야 합니다.
  3. 실제 발신에 쓰는 모든 도메인에 명시적 DMARC 레코드를 게시하세요. PSL 수신자와 트리 워크 수신자가 다른 답에 도달할 여지를 원천 차단하는, 스펙이 직접 권하는 방법입니다.
  4. 존재하지 않는 서브도메인 사칭이 걱정이라면 np를 쓰세요. 실존 서브도메인 정책(sp)과 분리해서, NXDOMAIN인 이름만 강하게 막을 수 있습니다.
  5. -all을 쓰고 있다면 집계 리포트의 사각지대를 인지하세요. DATA 이전에 거부된 메일은 리포트에 남지 않습니다.
  6. 일반 사용자 도메인의 p=reject는 다시 생각하세요. 표준이 정한 절차 — none 최소 한 달, quarantine 같은 기간, 리포트 비교 — 를 거치지 않은 reject 전환은 이제 근거 문서를 들이밀 수 있는 반대 사유가 됩니다.

마치며

프로토콜 비트만 보면 이번 표준화는 조용한 개정입니다 — 레코드는 그대로고, 통과/실패 판정 로직도 대부분 그대로입니다. 하지만 세 가지는 실질적으로 달라졌습니다. 조직 도메인 판별이 외부 목록(PSL) 의존에서 DNS 자체 탐색(트리 워크, 최대 8쿼리)으로 바뀌었고, 점진 전환 장치가 현실에서 검증된 형태(t 태그)로 교체됐으며, 운영 원칙들이 처음으로 인용 가능한 규범 문장이 됐습니다 — p=reject에는 DKIM이 의무다, 사용자 도메인의 reject는 하지 마라, 수신자는 reject 선언만으로 버리지 마라.

그리고 이 표준의 가장 미더운 부분은 자기 한계를 문서 안에 적어 뒀다는 점입니다. 메일링 리스트 문제는 여전히 미해결이고, ARC는 여전히 실험이며, 수신자들이 조언을 따르지 않으리라는 것까지 표준이 스스로 예측합니다. 11년 걸린 표준화의 결론이 "완성"이 아니라 "현실의 정직한 기록"이라는 것 — 이메일이라는 40년 된 시스템에는 그게 오히려 어울리는 결말 같습니다.

참고 자료

DMARC Becomes a Standard After 11 Years — RFC 9989's Tree Walk, the pct Sunset, and the p=reject Warning

Introduction — A Protocol Everyone Used but No One Standardized

This starts with an odd fact. Gmail and Yahoo have effectively mandated DMARC for bulk senders since 2024, banks and government agencies get audited on their adoption status, and an entire email-security startup ecosystem is built on top of it — yet RFC 7489, the document that defines DMARC, was never an IETF standard. Published in March 2015, it is an Independent Submission that never went through IETF working-group consensus, and its classification is Informational. Looking only at the document's status, the entire world's email authentication has run for 11 years on top of a document that essentially recorded "here is what someone is doing."

That ended in May 2026. The IETF DMARC working group's so-called DMARCbis effort was published as RFC 9989, making DMARC a Standards Track document and obsoleting both RFC 7489 and RFC 9091 (the experimental document that covered PSD DMARC). Per the datatracker, it is draft revision 41, an 83-page result.

You might wave this off as "congratulations on becoming a standard," but this revision actually changes the protocol's behavior. The algorithm for finding the organizational domain has been swapped out wholesale, a handful of tags have disappeared and appeared, and above all, operational principles that had long been the community's tribal knowledge are now nailed down for the first time in MUST and SHOULD NOT language. Let's go through it one piece at a time. (If SMTP and DNS themselves are unfamiliar territory, DNS and Email Protocols is worth reading first.)

What Was Published — DMARC Split into Three Documents

The single RFC 7489 spec has been split into three documents. All of them were published together in May 2026, and all of them are Standards Track.

  • RFC 9989 — the DMARC core. Policy record syntax, alignment evaluation, policy discovery. It obsoletes RFC 7489 and RFC 9091. The editors are T. Herr of Valimail and J. Levine of Standcore.
  • RFC 9990 — aggregate reporting. The XML report format and transport method were split off into this document.
  • RFC 9991 — failure reporting. It updates RFC 6591.

Splitting off the reporting spec is not mere document housekeeping — it is a structural change that lets the reporting format evolve independently of the core going forward. For reference, RFC 9989's Appendix C.9 also records item by item how each of the 15 errata that accumulated against RFC 7489 over 11 years was disposed of.

What Didn't Change First — Your Records Are Still Valid

The single most important fact for practitioners is this: the version string stays the same. RFC 9989's definition of the v tag still specifies v=DMARC1 as the only valid value (case-sensitive, and it must be the record's first tag). The "DMARC2 is coming" rumor that once circulated in the community never materialized. Whatever record sits in DNS today remains valid under the new spec, and there is no migration event of any kind.

The reason this is possible lies in the spec's extension rule — because unknown tags MUST be ignored, adding a new tag never requires a version bump. That is exactly why the t, np, and psd tags we will see below could all be added inside v=DMARC1. Conversely, a retired tag like pct simply becomes an "unknown tag" to a new-generation receiver and is silently ignored.

The Biggest Change — PSL Out, DNS Tree Walk In

Under RFC 7489, the method for determining the Organizational Domain was the Public Suffix List (PSL). RFC 7489 itself was aware of the problems with this approach — it never mandated which PSL to use (it only suggested publicsuffix.org), gave no guidance on update cadence, and acknowledged that different receivers using different PSLs would create interoperability problems, writing that the method "should be replaced" once something more reliable came along. A volunteer-maintained list file living outside the IETF serving as the reference point for the whole world's email policy determination was always an uncomfortable dependency.

RFC 9989 replaces this with a DNS tree walk. Instead of an external list, it walks straight up the DNS hierarchy looking for a DMARC record.

Here is how it works. First, it queries the TXT record at the sender domain (the domain in RFC5322.From) with _dmarc. prepended; if there is none, it strips off labels one at a time and climbs upward. There is a cap on the number of queries to prevent DoS — up to 8 queries. A domain with more than 8 labels skips the middle and jumps straight to the point 7 labels from the right. Taking the RFC's own example, the full tree walk for a 13-label domain finishes in exactly the following 8 lookups.

Sender domain: a.b.c.d.e.f.g.h.i.j.mail.example.com

1. _dmarc.a.b.c.d.e.f.g.h.i.j.mail.example.com   (original domain)
2. _dmarc.g.h.i.j.mail.example.com               (jump to the rightmost 7 labels)
3. _dmarc.h.i.j.mail.example.com
4. _dmarc.i.j.mail.example.com
5. _dmarc.j.mail.example.com
6. _dmarc.mail.example.com
7. _dmarc.example.com
8. _dmarc.com

The rationale for setting the cap at 8 is also in the document — at publication time, observed data showed real-world sending domains going up to 7 labels, plus one extra for headroom.

The rule for picking the organizational domain among the records found while walking up is tied to the new psd tag. Summarized:

  • If a valid record has psd=n, that domain is the organizational domain. Done.
  • If a record encountered along the walk has psd=y (a declaration that this is a public-suffix-level domain), the domain one label below it is the organizational domain.
  • If neither is present, the name with the fewest labels among those where a valid record was found is the organizational domain.

This design lets PSD DMARC — the public-suffix-level policy (for example, a country-TLD operator blocking impersonation of non-existent domains beneath it) that RFC 9091 tried experimentally — get absorbed into the core spec without a separate registry. RFC 9989 dryly records the experimental result for 9091 as "not implemented as written" and obsoletes it.

The transition-era trap is spelled out in the spec too. A receiver implementing RFC 7489 (PSL-based) and one implementing RFC 9989 (tree walk) can arrive at different organizational domains, and therefore different policies and different alignment verdicts, for the same piece of mail. The spec offers two workarounds — publish an explicit DMARC record on every domain actually used for sending, and use strict alignment. If the sending domain itself has a record, either kind of receiver terminates on the very first query before any walking happens, so the algorithmic difference never surfaces.

Tag Cleanup — Why pct Died

This revision adds three tags (np, psd, t) and removes three (pct, rf, ri).

The story behind retiring pct is a good one. It was originally meant as a gradual-rollout device — "apply the policy to only N% of mail" — but the operational experience recorded in RFC 9989's Appendix A.6 is this: values other than 0 and 100 were rarely applied precisely, and implementations varied widely. Yet pct=0 alone survived, for a completely different purpose. Some intermediaries (mailing lists, etc.) and mailbox providers started reading pct=0 as a signal that "this domain is about to turn its policy on" and using it as a trigger to rewrite the From header so as to avoid DMARC failures. From a domain owner's perspective, comparing aggregate reports before and after turning on pct=0 let you estimate "how much traffic goes through intermediaries that don't rewrite From" — genuinely useful for deciding whether it was safe to move to enforcement.

So instead of keeping a percentage tag whose valid values were effectively just two, RFC 9989 distilled out only the surviving function and replaced it with the t tag (testing). t=y corresponds to pct=0, and the default t=n corresponds to pct=100. The meaning of t=y is precisely defined — it is a request to the verifier not to apply the declared policy as-is, but to apply it one notch lower. With t=y, p=reject is treated like quarantine, p=quarantine is treated like none, and it has no effect on report generation.

The np tag was imported from RFC 9091, and it is a policy for non-existent subdomains (NXDOMAIN, per RFC 8020 semantics). The fallback order is: if there is no np, use sp; if there is no sp either, use p. In practice, this is a tool you can use immediately against subdomain impersonation — you can observe real, existing subdomains under sp=none while immediately blocking impersonation of names that don't exist at all under np=reject.

_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine; t=y; sp=none; np=reject; rua=mailto:dmarc-rpt@example.com"

The rf (failure report format) and ri (report interval) tags were removed, and the syntax for specifying a maximum size on a report URI is also gone (the old syntax is now ignored). The reporting details now live in the territory of RFC 9990/9991.

The Operational Principles the Standard Nails Down for the First Time

In my view, the real weight of this revision lies here rather than in the algorithm. Things that were tribal knowledge — "everyone just does it this way" — for the past decade have become normative language (MUST/SHOULD) for the first time. The following is drawn from sections 7.4 and 8 of RFC 9989.

First, p=reject domains must not rely on SPF alone (MUST NOT). DKIM signing is mandatory (MUST). The reason is forwarding. In mail flows that relay messages — alumni mail relays, role-based aliases, and the like — SPF is almost guaranteed to break, because the sending IP the final recipient sees belongs to the relay, not the original sender. DKIM signing, by contrast, survives relaying as long as the body isn't modified. If a domain that used to pass DMARC on SPF alone turns on p=reject, legitimate relayed mail gets silently dropped.

Second, a domain where ordinary users send mail should not publish p=reject (SHOULD NOT). If employees or members can post to internet mailing lists from a domain, p=reject inflicts real damage on those lists and their subscribers. The spec even lays out a procedure if you must go there — p=none for at least one month, then p=quarantine for the same period, and only decide after comparing the disposition results in the aggregate reports. It also implies that a domain that only sends machine-generated transactional mail, like a bank's, and a domain where people freely write mail, deserve different policies.

Third, a receiver must not reject mail on the sole basis of p=reject (MUST NOT). Without other supporting analysis, a DMARC failure alone must (MUST) be treated like p=quarantine. In other words, the sending domain's policy declaration is input for the receiver to consider, not a command — what large receivers like Gmail have actually done in practice has become the standard's own sentence.

Section 8, which defines a checklist for "full DMARC participation," is also worth a look. Domain owners are expected to have both aligned SPF and aligned DKIM, set up an aggregate-report inbox and actually analyze it, and publish records on both the sending domain and the organizational domain. Receivers are expected to send aggregate reports at least once a day (SHOULD).

What the RFC Admits Itself — The Mailing List Problem Remains Unsolved

Section 7.4 contains a paragraph unusually candid for a standards document. Paraphrased: despite all the advice above, in practice almost no receiver applies mitigations for indirect mail flows, almost no organization considers the impact on its own users' indirect mail, and nothing in this document seems likely to change that reality. As a result, mail that passes through mailing lists without modifying From is frequently rejected because of p=reject, and over the past decade every piece of list software has adopted a From-rewriting workaround — a fact the document records as now settled.

So how far has the technology that could save lists without rewriting From actually come? The candidate RFC 9989 names directly is ARC (Authenticated Received Chain, RFC 8617), and its assessment is unsentimental — "none of the methods have become widely used." In fact, RFC 8617 has sat at Experimental status since 2019 and remains there today. The section closes with a line saying the document will be updated once such a method achieves wide adoption. In short, DMARC's oldest side effect remains an open problem even after standardization, and the standard says so itself.

The SPF -all Blind Spot — Rejections That Never Hit the Reports

One operational trap flagged in Section 7.1 deserves separate mention. SPF can be evaluated early in the SMTP transaction, before the message body is even transmitted. That means mail from a domain whose SPF record ends in a hard fail (-all) can be rejected before DMARC processing even begins. The problem here is two layers deep.

  • Mail that would have passed under DMARC — because it carries an aligned DKIM signature — can get cut off first at the SPF stage.
  • Because mail rejected before the DATA stage never gets far enough for the From domain to be revealed, it never shows up in the aggregate reports at all.

If you're using DMARC aggregate reports to monitor your sending posture, early rejections caused by -all happen entirely outside that monitoring net. This is the point where "the reports look clean" and "all my mail is actually getting through" become two different claims, and any domain using -all needs to be aware of this blind spot. Controlling rejection through DMARC policy on top of a soft fail (~all) and solid DKIM alignment is the better choice for visibility.

Where Implementations Stand

Two months after publication, we are clearly in a transition period. A few checkable data points:

  • OpenDMARC opened a gap-analysis issue against RFC 9989/9990/9991 on 2026-05-27 and is tracking it, and a walk_mode selection PR that lets you choose organizational-domain discovery among the legacy 7489 walk, PSL, the 9989 tree walk, or automatic was merged into the develop branch on 2026-06-21. Even in a reference-grade open-source implementation, the tree walk has only just landed in a development branch.
  • The Dutch government-affiliated diagnostic tool Internet.nl also has an open issue tracking the PSL-to-tree-walk swap.
  • Gmail's sender guidelines are, as of this writing, still on the 2024 regime — senders sending 5,000 or more messages a day through Gmail accounts must set up both SPF and DKIM and publish DMARC, though the policy may be none (official documentation). There is no mention of RFC 9989 anywhere on the page.

There's no public material confirming whether large mailbox providers have internally switched to the tree walk, so I won't assert anything here. What is clear is that PSL-based and tree-walk-based receivers will coexist on the internet for a while, which makes the workaround mentioned above — publishing explicit records on every domain used for sending — a real, practical defense for the transition period.

Practical Checklist — What to Do Now, and What You Can Skip

Start with what you don't need to do. Leave v=DMARC1 in your records as-is. There is no such thing as a migration to DMARC2. Your existing deployment keeps working.

Here is what's actually worth doing.

  1. Secure DKIM alignment first. If you're at p=reject or planning to get there, verify that every sending path carries an aligned DKIM signature. A p=reject that depends on SPF passing alone is now an explicit standards violation (MUST NOT).
  2. Clean pct, rf, and ri out of your records. New-generation receivers ignore them anyway, but legacy receivers still interpret pct, which is exactly why the two populations behave differently. If you need a gradual-rollout signal, move to t=y — but keep in mind that legacy receivers, in turn, don't understand t either.
  3. Publish an explicit DMARC record on every domain actually used for sending. This is the spec's own recommended way to head off the possibility that PSL-based and tree-walk-based receivers land on different answers.
  4. Use np if you're worried about impersonation of non-existent subdomains. Separate from your policy for real, existing subdomains (sp), you can strongly block only names that resolve NXDOMAIN.
  5. If you're using -all, be aware of the blind spot in your aggregate reports. Mail rejected before DATA never shows up in the reports.
  6. Reconsider p=reject on domains ordinary users send from. A reject transition that skipped the standard's prescribed procedure — none for at least a month, quarantine for the same period, comparing the reports — is now something people can push back on with a reference document in hand.

Closing

Looked at purely in terms of protocol bits, this standardization is a quiet revision — the records stay the same, and most of the pass/fail evaluation logic stays the same too. But three things have substantively changed: organizational-domain determination moved from dependency on an external list (PSL) to DNS's own discovery (a tree walk, up to 8 queries); the gradual-rollout device was replaced with a form validated by real-world experience (the t tag); and operational principles became citable normative sentences for the first time — DKIM is mandatory for p=reject, don't reject on a user domain, and receivers must not discard mail on a reject declaration alone.

And the most trustworthy part of this standard is that it wrote its own limitations into the document. The mailing-list problem remains unsolved, ARC remains Experimental, and the standard even predicts that receivers won't follow its own advice. The conclusion of an 11-year standardization effort isn't "completion" — it's "an honest record of reality." For a 40-year-old system like email, that actually seems like a fitting ending.

References