なりすましメールを防ぐSPF・DKIM・DMARCの仕組みをゼロから解説
自分のWebサービスからメール通知を送る。一見シンプルですが、その裏には「このメールは本当にあなたが送ったものですか?」という認証の仕組みが必要です。
この記事では、Webサービス開発でメール送信機能を実装する際に避けて通れないSPF、DKIM、DMARCについて、手紙の郵送にたとえながら解説します。
この記事のゴール
- メール認証(SPF/DKIM/DMARC)が「なぜ必要か」を理解できる
- 各技術が「何をしているか」をイメージできる
- 実際のDNSレコードを見て「何が書いてあるか」を読めるようになる
- 公式ドキュメントを読むための前提知識が身につく
目次
- そもそもなぜメール認証が必要なのか
- メール送信の仕組み(超基本)
- SPFとは
- DKIMとは
- DMARCとは
- 3つの関係をまとめる
- 実践: Resend + Cloudflareでメール認証を設定する
- DNSレコードを読んでみよう
- よくある疑問
- まとめ
1. そもそもなぜメール認証が必要なのか
メールは「送信者を偽れる」仕組みで動いている
これは意外かもしれませんが、メールの送信プロトコル(SMTP)は、送信者のアドレスを自由に書き換えられるようにできています。
紙の手紙を思い浮かべてください。封筒の「差出人」欄に何を書くかは、書く人の自由ですよね。「東京都千代田区 田中太郎」と書いても、実際に田中太郎さんかどうかは誰も確認しません。
メールもまったく同じです。From: support@amazon.co.jp と書いてメールを送ることは、技術的には誰にでもできてしまいます。
なりすましメールの被害
この仕組みを悪用したのが**なりすましメール(スプーフィング)**です。
From: support@your-bank.co.jp
件名: 【重要】お客様のアカウントが凍結されました
以下のリンクからログインして確認してください。
https://fake-bank-site.com/login ← 偽サイト
受信者はメールの差出人を見て「銀行からのメールだ」と思い込み、偽サイトにパスワードを入力してしまいます。これがフィッシング詐欺です。
Webサービス開発者にとっての問題
あなたが開発したWebサービスからメールを送る場合、2つの問題が発生します。
| 問題 | 説明 |
|---|---|
| 迷惑メールに振り分けられる | 認証がないメールはGmailやOutlookに「怪しいメール」と判断される |
| ドメインが悪用される | 認証がないと、第三者があなたのドメインを使って偽メールを送れてしまう |
SPF・DKIM・DMARCは、この両方の問題を解決する仕組みです。
2. メール送信の仕組み(超基本)
メール認証を理解するために、まずメールがどう送られるかを簡単に見ましょう。
送信者のアプリ
|
v
[送信メールサーバー(SMTP)] ← 「このサーバーからメールを送るよ」
|
v
インターネット
|
v
[受信メールサーバー] ← 「このメール、本物?」
|
v
受信者のメールボックス(Gmail等)
受信メールサーバーが「このメール、本物?」と判断するときに、**DNS(Domain Name System)**に設定された情報を参照します。
DNSとは?
DNSは「インターネットの電話帳」です。ドメイン名(例: locatripjapan.com)に対して、さまざまな情報を紐づけて公開できます。
| DNSレコードの種類 | 役割 | 例 |
|---|---|---|
| A | ドメインのIPアドレス | 93.184.216.34 |
| MX | メールの送り先サーバー | mail.example.com |
| TXT | テキスト情報(何でも書ける) | SPFやDKIMの設定もここ |
| CNAME | 別のドメインへの転送 | alias.example.com |
SPF、DKIM、DMARCの設定は、主にTXTレコードとしてDNSに登録します。
3. SPFとは
一言で言うと
「このドメインからメールを送っていいサーバーの一覧表」 をDNSに公開する仕組み。
手紙にたとえると
あなたの会社(example.com)の受付に「郵便物を出していいのは、郵便局Aと宅配便Bだけです」という掲示を出すようなもの。
受け取った側は、掲示を確認して「この手紙は郵便局Aから来ている。OK、本物だ」と判断できる。
仕組み
1. 送信サーバー(IP: 203.0.113.5)が hello@example.com からメールを送信
2. 受信サーバーが example.com のDNSを問い合わせる
3. TXTレコードに「v=spf1 ip4:203.0.113.5 ~all」が見つかる
4. 送信サーバーのIP(203.0.113.5)が許可リストに含まれている → OK!
SPFレコードの読み方
v=spf1 include:amazonses.com ~all
| 部分 | 意味 |
|---|---|
v=spf1 | 「これはSPFレコードです」という宣言 |
include:amazonses.com | Amazon SES(メール送信サービス)のサーバーを許可 |
~all | 上記以外のサーバーからのメールは「怪しい」と判定(ソフトフェイル) |
~allの種類:
| 記述 | 意味 | 厳しさ |
|---|---|---|
+all | 全て許可 | 緩い(非推奨) |
~all | 許可リスト以外は怪しいと判定 | 標準的 |
-all | 許可リスト以外は拒否 | 厳しい |
SPFの限界
SPFには1つ大きな弱点があります。メールが転送されると壊れることです。
メールが別のサーバーを経由して転送されると、送信元のIPアドレスが変わってしまい、SPFチェックに失敗します。この弱点を補うのがDKIMです。
4. DKIMとは
一言で言うと
「メールに電子署名(ハンコ)を押して、改ざんされていないことを証明する」 仕組み。
手紙にたとえると
あなたの会社が持つ特別な印鑑(秘密鍵)で封蝋をして手紙を送る。
受け取った側は、あなたの会社が公開している印鑑の型(公開鍵)と照合して「確かにこの会社が封をした手紙だ。途中で開けられてもいない」と確認できる。
仕組み
DKIMは公開鍵暗号方式を使っています。
[送信側]
1. メールの内容からハッシュ(指紋)を生成
2. 秘密鍵でハッシュを暗号化(= 電子署名)
3. 署名をメールヘッダーに添付して送信
[受信側]
4. DNSから送信者の公開鍵を取得
5. 署名を公開鍵で復号してハッシュを取り出す
6. メール本文から同じ方法でハッシュを生成
7. 2つのハッシュを比較 → 一致すれば本物!
公開鍵暗号方式とは?
少し脱線しますが、DKIMの根幹なので簡単に説明します。
鍵が2つ1組になっている暗号方式です。
| 鍵 | 誰が持つ | 役割 |
|---|---|---|
| 秘密鍵 | 送信者だけが持つ | 署名を作る(暗号化) |
| 公開鍵 | 誰でも見られる(DNS) | 署名を検証する(復号) |
イメージとしては:
- 秘密鍵 = 自分だけが持つ印鑑
- 公開鍵 = 印鑑証明書(誰でも役所で取得できる)
秘密鍵で押した印鑑は、公開鍵(印鑑証明書)で「本物の印鑑だ」と確認できます。逆に、公開鍵からは秘密鍵を作れないので、偽造は不可能です。
DKIMレコードの読み方
resend._domainkey.locatripjapan.com TXT "p=MIGfMA0GCSqGSIb3DQEBA..."
| 部分 | 意味 |
|---|---|
resend._domainkey | セレクタ名。どのサービスの鍵かを区別する |
_domainkey | 「これはDKIM用の公開鍵です」という目印 |
p=MIGfMA0... | 公開鍵の本体(Base64エンコード) |
SPFとDKIMの違い
| 項目 | SPF | DKIM |
|---|---|---|
| 検証対象 | 送信サーバーのIPアドレス | メール本文の内容 |
| たとえ | 「誰が郵便を出していいか」の許可リスト | 「封蝋」で中身が改ざんされていないことを証明 |
| 転送に強い? | 弱い(IPが変わると壊れる) | 強い(署名はメールに付いたまま) |
| 設定場所 | DNS TXTレコード | DNS TXTレコード |
SPFとDKIMは補い合う関係です。 どちらか一方ではなく、両方設定するのが基本です。
5. DMARCとは
一言で言うと
「SPFとDKIMの結果をどう扱うか」のルールを公開する仕組み。
手紙にたとえると
「もし印鑑(DKIM)も郵便許可(SPF)も確認できなかった手紙が届いたら、捨ててください。そして、怪しい手紙があったら admin@example.com に報告してください」
という指示書を受付に貼り出すようなもの。
DMARCの3つの役割
- SPFとDKIMの結果に基づいてメールをどう処理するか指定する
- レポートを受け取れる(誰があなたのドメインでメールを送っているか把握)
- SPFとDKIMを「束ねる」ポリシーとして機能する
DMARCレコードの読み方
_dmarc.example.com TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"
| 部分 | 意味 |
|---|---|
v=DMARC1 | 「これはDMARCレコードです」という宣言 |
p=quarantine | 認証に失敗したメールの処理方法 |
rua=mailto:... | レポートの送り先メールアドレス |
p=(ポリシー)の種類:
| 値 | 意味 | 厳しさ |
|---|---|---|
none | 何もしない(監視のみ) | 緩い(最初はこれ推奨) |
quarantine | 迷惑メールフォルダに振り分け | 中間 |
reject | 受信を拒否 | 厳しい |
6. 3つの関係をまとめる
メールが届いた!
|
v
[SPFチェック] → 送信サーバーは許可リストに入っている?
|
v
[DKIMチェック] → 電子署名は正しい? 内容は改ざんされていない?
|
v
[DMARCチェック] → SPFとDKIMの結果を踏まえて、どう処理する?
|
├── 両方OK → 受信トレイへ
├── 片方失敗 → DMARCポリシーに従う(quarantineなら迷惑メールへ)
└── 両方失敗 → DMARCポリシーに従う(rejectなら受信拒否)
3つのまとめ表
| 技術 | 役割 | たとえ | 設定場所 |
|---|---|---|---|
| SPF | 送信サーバーの許可リスト | 「郵便を出していいのはこの業者だけ」 | DNS TXTレコード |
| DKIM | メールの電子署名 | 「封蝋」で改ざん防止 | DNS TXTレコード + 送信サーバー |
| DMARC | ポリシーとレポート | 「怪しい手紙の処理方法を受付に指示」 | DNS TXTレコード |
7. 実践: Resend + Cloudflareでメール認証を設定する
ここからは、実際にWebサービスのメール送信で設定した手順を紹介します。
背景
筆者は海外旅行者向けのカスタム旅行プランサービスを開発しています。ユーザーへのメール通知にメール送信サービスResendを使用し、ドメイン管理にはCloudflareを使っています。
なぜこの設定が必要?
Resendのデフォルトでは onboarding@resend.dev というテスト用アドレスからメールが送られます。これは開発中は問題ありませんが、本番運用では以下の問題があります。
- 受信者に「知らないアドレスからのメール」と不信感を与える
- Gmailなどで迷惑メールに振り分けられやすい
- ブランドの信頼性が損なわれる
自分のドメイン(例: hello@locatripjapan.com)から送信するには、ドメインの認証が必要です。
設定手順
ステップ1: Resendにドメインを追加
Resendダッシュボードの Domains > Add Domain で自分のドメインを追加します。
ステップ2: 表示されたDNSレコードを確認
Resendが3つのDNSレコードを表示します。
| Type | Name | 役割 |
|---|---|---|
| TXT | resend._domainkey | DKIM公開鍵(メールの署名検証用) |
| MX | send | メールの送信経路(Resendのサーバー) |
| TXT | send | SPF(送信サーバーの許可リスト) |
ステップ3: CloudflareにDNSレコードを追加
Resendが Auto configure オプションを提供している場合、ワンクリックで自動設定されます。Cloudflareを利用している場合はこれが最も簡単です。
手動の場合は、Cloudflareダッシュボードの DNS > Records > Add record から、Resendが表示した3つのレコードを1つずつ追加します。
注意: Proxy status(プロキシ状態)は DNS only(グレーの雲マーク)にしてください。メール関連のDNSレコードはCloudflareのプロキシを通すと正常に動作しません。
ステップ4: Resendでドメイン認証を確認
DNSレコード追加後、Resendのダッシュボードでドメインのステータスが Verified に変わります。DNS反映に最大48時間かかることがありますが、Cloudflareの場合は通常数分で完了します。
ステップ5: アプリケーション側の設定
メール送信元アドレスを環境変数で管理し、本番では認証済みドメインを使用します。
// 環境変数で送信元を管理(本番はカスタムドメイン、開発はResendテスト用)
const FROM_EMAIL = process.env.FROM_EMAIL || 'App <onboarding@resend.dev>'
# .env(本番)
FROM_EMAIL=LocaTripJapan <hello@locatripjapan.com>
8. DNSレコードを読んでみよう
実際に設定したDNSレコードを1つずつ読み解いてみましょう。
DKIM(TXTレコード)
Type: TXT
Name: resend._domainkey
Content: "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD8Zi..."
resend= セレクタ名(Resendが使う鍵の識別子)_domainkey= 「DKIM用の公開鍵」を示す決まり文句p=MIGf...= 公開鍵そのもの(Base64エンコードされたRSA公開鍵)
受信サーバーはこの公開鍵を使って、メールに付いた署名を検証します。
SPF(TXTレコード)
Type: TXT
Name: send
Content: "v=spf1 include:amazonses.com ~all"
send= サブドメイン(send.locatripjapan.comからメールを送る設定)v=spf1= SPFバージョン1include:amazonses.com= Amazon SES(Resendが内部で使っているメール配信基盤)のサーバーを許可~all= それ以外は「怪しい」として扱う
MX(MXレコード)
Type: MX
Name: send
Content: feedback-smtp.ap-northeast-1.amazonses.com
Priority: 10
MX= メールの配送先を指定するレコードsend=send.locatripjapan.comサブドメインのメール設定feedback-smtp...= バウンスメール(送信失敗の通知)の受け取り先Priority: 10= 優先度(数字が小さいほど優先)
9. よくある疑問
Q. SPFだけ設定すればDKIMはいらない?
両方必要です。 SPFはメール転送に弱く、DKIMはIP検証ができません。2つを組み合わせることで、お互いの弱点をカバーします。Gmailなどの主要メールサービスは、SPF・DKIM両方の設定を推奨しており、どちらかが欠けるとスパム判定されやすくなります。
Q. DMARCは設定しなくても大丈夫?
MVPの段階では必須ではありません。ただし、2024年2月からGmailとYahoo!メールが1日5,000通以上送信するドメインにDMARC設定を義務化しています。サービスが成長したら設定しましょう。
参考: Google Workspace - メール送信者のガイドライン
Q. Cloudflareのプロキシ(オレンジの雲)をONにしたらダメ?
メール関連のDNSレコードは**DNS only(グレーの雲)**にしてください。CloudflareのプロキシはHTTPトラフィック用であり、メールプロトコル(SMTP)を通さないため、プロキシをONにするとメール認証が壊れます。
Q. 設定後、反映されるまでどのくらいかかる?
DNSレコードの反映(プロパゲーション)には最大48時間かかりますが、Cloudflareの場合は通常数分から数十分で完了します。Resendのダッシュボードで Verify ボタンを押して確認できます。
Q. 個人開発でも設定すべき?
はい。 設定しないとGmailが迷惑メールに振り分ける確率が大幅に上がります。ユーザーにメールが届かないサービスは信頼を失います。設定自体は10分程度で完了するので、メール送信機能を実装したら必ず設定しましょう。
10. まとめ
| やったこと | なぜ必要か |
|---|---|
| Resendにドメインを登録 | 自分のドメインからメールを送れるようにする |
| DKIM(TXTレコード)を設定 | メールの電子署名を検証可能にする |
| SPF(TXTレコード)を設定 | 許可されたサーバーからの送信であることを証明する |
| MX(MXレコード)を設定 | バウンスメール(送信エラー)を正しく処理する |
メール認証は地味な設定作業ですが、ユーザーにメールが確実に届くというサービスの信頼性に直結します。Webサービスを本番運用する際は、必ず設定しましょう。