新しいメール配信や請求書のサービスを入れて、案内どおりにDNSへSPFレコードを「追加」した。その後から、送ったメールが迷惑メールに入ると言われるようになった。この流れなら、SPFが2行になっています。
メール配信や請求書のサービスを足したら、案内に「このTXTレコードを追加してください」とあった。そのとおりにした後から、取引先に「迷惑メールに入っていた」と言われる。そういう人へ。
SPF(このドメインの名前でメールを送ってよいサーバを、DNSに書いておく1行)は、2行あると、どちらも正しくても全部が失敗扱いになります。受信側が都合のよいほうを選んでくれることはありません。この記事を読み終えると、dig で行数を数え、1行にまとめ、まとめた後に踏みやすい「参照10回」の上限まで確かめられます。
- この記事で出来ること
- digでSPFの行数を数え、1行にまとめ、参照10回の上限まで確かめられる
- 前提
- DNSの管理画面に入れること(入れなければ、記事の文面で業者に頼む)。digかnslookupが打てるPC
- 所要時間
- 確認5分、書き換え15分。反映はレコードのTTL(多くは1時間)の後
先に結論
- 直し方は統合です。2行の中身を1行にまとめ、古いほうを消す。書き足して終わりではありません。
- サービスの案内に「このTXTレコードを追加してください」とあっても、真に受けません。足すのは
include、増やしてはいけないのは行です。 - 10回の上限に当たりそうなら、工夫する前に、もう使っていない送信サービスを外します。
目次(9)
1. 何行あるかを数える
自分のドメインに登録されているTXTレコード(文字を書いておく種類の行)を全部表示させる1行です。見るだけで、何も変わりません。コマンドを打てないなら、DNSの管理画面のレコード一覧で、種類が「TXT」の行を数えても同じです。管理画面に入れなければ、ブラウザで使える Google Admin Toolbox の Dig(toolbox.googleapps.com/apps/dig/)にドメイン名を入れて TXT を押し、結果を後半の「業者に送る文面」に貼って頼みます。
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が未設定 | SPF・DKIM・DMARCの3行の入れ方 |
v=spf1 の行が1つ | 数は正しい | 4節(参照回数)へ |
v=spf1 の行が2つ以上 | permerror になる状態 | 3節へ |
1行の中に引用符の区切りが複数("v=spf1 …" "… ~all") | 1つのレコードが複数の文字列に分かれているだけ | 数は1つ。4節へ |
最後の行は見間違えやすい点です。1つの文字列は255オクテットまでなので、長いレコードは管理画面が自動で分割します。RFC 7208は、複数の文字列を空白を足さずに連結して1つとして扱うと定めています(3.3節)。これを「2行ある」と勘違いして片方を消すと、レコードが途中で切れます。
2. なぜ2行ではいけないのか
RFC 7208の定めはこうです。
- 3.2節: ドメイン名は、判定の際に複数のレコードが選ばれる状態になってはならない
- 4.5節: 選ばれたレコードが2つ以上なら、判定は permerror を返す
- 2.6.7節: permerror は「公開されているレコードを正しく解釈できない」ことを示し、DNSの運用者による対処が必要
本当にそうなるのか、手元の検証環境に v=spf1 が2行あるドメインを作って確かめました。検証ツール2つ(pyspf と Mail::SPF の spfquery)と、実際にメールを受けた受信サーバの3つで見ています。3つとも permerror です。どちらの行も、単独なら正しいのに、です。

