メインコンテンツへスキップ
友田 陽大
Resend・メール配信
Resend
メール配信
SPF/DKIM/DMARC
到達率
インフラ
信頼性

Resend のドメイン認証と到達率:SPF・DKIM・DMARC を「正しいホスト名」に置く

Resend のドメイン検証が通らない原因のほとんどは DNS のホスト名です。SPF は send サブドメイン、DKIM は resend._domainkey、DMARC は _dmarc。正確なレコード表・dig での実測・DMARC の育て方・一括送信者要件を公式と RFC に忠実にまとめます。

公開日
読了時間
33分
著者
友田 陽大
シェア

このサイトの問い合わせフォームは、ある時期から送信のたびに 502 を返し続けていました。Route Handler のコードは正しく、Zod のバリデーションも通り、ローカルでは動く。原因は Resend のドメイン検証が通っていないことで、その検証が通らない原因は、私が DKIM・SPF の TXT・SPF の MX・DMARC の4件すべてを apex(ルートドメイン)に置いていたことでした。コードを何度読んでも見つからないはずで、壊れていたのは DNS のホスト名だったのです。

珍しい事故ではありません。Resend のトラブルシューティングページは、確認手順の2番目に「レコードが正しい場所(ルートドメインではなく send サブドメイン)に追加されているか確認する」を置いています。わざわざ手順に書かれているということは、そこで詰まる人が多いということです。

この記事は、Resend のドメイン認証を一度で通し、以後崩さないための実務ガイドです。3つの規格の役割分担を RFC まで遡って整理し、正確なレコード表を示し、ホスト名の罠を dig で潰し、DMARC を安全に育て、Gmail・Yahoo・Microsoft の要件に合わせ、最後に「届いているのに見えない」ときの切り分けまで通します。クラスタ全体の地図は Resend 本番運用ガイド にあります。


なぜ SPF・DKIM・DMARC の3つが必要か

3つは競合する規格ではなく、役割の違う3層です。ここが腹落ちすると、あとのレコード配置がすべて理屈で決まります。

規格一言でいうと答える問い一次規格
SPF送ってよい経路の宣言この IP はこのドメインの代理で送ってよいのかRFC 7208
DKIM署名による同一性の証明本文とヘッダはドメイン所有者が署名したままかRFC 6376(鍵長は RFC 8301 が更新)
DMARC失敗時の指示と報告SPF/DKIM が落ちたらどう扱い、誰に報告するかRFC 9989(RFC 7489 を廃止)

SPF(RFC 7208)は、送信元 IP がそのドメインの代理送信を許可されているかを DNS の TXT で宣言します。§3.1 は「SPF レコードは DNS TXT(type 16)としてのみ公開しなければならない」「同一の所有者名に複数の SPF レコードは許されない」と定めています。send.example.com に SPF TXT を2本置くのは仕様違反で、必要なら1本にマージします。

DKIM(RFC 6376)は、ヘッダと本文に秘密鍵で署名し、公開鍵を DNS に置いて検証させます。§3.6.2.1 は「すべての DKIM 鍵は _domainkey という名前のサブドメインに格納される」と定めており、Resend が resend._domainkey を使うのは resend がセレクタだからです。鍵レコードの p= タグは公開鍵データで、RFC 6376 は「必須。値が空の場合はこの公開鍵が失効したことを意味する」と定義しています。値を途中で切って貼ると失効扱いになりうるので、必ず全文をコピーしてください。

DMARC は、SPF と DKIM が失敗したときの扱いを送信側が指示し、結果の報告を受け取る仕組みです。ここが2026年時点で最も知識が古びやすく、DMARC は 2026年5月の RFC 9989(Standards Track)が RFC 7489 と RFC 9091 を廃止しました。少なくとも「DMARC は Informational RFC だから正式な標準ではない」という説明はもう成立しません。

判定条件は Resend のドキュメントが明快です。

An email must pass either SPF or DKIM checks (but not necessarily both) to achieve DMARC compliance and be considered authenticated. A message fails DMARC if both SPF and DKIM fail on the message. — Resend Docs, DMARC

DMARC の判定としては片方通ればよい。しかし後述する Gmail・Yahoo・Microsoft の一括送信者要件は両方の設定を求める——この二段構えを混同しないでください。


Resend が生成する正確なレコード表

example.com をリージョン us-east-1 で追加した場合、Resend が要求するレコードは次のとおりです。ホスト欄は相対名(ドメイン部分を含まない形)で示します。

目的Resend 上の record種別ホスト(相対名)優先度
バウンス/苦情の Return-PathSPFMXsendfeedback-smtp.us-east-1.amazonses.com10
SPF ポリシーSPFTXTsend"v=spf1 include:amazonses.com ~all"
DKIM 公開鍵DKIMTXTresend._domainkeyp=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB...(生成された全文)
クリック/開封追跡(任意)TrackingCNAMElinkslinks1.resend-dns.com
受信(任意)Receiving MXMXinboundinbound-smtp.us-east-1.amazonaws.com10
DMARC(手動。Resend は作らない)TXT_dmarcv=DMARC1; p=none; rua=mailto:dmarcreports@example.com;

この表の本当の要点は、置き場所が4通りに割れていて、しかも DMARC だけ例外だという点です。

レコード置く場所置いてはいけない場所
SPF の MXsend.example.comapex
SPF の TXTsend.example.comapex
DKIM の TXTresend._domainkey.example.comapex、send.
DMARC の TXT_dmarc.example.com(組織ドメイン側)send.
追跡の CNAME追跡サブドメインapex

