郵便局長
転送メールの「受け渡し記録」―ARC認証で信頼をつなぐ仕組み―
ARC(認証済み受け渡しチェーン)は、メール転送時の「受け渡し記録」です。各中継地点が署名を残すことで、最終的な受信者が経路を検証できます。
郵便局で書留を扱うとき、私たちは必ず「受け渡し記録票」に判を押していました。差出人と受取人だけでなく、途中で荷物に触れたすべての担当者が記録に残す。配達区の担当が、集配センターが、そして最終的に配達した局員が。荷物が遠くから旅をしてきたとき、その票を見れば「誰がどこで受け取り、誰がどこへ渡したか」が一目でわかる仕組みでした。
メールの認証も、転送というひと手間が加わると、まったく同じ問題に直面します。そしてその問題を解決するために生まれたのが、ARC(Authenticated Received Chain)です。
ARCが生まれるまでの経緯
ARCを理解するには、まずメール認証の歴史を少し振り返る必要があります。
2012年前後、DMARC(Domain-based Message Authentication, Reporting & Conformance)が普及し始めました。DMARCは、送信元ドメインのDKIM署名とSPFレコードを照合することで、なりすましメールを検出する優れた仕組みです。企業や大手サービスがDMARCを導入するにつれ、迷惑メール対策は大きく前進しました。
しかし、ここで見落とされていた問題が浮かび上がりました。メール転送です。
日本でも、企業のシステム担当者が「会社のメールをGmailに転送して外出先でも読めるようにしたい」と設定したり、Mailman(メーリングリストソフトウェア)を使ったオープンソースコミュニティのMLがメンバー全員にメールを配信したりすることは日常的な光景です。こうした転送が行われると、転送元サーバーのIPアドレスは送信元ドメインのSPFレコードに載っていませんし、転送時にメール本文や件名が少し変わると、DKIMの電子署名も壊れてしまいます。
受信サーバーは難しい判断を迫られることになりました。「SPF・DKIMが通らないから拒否する」と設定すれば正規の転送メールが届かなくなる。「多少失敗しても受け入れる」と設定すれば迷惑メールが紛れ込む。どちらも困ります。
この課題を受けて、Google・Microsoft・Yahoo・LinkedInなどのエンジニアたちがARC作業部会を結成し、2015年頃から本格的な仕様策定を開始しました。実運用テストを繰り返しながら仕様を磨き、2019年7月にRFC 8617として正式に標準化されました。同年、GoogleがGmailでのARC対応を開始し、MicrosoftもExchange OnlineでARC署名の付与と検証をサポートしました。現在では、KaiMailのようなメール転送サービスにとって、ARCの実装は標準的なベストプラクティスとなっています。
転送メールの「受け渡し記録」―ARCの仕組み―
ARC は、転送経路上の各中継地点(フォワーダー)が3種類のヘッダーを付け加えることで機能します。書留の受け渡し記録票に「受け取った日時・担当者・状態」を記録するのと、まったく同じ発想です。
3種類のARCヘッダー:
ARC-Authentication-Results(AAR) ―「私がこのメールを受け取ったとき、認証結果はこうでした」という記録。SPF・DKIM・DMARCの検査結果を記します。転送のたびにi=1、i=2と番号が増えていきます。
ARC-Message-Signature(AMS) ―「私がこのメールを受け取ったときの状態」に対する電子署名。DKIMと同じRSA暗号方式を使い、この時点でのメッセージが改ざんされていないことを証明します。
ARC-Seal(AS) ―「これより前に付けられたすべてのARCヘッダーセットを封印する」署名。チェーン全体を保護し、過去のスタンプが誰かに書き換えられていないことを保証します。
KaiMailが転送処理を行うと、受信したメールに以下のようなヘッダーが追加されます(読みやすくするために一部省略しています)。
ARC-Authentication-Results: i=1; kaimail.net;
dkim=pass header.d=sender-domain.com;
spf=pass smtp.mailfrom=sender-domain.com;
dmarc=pass action=none header.from=sender-domain.com
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed;
d=kaimail.net; s=arc2024;
h=from:to:subject:date:message-id:mime-version:content-type;
bh=<ボディのハッシュ値>;
b=<電子署名>
ARC-Seal: i=1; a=rsa-sha256; cv=none;
d=kaimail.net; s=arc2024;
b=<シール署名>
cv=(chain validation)という項目に注目してください。最初の転送地点(i=1)では常にcv=noneとなります。2つ目以降ではcv=pass(すべてのシールが検証済み)またはcv=fail(どこかで検証が失敗した)となります。
cv=failが必ずしも「不正なメール」を意味するわけではありません。「ARCに対応していない中継サーバーがメールを転送した」「予期しない変更が加わった」など、無害な原因も多くあります。チェーンはどこで何が起きたかを示すだけで、正直な記録です。
ARCヘッダーを実際に見てみよう ―Pythonコード―
少し時間をかけて、コードで確認してみましょう。今回も一緒に歩んでいきます。
PythonでDKIMとARCを扱う標準的なライブラリはdkimpyとauthheadersです。まずインストールしてください。
pip install dkimpy authheaders
ARCヘッダーを付与してメールを署名する
import authheaders
# 転送処理を行うサーバーとして、受信した生のメールメッセージを読み込む
with open("received_message.eml", "rb") as f:
raw_message = f.read()
# 受信時のSPF・DKIM・DMARC検査結果(本番環境ではMTAが生成)
auth_results = (
"i=1; kaimail.net; "
"dkim=pass header.d=example.com; "
"spf=pass smtp.mailfrom=example.com; "
"dmarc=pass action=none header.from=example.com"
)
# ARC署名用の秘密鍵(RSA、PEM形式)
with open("arc_private_key.pem", "rb") as f:
private_key = f.read()
# ARCヘッダーを付けてメッセージに署名する
signed_message = authheaders.sign_message(
message=raw_message,
authserv_id="kaimail.net",
selector=b"arc2024",
domain=b"kaimail.net",
privkey=private_key,
sig=b"ARC",
auth_results=auth_results.encode()
)
print(signed_message.decode())
ARCチェーンを検証する
import authheaders
with open("forwarded_message.eml", "rb") as f:
raw_message = f.read()
# verify_arc_chainはチェーン全体の検証結果と各ホップの詳細を返す
cv, results = authheaders.verify_arc_chain(raw_message)
print(f"ARCチェーン全体の状態: {cv}")
for r in results:
print(f" ホップ {r['instance']}: シール={r['seal']}, メッセージ署名={r['ams']}")
cv=passが返れば、チェーン全体が正常に検証されています。転送によってSPFやDKIMが壊れていても、受信サーバーはこの結果をもとに信頼の判断を行うことができます。
ARCヘッダーをシンプルにパースする
import re
from email import message_from_bytes
with open("forwarded_message.eml", "rb") as f:
msg = message_from_bytes(f.read())
arc_headers = {
"ARC-Authentication-Results": [],
"ARC-Message-Signature": [],
"ARC-Seal": [],
}
for header_name in arc_headers:
values = msg.get_all(header_name, [])
for v in values:
instance_match = re.search(r'i=(\d+)', v)
instance = int(instance_match.group(1)) if instance_match else 0
arc_headers[header_name].append((instance, v.strip()))
# インスタンス番号順に出力
for header_name, entries in arc_headers.items():
for i, val in sorted(entries):
print(f"\n[{header_name}] i={i}")
print(val[:200], "..." if len(val) > 200 else "")
KaiMailのARC署名が正しいかどうかを確認する方法
KaiMail経由で届いたメールのARCヘッダーが適切かどうかを検証する方法をいくつかご紹介します。
方法1 ―Gmailの「元のメールを表示」機能―(コード不要)
- KaiMail経由で届いたメールをGmailで開く
- 右上の「…」メニューから 「元のメールを表示」 を選択する
- 「クリップボードにコピー」してから、Googleが提供するメッセージヘッダー解析ツール toolbox.googleapps.com/apps/messageheader/ に貼り付ける
ARC-Sealのcv=noneまたはcv=passを確認する
方法2 ―MXToolboxによるヘッダー解析―
MXToolboxの EmailHeaders解析ページ に生のヘッダーを貼り付けると、ARCヘッダーの形式や署名の状態を確認できます。
方法3 ―Pythonによる検証スクリプト―
Gmailで「元のメールを表示」→「元のメールをダウンロード」で.emlファイルとして保存し、以下のスクリプトで検証します。
import authheaders
import sys
eml_path = sys.argv[1] # 例: python verify_arc.py my_message.eml
with open(eml_path, "rb") as f:
raw = f.read()
cv, results = authheaders.verify_arc_chain(raw)
print(f"\n=== ARC チェーン検証結果 ===")
print(f"チェーン全体の状態: {cv.upper()}")
print()
for r in results:
i = r.get("instance", "?")
seal_status = r.get("seal", "不明")
ams_status = r.get("ams", "不明")
domain = r.get("domain", "不明")
print(f" ホップ {i} ({domain}):")
print(f" ARC-Seal: {seal_status}")
print(f" ARC-Message-Signature: {ams_status}")
KaiMailで正常に転送されたメールの期待される出力:
=== ARC チェーン検証結果 ===
チェーン全体の状態: PASS
ホップ 1 (kaimail.net):
ARC-Seal: pass
ARC-Message-Signature: pass
方法4 ―OpenARCコマンドラインツール―
Linuxマシンをお使いの方は、openarcツールでも検証できます。
# インストール(Debian/Ubuntu系)
sudo apt install openarc
# 保存したメールファイルを検証
openarc -v -f forwarded_message.eml
ARC verification results: passが表示されれば正常です。
検証が失敗した場合
cv=failが表示された場合、最も多い原因はKaiMailの下流で別の転送処理が行われた際にARCチェーンが更新されなかったか、メッセージが何らかのフィルターによって変更された場合です。チェーンはどこで問題が発生したかを記録しているので、ログをさかのぼれば原因が特定できます。
なぜKaiMailはARCを実装しているのか
KaiMailは、メールの送信元と最終受信者の「あいだ」に位置するサービスです。まさにSPF・DKIMが最も壊れやすい位置です。ARCヘッダーを付与することで、KaiMailは最終受信サーバーに対してこう伝えています。「このメールを私が受け取ったとき、認証はこの状態でした。私の判断を信頼していただけますか。」
GmailやOutlookは、信頼済みのフォワーダーから届いたメールの判定に、ARCを考慮した仕組みを採用しています。転送されたメールが迷惑メールフォルダに入らずに受信トレイへ届くのは、こうした地道な実装の積み重ねによるものです。
さくらインターネットやXSERVERでメールアドレスを運用しながら、それをGmailやiCloudに転送して使っている方は多くいらっしゃいます。そういった場面でも、ARCはメールの信頼性を守る重要な役割を担っています。
最後に
郵便の受け渡し記録は、不信感から生まれたものではありませんでした。荷物が大切に届いてほしいという、関わる全員の責任感から生まれた仕組みでした。ARCも同じです。各転送地点が「自分はこう受け取り、こう渡した」と記録に残す。それが積み重なって、受取人のもとに届いたとき、その手紙の旅が証明されます。
ヘッダーの中には、たくさんの誠実な仕事が刻まれています。ぜひゆっくり読んでみてください。