v=spf1 が2行あるドメインを、2つの検証ツールと実際の受信サーバで確かめた結果。3つとも permerror(検証環境・撮影 2026-09-20)見るのは、検証ツールの理由の文(レコードが2つ以上見つかった)と、受信したメールに付いたヘッダーです。
lab$ dig +short example.com TXT
"v=spf1 ip4:192.0.2.100 ~all"
"v=spf1 include:_spf.lab.example ~all"
"site-verification=lab-dummy-0000"
lab$ python3 -m spf 192.0.2.100 info@example.com client.lab.example
result: ('permerror', 550, 'SPF Permanent Error: Two or more type TXT spf records found.') None
(中略)
lab$ grep -E "^Received-SPF" /var/mail/info
Received-SPF: Permerror (mailfrom) identity=mailfrom; client-ip=192.0.2.100; helo=client.lab.example; envelope-from=info@example.com; receiver=example.jp
permerror のメールをどう扱うかは受信側の方針です。だから厄介で、全部が止まるのではなく、相手によって届いたり迷惑メールに入ったりします。よくあるのは、社内や身内のテストでは届くので気づかず、数週間後に取引先から「最近メールが迷惑メールに入る」と言われて発覚する形です。受信側が判定結果をヘッダーに記録していれば、届いたメールの Authentication-Results に spf=permerror と残ります(RFC 8601)。上の検証のように Received-SPF: Permerror という別のヘッダーに書く受信サーバもあるので、どちらかを探します。疑ったら、外部のアドレスへ1通送ってヘッダーを見るのがいちばん早い確認です。
3. 1行にまとめる
- 2行から、
v=spf1と末尾のallを除いた部分(include、ip4、ip6、a、mxなど)を書き出す - いま実際に送っている経路だけを残す。 使い終えた事業者の分は入れない
v=spf1を先頭に1回、残した部分を並べ、末尾にallを1回だけ置く- 管理画面で片方をこの内容に書き換え、もう片方を削除する
まとめる前:
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
検証環境でも2行を1行にまとめ、同じ3つの方法で確かめ直しました。3つとも pass に変わります。変えたのは行の数だけで、中身(ip4 と include)は足しも引きもしていません。