SPF と DKIM は send.resend._domainkey. の下、DMARC だけは組織ドメインの _dmarc。私が事故ったのはまさにこの非対称で、「Resend のレコードだから同じ階層だろう」と考えて4件を apex にまとめました。send.example.com に DMARC を置いても何も起きません(受信側は _dmarc.example.com しか見ません)。

Resend に追加したドメイン自体がサブドメイン(例:notifications.example.com)の場合、SPF は send.notifications.example.com、DKIM は resend._domainkey.notifications.example.com丸ごとずれます。なお Resend は DMARC レコードを作ってくれません。ドメイン詳細画面に推奨値を表示するだけで、公開は自分の責任です。

DKIM の形状には公式ドキュメント内の食い違いが1つあります。create-domain の API リファレンスの例は DKIM を3本の CNAME で示す一方、get-domain の例・domain.updated Webhook のペイロード・5社ぶんの DNS プロバイダ別ガイドはすべて resend._domainkey の単一 TXT です。裏付けの数からは単一 TXT が現行と考えるのが妥当ですが、確実なのは自分の画面に出た値です。生成されたものをそのまま貼ってください。

API から扱うときの型の実際

テナントごとにドメインを持つ SaaS などでは API で回します。ここで注意が必要なのは、インストール済みの resend@6.4.1 の型定義が公式のコードサンプルより狭いことです。公式の追跡設定ページには resend.domains.create({ name, openTracking, clickTracking, trackingSubdomain }) というサンプルがありますが、v6.4.1 の CreateDomainOptions{ name, region?, customReturnPath? } の3つだけで、trackingSubdomainUpdateDomainsOptions にもありません。型に無いパラメータを渡したいときは、SDK が公開している汎用 HTTP メソッド(resend.post() / resend.patch())で REST の snake_case を直接叩くのが現実解です。

import { Resend } from "resend";

const resend = new Resend(process.env.RESEND_API_KEY);

// SDK は throw しない。必ず { data, error } を分岐する。
const { data, error } = await resend.domains.create({
  name: "notifications.example.com",
  // リージョンは MX の値に埋め込まれる。あとから変更できないので最初に決める。
  region: "ap-northeast-1",
  // Return-Path のサブドメイン。既定は send。63文字以内・英数字とハイフンのみ。
  customReturnPath: "outbound",
});
// 分類はステータスコードではなく error.name で行う。
// 公式ドキュメントと SDK でステータス値が食い違う項目があるため。
if (error) throw new Error(`Resend domains.create failed: ${error.name}`);
// data.records に貼るべき DNS レコードが全部入っている(種別・ホスト・値・優先度)。

// DNS を貼り終えたら検証を起動する。verify は「通った/通らない」を返さず、
// 非同期の検証サイクルを開始するだけ。呼ぶとドメインは一旦 pending になる。
await resend.domains.verify(data.id);

// 結果は get でポーリングするか domain.updated Webhook で受ける。
// レコード単位の status を見れば「どの1本が落ちているか」がわかる。
const { data: domain } = await resend.domains.get(data.id);
console.log(domain?.records.filter((r) => r.status !== "verified"));

型を読んで初めてわかる差分がもう1つあります。v6.4.1 の DomainStatuspending / verified / failed / temporary_failure / not_started の5値で、ドキュメントに載っている partially_verifiedpartially_failed を含みません。送信と受信の capability が分かれた結果ドキュメント側に増えたステータスなので、網羅的に分岐している箇所には未知の値が来る前提のフォールバックを置いてください。Webhook 側の扱いは Resend の Webhook と署名検証・バウンス処理 に分けています。


最大の落とし穴:ホスト名の二重付与

ここが本題です。多くの DNS プロバイダは、ホスト欄に入力した値の末尾に自ドメインを自動補完します。 つまり send.example.com と入力すると、実際に作られるのは send.example.com.example.com です。Resend の画面には FQDN が表示されるので、それをそのままコピペすると壊れます。

Resend は Cloudflare・Vercel・Route 53・GoDaddy・Namecheap の全ガイドで、同一の文言でこう警告しています。

