結論
- SPFの仕様(RFC 7208)は、1つのドメイン名に「v=spf1」で始まるレコードを複数置いてはならないと定めています。2つ以上見つかった場合、判定の結果は permerror(恒久的なエラー)になります。
- 直し方は「2つの中身を1つのレコードにまとめ、古い方を消す」です。追記ではなく統合です。
- 2つになるのは、メールの事業者を足したり替えたりしたときに、案内どおりのレコードを「追加」した場面で起こりやすい状態です。
- まとめた後は、レコードが1つになったことと、DNSの参照回数が上限の10回に収まっていることを確かめます。
SPFそのものの役割と、DKIM・DMARCとの関係は別の記事にまとめています。
1. いくつあるかを数える
dig +short example.com TXT
"v=spf1 include:_spf.mail-a.example ~all"
"v=spf1 include:_spf.mail-b.example ~all"
"some-site-verification=abcdefg"
Windowsでは nslookup -type=TXT example.com で同じ内容を見られます。
数えるのは「v=spf1」で始まる行だけです。TXTレコードはサイトの所有確認など別の用途にも使われるので、TXTが複数あること自体は問題ではありません。上の例では「v=spf1」が2行あり、これが直す対象です。
| 表示 | 状態 | 次に進む先 |
|---|---|---|
| 「v=spf1」の行が0 | SPFが未設定 | 上のリンク先の記事の手順へ |
| 「v=spf1」の行が1つ | 数は正しい | 4節(参照回数)へ |
| 「v=spf1」の行が2つ以上 | permerror になる状態 | 2節へ |
| 1行の中に引用符の区切りが複数ある(“v=spf1 …” ”… ~all”) | 1つのレコードが複数の文字列に分かれているだけ | 数は1つ。4節へ |
最後の行は見間違えやすい点です。RFC 7208は、1つのレコードが複数の文字列でできている場合、空白を足さずに連結して1つとして扱うと定めています。1つの文字列は255オクテットまでなので、長いレコードは管理画面が自動で分割することがあります。
2. なぜ2つではいけないのか
RFC 7208の定めは次のとおりです。
- 3.2節: ドメイン名は、判定の際に複数のレコードが選ばれる状態になってはならない。
- 4.5節: 選ばれたレコードが2つ以上なら、判定の関数は permerror を返す。
- 2.6.7節: permerror は「公開されているレコードを正しく解釈できない」ことを示し、DNSの運用者による対処が必要な状態である。
つまり、受信側は2つのうち都合のよい方を選んでくれるわけではありません。どちらのレコードも単独では正しくても、2つあるだけで全体がエラーになります。permerror のメールをどう扱うかは受信側の方針によります。受信側が判定結果をメールのヘッダー(Authentication-Results)に記録している場合は、届いたメールのヘッダーに「spf=permerror」と残ります(RFC 8601)。
3. 1行にまとめる
まとめ方
- 2つのレコードから、「v=spf1」と末尾の「all」を除いた部分(include、ip4、ip6、a、mx など)を書き出す。
- いま実際にメールを送っている経路だけを残す。使い終えた事業者の分は入れない。
- 「v=spf1」を先頭に1回、残した部分を並べ、末尾に「all」を1回だけ置く。
- DNSの管理画面で、片方のレコードをこの内容に書き換え、もう片方を削除する。
まとめる前:
v=spf1 include:_spf.mail-a.example ~all
v=spf1 include:_spf.mail-b.example ip4:192.0.2.10 ~all
まとめた後:
v=spf1 include:_spf.mail-a.example include:_spf.mail-b.example ip4:192.0.2.10 ~all
書き込んで使う表
| 送信の経路(誰が送るか) | いまも使っているか | レコードに入れる部分 |
|---|---|---|
| 例: ふだんのメール(事業者A) | はい | include:_spf.mail-a.example |
| 例: サイトの問い合わせフォーム(サーバ) | はい | ip4:192.0.2.10 |
| 例: 以前使っていたメール配信サービス | いいえ | 入れない |
経路の洗い出しが、この作業でいちばん漏れやすい部分です。メールソフトからの送信のほかに、サイトのフォーム、請求書や予約のサービスが自分のドメインを差出人にして送っていないかを確かめます。include に書く値は、各事業者の公式ヘルプに載っているものをそのまま使います。
末尾の「~all」と「-all」が2つのレコードで食い違っているときは、どちらか1つに決めます。迷う場合は、いま使っている事業者の公式ヘルプが案内している書き方に合わせます。
4. まとめた後に見ること
参照回数の上限
RFC 7208の4.6.4節は、SPFの評価の中でDNSの参照を起こす項目(include、a、mx、ptr、exists の各機構と redirect 修飾子)を、合計10回までに制限しています。超えた場合の結果も permerror です。
include は、その先のレコードの中にある include も数に入ります。2つを1つにまとめると、この数は足し算になります。
dig +short _spf.mail-a.example TXT
のように include の先を順にたどり、参照を起こす項目を数えます。ip4 と ip6 は参照を起こさないので数に入りません。
反映の確認
dig +short example.com TXTで「v=spf1」が1行になっている。- 古い答えが残る時間(TTL)が過ぎてから、外部のアドレスあてに1通送る。
- 届いたメールのヘッダーを開き、「spf=pass」になっているかを見る。
TTLの考え方と、変更が見えるまでの待ち方は次の記事にあります。
5. 確認表
| # | 確認すること | 済 |
|---|---|---|
| 1 | 「v=spf1」で始まるTXTレコードが1つだけである | □ |
| 2 | 自分のドメインを差出人にして送る経路を、すべて書き出した | □ |
| 3 | 使い終えた事業者の include を外した | □ |
| 4 | 「all」がレコードの末尾に1回だけある | □ |
| 5 | DNSの参照を起こす項目が、include の先も含めて10回以内である | □ |
| 6 | 古い方のレコードを削除した(残したままにしていない) | □ |
| 7 | 送ったメールのヘッダーで spf=pass を確認した | □ |
| 8 | 経路を足すときは「追加」ではなく「既存の1行に書き足す」と決めた | □ |
出典(取得日: 2026-09-20)
- RFC 7208 Sender Policy Framework (SPF) for Authorizing Use of Domains in Email, Version 1(2.6.7、3.2、3.3、4.5、4.6.4の各節) https://www.rfc-editor.org/rfc/rfc7208.html
- RFC 8601 Message Header Field for Indicating Message Authentication Status https://www.rfc-editor.org/rfc/rfc8601.html