lab$ dig +short example.com TXT
"v=spf1 ip4:192.0.2.100 include:_spf.lab.example ~all"
"site-verification=lab-dummy-0000"
lab$ python3 -m spf 192.0.2.100 info@example.com client.lab.example
result: ('pass', 250, 'sender SPF authorized') ip4:192.0.2.100
書き込んで使う表
| 送信の経路(誰が送るか) | いまも使っているか | レコードに入れる部分 |
|---|---|---|
| 例: ふだんのメール(事業者A) | はい | include:_spf.mail-a.example |
| 例: サイトの問い合わせフォーム(サーバ) | はい | ip4:192.0.2.10 |
| 例: 以前使っていたメール配信サービス | いいえ | 入れない |
漏れやすいのは、人が送らないメールです。サイトのフォーム、請求書、予約のサービスが、自分のドメインを差出人にして送っていないかを確かめます。include の値は各事業者の公式ヘルプに載っているものをそのまま使います。
末尾の ~all と -all が2行で食い違っていたら、私は ~all に寄せます。理由は、統合の直後は経路の漏れがまだ残っているかもしれず、-all だと漏れた経路のメールが即座に拒否されうるからです。全経路で pass を確かめ、DMARCを入れてから厳しくしても遅くありません。
「誰が入れたか分からない include が残っているが、怖くて消せない」もよくあります。私なら、そのサービスの管理画面にまだ入れるか、請求が続いているかを確かめ、どちらも無ければ外します。不要な include は10回の枠を食うだけでなく、自分の管理下にない送信元に、自分のドメインを名乗る許可を与え続けている状態だからです。
4. まとめた後に踏みやすい「参照10回」
RFC 7208の4.6.4節は、DNSの参照を起こす項目(include、a、mx、ptr、exists の各機構と redirect 修飾子)を合計10回までに制限しています。超えた結果も permerror です。2行を1行にまとめると、この数は足し算になります。
include は、その先のレコードの中の include も数に入ります。
dig +short _spf.mail-a.example TXT
のように include の先を順にたどって数えます。ip4 と ip6 は参照を起こさないので数に入りません。大手のメールサービスは、1つの include の先でさらに3〜4回使うことがあり、3サービスを並べると10回に届きます。
超えそうなときの私の順番です。
- 使っていない送信サービスを外す。 これで収まることがほとんどです
aやmxを、参照を起こさないip4に書き換える(自分のサーバのIPアドレスが固定の場合だけ)- メール配信など一部の送信を、サブドメイン(
news.example.comなど)に分ける。SPFはドメイン名ごとに評価されるので、枠が別になります
勧めないのは、include の先のIPアドレスを全部調べて ip4 で並べ直す方法(フラット化)です。事業者が送信元のIPアドレスを変えた日に、予告なく届かなくなります。自動で追従するサービスもありますが、数人の会社でそこまでして1行に詰め込むなら、3のほうが安全です。
5. 反映の確認
dig +short example.com TXTでv=spf1が1行になっている- TTLが過ぎてから、外部のアドレスあてに1通送る。フォームや請求書サービスなど、表に書いた経路の全部で
- 届いたメールのヘッダーで
spf=pass(またはReceived-SPF: Pass)を見る
うまくいかなかったときの戻し方
まとめた後に「前は届いていた相手に届かなくなった」なら、統合のときに経路を1つ落としています。戻し方は、2行に戻すことではありません。 2行に戻せば permerror に戻るだけです。
- 作業の前に控えた元の2行(控えていなければ、DNSの管理画面の変更履歴)と、いまの1行を並べる
- 元の2行にあって、いまの1行に無い
include・ip4・a・mxを見つけ、いまの1行に書き足す - 末尾を
-allにしていたら、~allに緩める。漏れた経路のメールが即座に拒否されるのを止めるためです - レコードのTTL(多くは1時間)が過ぎてから、5節の確認をやり直す
直しても即効でないのは、受信側のリゾルバが古いTXTをTTLの間だけ覚えているからです。だから私は、作業の前に元の2行をメモ帳に貼って保存し、TTLを確かめてから触ります。
業者に送る文面
DNSを制作会社やサーバ会社が管理している場合は、次の文面で頼みます。「追加ではなく統合」が伝わらないと、3行目が増えて返ってきます。まとめた後の1行をこちらで書いて渡すのが確実です。【】を置き換えてください。
件名: example.com のSPFレコードの統合のお願い
【会社名】【担当者名】様
お世話になっております。【自社名】の【氏名】です。
example.com のTXTレコードに、v=spf1 で始まる行が2つあります。
SPFは1ドメインに1行と決まっており(RFC 7208 4.5節)、2行あると
受信側で認証エラー(permerror)になるため、1行への統合をお願いします。
現在の2行(dig +short example.com TXT の結果)
【1行目】
【2行目】
お願いしたいこと
1. 上の2行を削除し、次の1行だけを登録してください
【まとめた後の1行】
2. v=spf1 以外のTXTレコード(サイトの所有確認など)は、そのまま残してください
3. 作業後、TXTレコードの一覧をお送りください
今後、送信サービスを増やすときも、行を足さず、この1行に include を
書き足す形でお願いします。
6. 確認表
| # | 確認すること | 済 |
|---|---|---|
| 1 | v=spf1 で始まるTXTレコードが1つだけ | □ |
| 2 | 自分のドメインを差出人にして送る経路を、すべて書き出した | □ |
| 3 | 使い終えた事業者の include を外した | □ |
| 4 | all がレコードの末尾に1回だけある | □ |
| 5 | 参照を起こす項目が、include の先も含めて10回以内 | □ |
| 6 | 古いほうのレコードを削除した | □ |
| 7 | 全部の経路で、ヘッダーの spf=pass を確認した | □ |
| 8 | 経路を足すときは「既存の1行に書き足す」と、DNSを触る人全員で決めた | □ |
8がいちばん効きます。2行になる事故は、知識の不足ではなく「案内どおりにやった」結果だからです。
送信サービスが増えるたびにこの作業が怖いなら、メールの置き場所を見直す時期です。私なら、ふだんのメールはグループウェアに置き、DNSはレコードの一覧と履歴が見やすいDNSサービスかドメイン登録先に置きます。SPFの1行を誰がいつ変えたか追えるだけで、この種の事故は大きく減ります。
SPFはサーバやメールの乗り換えのたびに書き換えが要る場所です。乗り換え全体の順番は次の記事にあります。
→ サーバを乗り換えたらメールが止まった、を防ぐ。引っ越しはこの順番で動かす
出典(取得日: 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