Omit your domain from the record values in Resend when you paste. Instead of send.example.com, paste only send (or send.subdomain if you're using a subdomain).

DKIM も同様に、resend._domainkey.example.com ではなく resend._domainkey だけを貼ります。似た事故は値の側でも起きます。

Problem: Your MX record appears as feedback-smtp.eu-west-1.amazonses.com.example.com instead of feedback-smtp.eu-west-1.amazonses.com Solution: In your DNS provider, add a trailing period (dot) at the end of the record value: feedback-smtp.eu-west-1.amazonses.com.Resend Docs, What if my domain is not verifying?

末尾のドットは「これは FQDN なので加工するな」という DNS の作法です。値にドメインが継ぎ足されていたら、これで直ります。

画面ではなく DNS を実測する

管理画面は「自分が入力したつもりの値」を見せます。信じるべきは世界から見えている実際の応答です。

# SPF の MX(値に自ドメインが継ぎ足されていないか、優先度は何か)
dig +short MX send.example.com
# SPF の TXT(v=spf1 で始まる1本だけが返るか)
dig +short TXT send.example.com
# DKIM の TXT(p= が全文入っているか、途中で切れていないか)
dig +short TXT resend._domainkey.example.com
# DMARC(apex ではなく _dmarc に置けているか)
dig +short TXT _dmarc.example.com
# 二重付与の確認。ここに何か返ってきたら、それが事故のレコード。
dig +short TXT send.example.com.example.com

Resend 公式は nslookup -type=TXT resend._domainkey.example.com のような同等のコマンドを案内しています。さらに自前の DNS 参照ツール dns.email を公開しており、「レコードが公開的に見えているかの確認に使ってください」と複数ページから案内しています。ローカルの DNS キャッシュを疑う場面で便利です。

それでも通らないときのチェック順

Resend が名前を付けている失敗モードを、上から順に潰してください。

  1. 不正なレコード値 — 余計な引用符やスペース、長い値の切り詰め、DKIM レコードに SPF の情報を混ぜる、値を全部コピーしていない。
  2. DNS プロバイダによるドメイン自動付与 — 前述の二重付与。
  3. ネームサーバの競合 — DNS の管理場所が複数(Vercel、Cloudflare、レジストラ)に分かれ、権威を持たない側に貼っている。
  4. リージョン不一致(region-mismatch — ドメインの設定リージョンと MX の値のリージョンが違う。
  5. 複数リージョン(multiple-regions — 別リージョンを指す MX が複数ある。1ドメインの MX はすべて同一リージョンを指す必要がある。
  6. 伝播待ち — 通常15分程度で検証され、最大72時間かかることがある。72時間検出できないと failed になり、ダッシュボードの「Restart verification」で再開できる。

ドメイン詳細画面ではリアルタイムの DNS 検証が走り、問題のあるレコードに赤い波線が出ます。まずそこを見てください。


リージョンとカスタム Return-Path

送信リージョンは4つです——北バージニア(us-east-1)/アイルランド(eu-west-1)/サンパウロ(sa-east-1)/東京(ap-northeast-1。API の既定は us-east-1 です。このリージョンはどこかに独立した設定項目として存在するのではなく、MX の値そのものfeedback-smtp.<region>.amazonses.com)に埋め込まれています。だから「リージョンを変えたつもりで MX を貼り替え忘れた」が region-mismatch として観測されます。事前に知っておくべき制約が2つあります。

  • リージョン変更はインプレースでできません。 公式手順は「現在のドメインを削除する → 同じドメインを新しいリージョンで追加し直す → DNS を更新する」です。その間は送信が止まるので、最初の選択は慎重に。
  • リージョン ≠ データ所在地。 Resend は「リージョン選択が制御するのはメールがどこから送出されるかであり、顧客データがどこに保存されるかではない。メールのメタデータ・ログ・API レコードを含むすべてのアカウントデータは、選択した送信リージョンにかかわらず米国に保存される」と明記しています。「東京リージョンだからデータが国内に留まる」わけではありません。データ所在地の要件がある案件では、要件定義の段階で共有しておかないと後で揉めます。

Return-Path を分ける意味

既定では Return-Path(エンベロープの送信者、バウンスの戻り先)に send サブドメインが使われ、customReturnPath で変更できます。Resend はその用途を「カスタム Return-Path は SPF 認証・DMARC アライメント・バウンス処理に使われる」と説明しています。

ここが SPF と DMARC の関係を理解する鍵です。SPF が認証するのは From: ヘッダのドメインではなく、エンベロープの MailFrom ドメイン、つまり Return-Path 側です。From: noreply@example.com で送っても、SPF が検証するのは send.example.com の SPF レコードになります。この2つが一致しないのに DMARC が通るのは、アライメントが既定で relaxed だからです。RFC のアライメント定義に沿った具体例で言えば、SPF が cbg.bounces.example.com で通り From:payments@example.com のとき、組織ドメインが一致するので relaxed では整合、strict(aspf=s)では不整合になります。

つまり DMARC で aspf=s を指定すると、Resend の既定構成(send. の Return-Path)は SPF アライメントに失敗します。 DKIM 側が整合していれば DMARC 全体としては通りますが片肺です。特別な理由がなければ aspf は既定の relaxed のままにしてください。なお customReturnPath は63文字以内、先頭は英字、末尾は英数字、使えるのは英数字とハイフンのみで、Resend は「testing のような信頼を損なう値は避けてください。メールクライアントによっては受信者に見えます」と注意しています。


SPF の 10 DNS ルックアップ上限

SPF で最も多い運用事故は、既存の SPF に include: を足し続けて上限を超えることです。RFC 7208 §4.6.4 の規定は明快です。

The following terms cause DNS queries: the "include", "a", "mx", "ptr", and "exists" mechanisms, and the "redirect" modifier. SPF implementations MUST limit the total number of those terms to 10 during SPF evaluation, to avoid unreasonable load on the DNS. If this limit is exceeded, the implementation MUST return "permerror".

permerror は「判定不能」であって pass ではありません。SPF が事実上死ぬうえ、壊れるのは追加した1件ではなくそのドメインの SPF 評価全体です。

数える数えない
include: a mx ptr exists の各機構、redirect= 修飾子all ip4: ip6: の各機構、exp= 修飾子

さらに RFC 7208 は「void lookup(空応答または NXDOMAIN が返るルックアップ)は2回までに制限すべきで、超過は permerror」とも定めています。廃止したサービスの include: を消し忘れるとここに引っかかります。ptr 機構は §5.5 の見出しが "ptr (do not use)" で、公開すべきではないと明記されています。Microsoft も高ボリューム送信者向け FAQ で「10 の DNS ルックアップを超えると SPF チェックが失敗する可能性がある。レコードを flatten するかインクルードを減らすツールがある」と案内しています。

ここで Resend 固有の朗報があります。Resend の SPF は send. サブドメインに独立して置かれるため、apex の既存 SPF の10ルックアップ枠を消費しません。 Google Workspace と他の SaaS を apex の SPF に並べているところへ Resend を足したら壊れた、という事故は構造的に起きにくい設計です。

念のため出典を分けておきます。これは Resend の公式ドキュメントが述べている保証ではなく、SPF の評価がドメインごとに独立している(RFC 7208)という仕様と、Resend がレコードを send. に置くという事実から私が導いた帰結です。 公式は10ルックアップ上限との関係に一切触れていません。自分の環境で dig txt send.example.comdig txt example.com の両方を確認してから前提にしてください。ただし2点、注意があります。

  • send.example.comすでに SPF TXT や MX がある場合は別問題です。RFC 7208 §3.2 の「同一所有者名に複数レコードを置いてはならない」に反するため、2本目として追加せず既存を確認して1本にまとめます。MX も既存を削除してから Resend のものを追加します。
  • Resend が生成する SPF は ~all(softfail)です。これを -all に変えることの是非を公式ドキュメントは何も述べていません。推奨も非推奨もされていない領域なので、変更するなら自分で影響範囲を検証してください。
  • サイズ制約も効きます。RFC 7208 は、TXT の character-string の最大長が 255オクテットであること、SPF レコードは照会結果が 512オクテットに収まる程度に小さく保つべきであること、DNS 名と全レコードの合計が 450オクテット未満なら UDP に収まることを述べています。

DMARC の育て方

三段階で上げる

Resend の公式手順は3ステップです。いきなり reject にしない——これが最も重要です。

Step 1  v=DMARC1; p=none; rua=mailto:dmarcreports@example.com;
        ↓ レポートを読み、全送信元が SPF か DKIM で整合していることを確認
Step 2  v=DMARC1; p=quarantine; rua=mailto:dmarcreports@example.com;
        ↓ 迷惑メール送りになっているものが自社の正規送信でないことを確認
Step 3  v=DMARC1; p=reject; rua=mailto:dmarcreports@example.com;
ポリシー受信側の挙動
p=none;すべて通す。DMARC 失敗を観測するだけ
p=quarantine;DMARC 失敗のメールを迷惑メールフォルダへ
p=reject;DMARC 失敗のメールの配送を拒否

Resend の言葉では「quarantinereject を使うのがベストプラクティスですが、メッセージが配信され DMARC を完全に通過していることが分かってから行ってください」。段階を踏む理由は現実的です。自社ドメインから送っているのは Resend だけとは限りません。会計 SaaS、CRM、採用管理、監視ツール、社内の古い cron——p=nonerua を受けると、把握していなかった送信元が並んで出てきます。それを整合させる前に reject にすると、それらが黙って消えます。

rua を受ける口を先に作る

rua は集約レポート(XML 添付のメール)の受け取り先です。RFC 9989 は「タグが無い場合、受信側は集約レポートを生成してはならない(MUST NOT)」と定めています。つまり rua の無い DMARC レコードは、観測手段を持たないまま宣言だけしている状態です。Resend 自身が、DMARC の XML レポートを人間が読める形に変換するオープンソースの DMARC Analyzer を公開しています。ブラウザで使えるホスト版が checkdmarc.email、リポジトリが resend/resend-dmarc-analyzer です。送信元ごとに SPF/DKIM のアライメント結果を見られるので、p=none 期間の読み解きに使えます。Next.js + React Email + Resend で作られており、Resend Receiving を使った自動取り込みで自己ホストもできます。Google の Postmaster Tools も併用してください。

タグ一覧と、いま起きているズレ

ここが「知識が古いと事故る」最大の箇所です。Resend のドキュメントの DMARC パラメータ表には pct が載っていますが、RFC 9989(2026年5月)は pct タグを削除しました。

タグ意味現状
vプロトコルバージョン。v=DMARC1 固定、大文字小文字を区別し必ず先頭現行
p組織ドメインのポリシー。none / quarantine / rejectRFC 9989 では RECOMMENDED に格下げ。省略時は p=none として扱われる
spサブドメインのポリシー現行
np存在しないサブドメインのポリシーRFC 9989 で新設
tテストモード。y / n(既定 nRFC 9989 で新設。pct の実質的な後継
psdそのドメインが公開サフィックスドメインかのフラグRFC 9989 で新設
adkim / aspfDKIM / SPF のアライメントモード。r(relaxed、既定)または s(strict)現行
rua / ruf集約レポート / 失敗レポートの送り先現行(ruf は後述の注意あり)
pctフィルタ対象の割合RFC 9989 で削除。t=y/n に置換

RFC 9989 が pct を削除した理由も明記されています——「運用経験から、pct は 0 か 100(既定値)以外の値では正確に適用されず、実装ごとのばらつきが大きかった」。そのうえで「pct=0 の機能には価値があったので、t(testing)タグを y/n の2値として導入した」としています。t=y は「p=quarantine なら none として、p=reject なら quarantine として適用する」という意味です。なお Resend 自身も「DMARC プロトコルには pctruf の両方が含まれるが、メールボックスプロバイダに広く従われてはいない。これらの設定は尊重されない場合がある」と正直に書いており、Microsoft も「RUA は DMARC レコードに指定されたアドレスへ送るが、RUF を送る予定はない」と明言しています。ruf に依存した設計はしないでください。

RFC 9989 のもう1つの大きな変更は、組織ドメインの決定方法が Public Suffix List から「DNS Tree Walk」に置き換わったことです。ラベルを左から削りながら _dmarc. を引いていく方式で、8ラベルを超えるドメインでも DNS クエリが8回を超えないショートカットが組み込まれています。深いサブドメインを使っている場合、どの _dmarc が効くかの解釈が RFC 7489 時代と変わりうると認識しておいてください。

p は組織ドメイン、sp はそのサブドメイン、np は存在しないサブドメインに効きます。送信を notifications.example.com に寄せているなら、apex 側を p=reject で締め、送信サブドメインだけを段階的に上げるという組み方ができます。BIMI(受信箱にロゴを出す仕組み)を狙う場合は追加の制約があり、Resend は「サブドメインで BIMI を使う場合、ルートまたは apex ドメイン側にもサブドメインと同様に p=quarantine または p=reject の DMARC ポリシーが必要。無いとサブドメインは BIMI ロゴの表示要件を満たさない」と明記しています。


Gmail・Yahoo・Microsoft の一括送信者要件

2024年2月以降、主要な受信側は送信者要件を明文化しました。3社は要件が微妙に違い、しかも広く引用されている数字が間違っていることがあります。 一次情報だけで整理します。

Gmail(個人アカウント)Yahoo / AOLOutlook.com(コンシューマ)
一括送信者の閾値個人 Gmail 宛に24時間で約5,000通以上。主ドメイン単位で合算。一度該当すると恒久的数値の公表を明確に拒否Microsoft コンシューマ向けに5,000通以上、同一の 5322.From ドメイン
全送信者への要求SPF または DKIMSPF または DKIM個別の規定なし
一括送信者への要求SPF かつ DKIM かつ DMARC(p=none 可)SPF かつ DKIM かつ DMARC(最低 p=none、かつ DMARC が pass すること)SPF かつ DKIM かつ DMARC(最低 p=none
アライメントFrom: が SPF か DKIM の組織ドメインと整合(一方でよい)同左。relaxed で可と明記SPF と DKIM の少なくとも一方が 5322.From と整合
スパム率0.10% を目安、0.30% には決して到達させない0.3% 未満(受信箱に配信された分で算出)数値は非公表
ワンクリック配信停止マーケティング/購読メールに必須。RFC 8058 のヘッダのみが有効で mailto もランディングページも不可必須。RFC 8058 が強く推奨、mailto も許容「機能する配信停止リンク」は推奨事項
失敗時4.7.2x でレート制限 → 5.7.2x でブロック迷惑メール送りまたは拒否迷惑メール送り、そして 550 5.7.515 で拒否

広く流通している誤りを潰しておきます。

  • 「Yahoo の一括送信者は5,000通/日」は Yahoo の公式見解ではありません。 Yahoo の FAQ は「一括送信者とは相当量のメールを送る送信者を指す。我々は量の閾値を指定しない」と明言しています。5,000通/日を公表しているのは Google と Microsoft です。
  • 「スパム率0.3%が Gmail の要件」だけを覚えるのは危険です。 同じページの監視セクションは「Postmaster Tools のスパム率を 0.10% 未満に保ち、0.30% 以上には決して到達させないこと」と書いています。0.30% は要件というより崖で、超えると救済(mitigation)の対象外になります。
  • Gmail の一括送信者ステータスは恒久的です。 「一度でも該当した送信者は恒久的に一括送信者として分類される。送信習慣を変えても変わらない」と FAQ にあります。
  • Gmail の送信者ガイドラインは Google Workspace 宛には適用されません。 対象は @gmail.com / @googlemail.com の個人アカウント宛です。
  • 日本の読者向けの重要な注意:Yahoo は「Yahoo! JAPAN は別法人であり、その方針について我々は述べられない」と明言しています。 上表の Yahoo 欄を Yahoo! JAPAN に当てはめないでください。

DKIM 鍵長にはねじれがあります。Gmail は「個人 Gmail 宛の送信には 1024 ビット以上の DKIM 鍵が必要。セキュリティ上の理由から、DNS プロバイダが対応していれば 2048 ビットを推奨」としています。一方 Resend は 1024 ビットで署名し、2048 ビットには対応しないと明言し、RFC 8301 §3.2 が定める検証者の対応必須最小長が1024ビットであること、Gmail・Outlook・Yahoo・Apple のいずれも1024ビット署名を受理することを根拠に挙げています。ただし同 §3.2 は署名者に2048ビット以上を SHOULD としており、Resend の方針はこの推奨とは異なる立場です。要件として2048ビットが必要な組織は、導入前に Resend に確認してください。

Resend 側のアカウントレベルのガードレールも別に存在します。バウンス率は4%未満、スパム率は0.08%未満を維持する必要があり、超えると送信が一時停止されることがあります。上表の受信側の閾値(Gmail が崖とする0.30%、Yahoo の0.3%)とはスコープが違う——受信側が自分で測る苦情率と、Resend のアカウントポリシー——ので混ぜないでください。バウンスと苦情の受け取りは Resend の Webhook と署名検証・バウンス処理、ワンクリック配信停止の実装は 一括送信・予約送信・購読管理 にまとめています。


サブドメイン戦略:トランザクションとマーケティングを分ける

Resend の推奨は一貫しています——ルートドメインではなくサブドメインから送る。理由は2つです。

Reputation Isolation — Things happen. Maybe someone decides to DDOS your signup page and you get stuck sending tens of thousands of bounced verification emails to burner addresses. … If your root domain ends up with a jeopardized reputation, it can be a long road to recovery. Sending Purpose Transparency — A password reset email carries higher priority than a monthly product update. … By segmenting your sending purposes by subdomain, you give Inbox Providers clear indication of where to place your emails.

実務的な分割の型は次のようになります。

用途サブドメイン例追跡Enforced TLS
認証・パスワードリセット・領収書account.example.com切る検討する価値あり
通知・アラートnotifications.example.com切る任意
ニュースレター・お知らせupdates.example.com入れる任意

Resend も同じ例を挙げています——「ニュースレターは開封・クリック追跡を有効にしつつ、パスワードリセットのような重要なトランザクションメールでは追跡を無効のままにできます」。同一ルートドメインの複数サブドメインを追加・検証でき、それぞれ個別に構成と検証が必要です。注意点を3つ。

  • ブランドに似せた別ドメインは使わない。 Resend は getacme-mail.comacme-alerts.com のような「ブランド隣接ドメイン」を名指しで避けるよう書いています。スパムフィルタに疑わしく見え、フィッシングやなりすましとして扱われうるためです。
  • 新しいサブドメインは新しいレピュテーション。 Resend が公開するウォームアップ表では、新規ドメインは1日目に最大150通、7日目で最大2,000通が目安です(既存ドメインの移行にはもっと速い表があります)。ウォームアップ中もバウンス率4%未満・スパム率0.08%未満を維持し、悪化したら速度を落として原因を調べるよう案内されています。
  • プランごとのドメイン数上限が、この分割の可否を決めます。 2026年8月時点の公式料金ページでは独自ドメイン数が Free = 1、Pro = 10、Scale = 1,000、Enterprise = 要相談です。サブドメインは1つずつ独立したドメインとして追加・検証する以上、上の3分割は独自ドメイン1つの無料プランでは成立しません。料金と上限は変わるので、サブドメインを増やす設計にする前に公式の料金ページで最新値を確認してください。 無料プランの送信上限は、トランザクションが1日100通・月3,000通(受信メールも同じ枠を消費)、マーケティングが月あたり最大1,000コンタクトへ無制限です。

開封・クリック追跡の代償

2024年頃の知識で最も更新が必要なのがここです。開封・クリック追跡は全ドメインで既定オフであり、次の2条件が揃わないと動きません。

  1. ドメインの open_tracking または click_tracking が有効であること。
  2. 追跡サブドメイン(例:links.example.com)が設定され、検証に成功していること

追跡サブドメインは CNAME で links1.resend-dns.com を指します。「共有の追跡ドメインは、書き換えられたリンクをスパムフィルタが疑わしいと判定しうるため到達率を損なう可能性がある」というのが Resend 自身の説明で、ダッシュボードの Deliverability Insights も共有ドメインの利用を改善項目として指摘します。仕組みそのものが到達率を下げます。開封追跡は1x1 の透明 GIF を埋め込み、その画像がダウンロードされたことで開封を検出します。クリック追跡は本文中の全リンクを追跡サブドメイン経由に書き換え、リダイレクトの途中でクリックを記録します。その両方が受信側に「マーケティングメールの信号」として読まれます。

Link and open tracking can be great for marketing emails but not for transactional emails. This kind of tracking can actually hurt your deliverability. … Also, Supabase has noted that link tracking is known for corrupting verification links, making them unusable for your users. — Resend Docs, Supabase Auth の到達率

リンク書き換えが検証リンクを壊すのは、マジックリンクやワンタイムトークンを送るサービスにとって致命的です。Resend の「Delivered なのに届かない」ページも、対処法の1つに「開封・クリック追跡をオフにする」を挙げています。

開封率という数字は正確ではない

そもそも開封率は測定値として信頼できません。Resend が挙げる理由は4つです。

  • Gmail のクリッピング — 102KB を超えるメッセージは切り詰められ、受信者が全体を表示しない限り開封としてカウントされない。
  • 画像を既定でダウンロードしない受信箱、企業ファイアウォールによるブロックやキャッシュ。
  • 配信前にメールを開く受信箱 — マルウェアスキャンやプライバシー保護(Apple Mail のプライバシー保護)が、読まれていないのに開封イベントを発生させる。
  • プレーンテキストのみのメールは追跡できない — 開封追跡は1x1 画像に依存するため。

Resend の結論は「開封追跡は、ユーザーがコンテンツに関与しているかを検出する統計的に正確な方法ではありません」。そして「配信されるかどうかには影響しないが、受信箱への配置には影響する可能性が高い」。代替として挙げられているのは、クリックを見ること、そして受信箱の外(ページ訪問やコンバージョン)で測ることです。

一度作ると消せない

運用上の罠がもう1つ。追跡サブドメインは作成後、変更はできても削除はできません。 送信済みメールのリンクを壊さないための仕様です。したがって、変更するとレコード表に有効な CNAME と非有効な CNAME が並びますが、古いほうを消してはいけません。変更後は新しいレコードの検証が必要で、済むまでは以前の値が使われます。そして追跡サブドメインを設定したドメインを削除すると、Resend が用意したプロキシも削除され、そのサブドメインを使う既存メールのリンクが壊れます。リンクを生かしたい場合は、削除前に Resend の追跡 DNS レコードを指す自前のプロキシを用意する必要があります。

プライバシーと国内法の視点

開封追跡は、受信者が意識しないまま「いつ開いたか」を記録する仕組みです。何を記録し何に使うのかを自社のプライバシーポリシーに書けるかどうかを、導入の判断基準にしてください。個人情報保護法上の位置づけは取得する項目や他情報との結合可能性で変わるため、ここで一律の断定はしません。広告宣伝メールを送るなら、これとは別に特定電子メール法のオプトイン規制と表示義務(法第4条の5項目)がかかります。条文の射程・同意記録の保存期間・罰則・フッターの実装例は 一括送信・予約送信・購読管理 にまとめたので、マーケティングメールを設計するならそちらを見てください。ドメイン認証とは別レイヤーの話ですが、着手のタイミングは同じです。


「Delivered なのに届いていない」の切り分け

実務で最も相談を受ける状況です。まず Delivered という表示が何を意味するかを正確に理解してください。

When an email is sent, it is marked as Delivered once the recipient server accepts it with a 250 OK response. However, the server can then direct the email to the inbox, queue it for later, route it to the spam folder, or even discard it. … Inbox Providers do not share any information on how the messages are later filtered. — Resend Docs, Delivered なのに受信者に届いていない場合

Delivered は「受信サーバが受け取った」であって「受信箱に入った」ではありません。 その後の仕分けは受信側の内部処理で、Resend には通知されません。ここを取り違えると送信基盤をいくら調べても答えが出ません。

[1. ログを見る] Resend のダッシュボードでそのメールのステータスは?
  ├─ Bounced ────→ Permanent なら宛先が存在しない。リストから外す
  │                 Transient なら容量超過・サイズ超過・内容拒否など。再送設計へ
  ├─ Complained ─→ 苦情。抑制リストに入り、以後そのアドレスへは送られない
  ├─ 送信自体が失敗 → error.name で分類(403 は差出人ドメインの不一致を疑う)
  └─ Delivered ──→ 2 へ

[2. 認証を見る] 受信メールのヘッダに spf=pass / dkim=pass / dmarc=pass はあるか?
  ├─ どれか fail ─→ 3 へ
  └─ すべて pass ─→ 4 へ

[3. DNS を実測する] dig で send. / resend._domainkey. / _dmarc. を引き、
  二重付与・値の切り詰め・リージョン不一致を潰す

[4. 内容とレピュテーションを見る]
  ├─ リンクのドメインが送信ドメインと一致しているか
  ├─ プレーンテキスト版(text)を入れているか
  ├─ 差出人が no-reply になっていないか
  ├─ 本文が 102KB を超えていないか(Gmail でクリップされる)
  ├─ 開封・クリック追跡を切ったらどうか
  └─ Postmaster Tools でドメインのレピュテーションを確認

[5. 受信側の事情を疑う]
  ├─ 企業のメールセキュリティ(Mimecast / Proofpoint / Barracuda 等)の隔離
  ├─ 個人のフィルタ設定、プロモーションタブ、削除済みフォルダ
  └─ 見つかったら「迷惑メールではない」を押してもらい、ドメインを許可リストへ

抑制リスト(Suppressions)についても知っておいてください。バウンスや苦情で追加されたアドレスはチーム全体に適用され、すべてのドメイン・サブドメインでスキップされます。「送ったはずなのにログに何も無い」ときはここを疑ってください。なお Gmail / Google Workspace は苦情(complained)イベントを返さないことで知られており、Gmail 宛の苦情は Resend からは見えません。送信そのものが 403 で失敗する典型は2つです。resend.dev のテスト用ドメインは自分のアカウントのメールアドレス宛にしか送れません。そして sending.domain.com を検証したのに from@domain.com にすると、ドメイン不一致で 403 になります。検証したドメインと from のドメインは、サブドメインまで含めて完全に一致させてください。

エラーの分類とリトライ設計は Resend の冪等性・リトライ・エラー設計、Route Handler の実装は Next.js App Router での Resend 実装 に分けています。私が冒頭の障害を根治したときも、DNS を直したうえで送信元のフォールバックとリトライと冪等キーを入れました。DNS はいつかまた壊れるので、壊れてもリードを落とさない層を送信コード側に持たせておく、という判断です。


チェックリスト

DNS を触ったら、この順で確認してください。

  • SPF の MX と TXT が send.(またはカスタム Return-Path のサブドメイン)にある
  • DKIM の TXT が resend._domainkey. にあり、p= の値が途中で切れていない
  • DMARC の TXT が _dmarc.(組織ドメイン側)にある。send. ではない
  • dig +short TXT send.example.com.example.com何も返さない(二重付与なし)
  • MX の値に自ドメインが継ぎ足されていない。値のリージョンとドメインのリージョンが一致
  • send. に SPF TXT や MX が二重に存在しない
  • apex の既存 SPF の DNS ルックアップ数が10以内(include: の棚卸し)
  • DMARC は p=none + rua から始めており、レポートを実際に読んでいる
  • aspf=s を設定していない(Resend の既定構成では SPF アライメントが落ちる)
  • トランザクション用ドメインで開封・クリック追跡がオフ。追跡を使うなら古い CNAME を消していない
  • from のドメインが、検証したドメインとサブドメインまで完全一致
  • プレーンテキスト版(text)を入れている。差出人は no-reply ではない
  • バウンス率4%未満・スパム率0.08%未満を監視する手段がある

まとめ

ドメイン認証は、一度通せば普段は意識しない領域です。だからこそ壊れたときに原因を探す場所を間違えます。私は Route Handler のコードを何度も読み返し、実際に壊れていたのは DNS のホスト名でした。要点を3つに畳むとこうなります。

  • 配置が4通りに割れていて、DMARC だけ例外。 SPF は send.、DKIM は resend._domainkey.、DMARC は組織ドメインの _dmarc.。ホスト欄には相対名だけを入れ、dig で FQDN を実測して確かめる。
  • DMARC は宣言ではなく運用。 p=none + rua で観測し、把握していなかった送信元を1つずつ整合させてから上げる。RFC 9989 で pct は無くなり t=y/n になった。
  • 追跡は既定でオフのままにする。 カスタム追跡サブドメインが必須で、リンク書き換えは検証リンクを壊しうる。開封率はそもそも統計的に正確ではない。

サービスの選定段階から見直すなら Resend と SendGrid・SES・Postmark の比較 もあわせて読んでください。まずは自分のドメインに対して dig +short TXT send.<あなたのドメイン>.<あなたのドメイン> を1回打ってみてください。何か返ってきたら、それが今日直すべきレコードです。

この記事は Resend 公式ドキュメント(Domains / DMARC / Tracking / Deliverability、2026年8月時点)と RFC 7208・RFC 6376・RFC 8301・RFC 9989、および Google・Yahoo・Microsoft の送信者要件ページに基づき、本番運用の判断軸を加えて再構成したものです。仕様・上限・料金は更新されるため、本番採用時は各公式ページで最新値をご確認ください。

よくある質問

DNS レコードを設定したのに Resend のドメイン検証が通りません。まず何を疑うべきですか?
ホスト名です。Resend の SPF(MX と TXT)は send サブドメイン、DKIM は resend._domainkey に置きます。多くの DNS プロバイダはホスト欄にドメインを自動補完するため、send.example.com と入力すると send.example.com.example.com という別のレコードが作られます。公式の指示どおり send / resend._domainkey だけを入力し、dig で FQDN を実測して確認してください。72時間検出できないとステータスは failed になります。
SPF と DKIM は両方必須ですか?
DMARC の判定としては片方通れば合格です。Resend のドキュメントも「SPF か DKIM のどちらかを通れば DMARC 準拠になり、両方失敗したときだけ DMARC 失敗になる」と明記しています。ただし Gmail・Yahoo・Microsoft の一括送信者要件は SPF と DKIM の両方の設定を求めます。Resend でドメインを検証すると両方が自動で構成されるため、実務上は「両方立てて、DMARC の判定は片方通ればよい」と理解してください。
DMARC をいきなり p=reject にしてよいですか?
やめてください。Resend の公式手順は p=none で観測し、rua でレポートを受け取り、配信と認証が確実に通っていることを確認してから quarantine、reject と上げる三段階です。会計 SaaS や CRM など把握していない送信元が同じドメインを使っていることは珍しくなく、いきなり reject にするとそれらが黙って消えます。まず rua を受ける口を用意するところから始めてください。
開封トラッキングは有効にすべきですか?
トランザクションメールでは切ってください。Resend は既定で無効にしており、ドキュメントでも開封率の無効化を推奨しています。理由は2つで、1x1 ピクセルとリンク書き換えが受信側にマーケティングメールの信号として読まれること、そして Apple Mail のプライバシー保護や画像ブロックのせいで開封数がそもそも統計的に正確ではないことです。Supabase はリンク追跡が検証リンクを壊すことでも知られていると Resend が引用しています。
ルートドメインとサブドメイン、どちらから送るべきですか?
サブドメインです。Resend が挙げる理由は2つで、レピュテーションの隔離(問題が起きたサブドメインだけを切り離せる。ルートドメインの評判が傷つくと回復に長くかかる)と、送信目的の明示(パスワードリセットと月次のお知らせを別サブドメインにすると受信側が仕分けしやすい)です。ブランドに似せた別ドメインを使うのは逆効果で、フィッシングと誤認されます。
Resend の DKIM は 1024 ビットですが問題ありませんか?
Gmail は個人 Gmail 宛の送信に 1024 ビット以上を要求し、2048 ビットを推奨しています。Resend は 1024 ビットで署名し 2048 ビットには対応しないと明言しています。RFC 8301 は署名者に 1024 ビット以上を MUST、2048 ビット以上を SHOULD としており、ここは要求と推奨がねじれています。Resend は 2048 が必要なら相談してほしいと書いているので、コンプライアンス要件がある場合は導入前に確認してください。

参考文献

友田

友田 陽大

経済産業大臣賞 受賞プロダクト開発者。TypeScript + Python + AWS で、SaaS・業界DX・実用レベルの生成AI(RAG)を、要件定義からインフラ・運用まで一人で完遂します。

メールが迷惑メールに入る・届かないでお困りですか?

到達率の改善とメール配信サービスの技術選定の技術顧問

「Gmail にだけ届かない」「DMARC を強めたら正規のメールまで弾かれた」「Amazon SES と Resend のどちらを選ぶべきか」——認証レコードの実地調査(SPF の10 DNS ルックアップ上限・DKIM・DMARC アライメント)から、送信ドメインの分離設計、Gmail / Yahoo / Microsoft の一括送信者要件への適合、ベンダー選定と送信量ベースのコスト試算まで、技術顧問として一緒に決めます。

プロジェクト単位(請負)・技術顧問のどちらにも対応可能です。まずは30分の無料技術相談から。

最短ルート:カレンダーから直接予約

相談内容が固まっている方は、フォーム送信よりその場で日程を確定する方がスムーズです。下記から空き時間をお選びください。

  • 30分のオンライン無料相談
  • Google Meet / Zoom / Microsoft Teams
  • NDA 商談前締結可・無理な営業はいたしません
無料相談の空き枠を予約する

あわせて読みたい