メール
メールには2つの層がある
その名の通り「封筒」と捉えると良い
headerとbody
封筒に入っている中身と捉えると良い
メーラーではこれだけが見えている
code:_
┌─ Envelope(SMTPで運ぶ時の情報) ──┐
│ MAIL FROM: bounce@sender.com │ ← 送信側サーバ間でのみ使われる
│ RCPT TO: bob@example.com │ ← 配送先を決めるのはこっち
│ │
│ ┌─ Headers + Body(中身)─────┐ │
│ │ From: Alice │ │ ← MUAが画面に表示するのはこっち
│ │ To: Bob <bob@...> │ │
│ │ Cc: Carol <carol@...> │ │
│ │ Subject: Hello │ │
│ │ │ │
│ │ Hi Bob, ... │ │
│ └──────────────────────────────┘ │
└────────────────────────────────────┘
table:_
目的 配送 表示・返信・スレッディング
寿命 配送中だけ メール本文と一緒に永続
書き換え ホップごとに書き換わる 原則そのまま運ばれる
ズレることも多い
なりすまし・フィッシング の温床になる
後付けで認証を付けた
table:_
DKIM メッセージに付いた署名がドメイン公開鍵で検証できるか(ヘッダ・本文の改ざん検知) DMARC ヘッダのFrom: ドメインと SPF/DKIM 検証結果が整合してるか メーリングリストや BCC、メール転送はこの「封筒と中身がズレる」性質を活かして実装されている。
To / Cc / Bcc の違い
table:_
ヘッダ メッセージヘッダに載る? エンベロープに載る?
Bccの特殊性
BccのアドレスはMTA(送信サーバ)が配送時にメッセージヘッダから消す だから受信者はBccに誰が含まれていたかわからない
ただしエンベロープの RCPT TO: にはちゃんと載っているので、配送はされる。 つまり、Bccで届いたメールはメッセージのTo/Ccヘッダを見ても自分宛だとわからない。
RCPT TO:(エンベロープ側)を見ないと自分が宛先だったことが判別できない。 メールのto/from 体系まとめ
全体構造: 2層 × 2方向
code:_
送信側 (from) 受信側 (to)
───────────────── ─────────────────
(= envelope-from) (= envelope-to)
(= reverse-path) (= forward-path)
│ │
│ 受信MTAが書き写す │
▼ ▼
メッセージ層 Return-Path: Delivered-To: From: ←━━ ユーザーが書く ━━━→ To:
Sender: (代理送信) Cc:
Reply-To: (返信先) Bcc: (← 削除される)
2. 同じものの呼び名対応表
「同じ実体」に複数の名前がついている。文脈で使い分ける。
from側
table:_
呼び名 レイヤー いつ使う言い方か
RFC5321.MailFrom DMARC用語 認証の議論
to側
table:_
呼び名 レイヤー いつ使う言い方か
3. レイヤー別の役割
エンベロープ層 (SMTPコマンド)
table:_
役割
MAIL FROM: バウンスの返り先。配送失敗したらここに通知
RCPT TO: 実際の配達先。複数指定可。Bccもここに入る
特徴: 配送中だけ存在。届いたら捨てられる(=メッセージにそのままは残らない)。
メッセージ層 (RFC 5322ヘッダ)
from系
table:_
ヘッダ 必須? 役割
From: 必須 誰が書いたか(人間に見える表示)
Sender: 任意 誰が投函したか(代理送信時のみ。普段は省略)
Reply-To: 任意 返信先(From: と別にしたいとき)
Return-Path: 自動 受信MTAが MAIL FROM: を写したもの
to系
table:_
ヘッダ 必須? 役割
4. 「同じはずだがズレる」典型ケース
table:_
ケース エンベロープ メッセージヘッダ
通常メール RCPT TO: bob@ To: bob@ (一致)
Bcc RCPT TO: bob@ To: alice@ (Bcc: は消える)
メーリングリスト RCPT TO: bob@ (展開後) To: ml@
エイリアス転送 RCPT TO: tanaka@ (実体) To: info@
代理送信 MAIL FROM: bot@ From: alice@, Sender: bot@
VERP MAIL FROM: bounce+bob@ From: ml@
→ エンベロープとメッセージは原則一致しないくらいの認識が正しい。
5. 認証との対応 (SPF / DKIM / DMARC)
table:_
仕組み 何を見るか どの「from」か
SPF 送信元IPがそのドメインから送る権利があるか envelope-from (MAIL FROM:)
DKIM メッセージ署名が公開鍵で検証できるか (ドメインは署名に含まれる d= タグ)
DMARC alignment From: のドメインが SPF/DKIM のドメインと一致するか From: (header-from)
ポイント: SPFはenvelope-from、DMARCはheader-fromを見る。fromが複数あるせいで認証が複雑化している。
6. 「自分宛だったか」を判別するときの優先順位
1. Delivered-To: ← 第一候補
2. Received: の for <...> 句 ← フォールバック
3. To: / Cc: ← 使うべきでない(取りこぼす)
7. SMTPセッション例 (全要素入り)
code:_
S: 220 smtp.example.com ESMTP
C: EHLO client
C: MAIL FROM:<bounce@ml.example.com> ← envelope-from
S: 250 Ok
C: RCPT TO:<bob@example.com> ← envelope-to (1)
S: 250 Ok
C: RCPT TO:<carol@example.com> ← envelope-to (2: 実はBcc)
S: 250 Ok
C: DATA
S: 354 ...
C: From: alice@example.com ← header-from
C: Sender: ml@example.com ← 代理送信の表現
C: Reply-To: ml@example.com ← 返信先
C: To: bob@example.com ← 表示用To (carolは載らない)
C: Cc: dave@example.com ← 表示用Cc (実は配送されてない例)
C: Subject: ...
C:
C: 本文
C: .
S: 250 Ok queued
C: QUIT
受信後bobのメールには:
code:_
Return-Path: <bounce@ml.example.com> ← MAIL FROM を写したもの
Delivered-To: bob@example.com ← RCPT TO を写したもの
From: alice@example.com
Sender: ml@example.com
Reply-To: ml@example.com
To: bob@example.com
Cc: dave@example.com
Subject: ...
8. 1枚で覚えるなら
code:_
FROM 系 TO 系
───────────── ─────────────
┌─────────┐ MAIL FROM: RCPT TO:
│エンベロープ│ = envelope-from = envelope-to
│(配送用) │ = reverse-path = forward-path
└─────────┘ │ 受信MTAが写す │
▼ ▼
┌─────────┐ Return-Path: Delivered-To:
│メッセージ │ ────────────────────────────────────
│(表示用) │ From: ★ユーザーが書く★ To:, Cc:
│ │ Sender:, Reply-To: Bcc: (消える)
└─────────┘
覚え方:
「エンベロープ = 配送のため」「メッセージ = 表示のため」
「同じものに複数の名前」がある(コマンド名/概念名/ヘッダ名/RFC正式名)
「from は複数(From/Sender/Reply-To/Return-Path)、to も複数(To/Cc/Bcc/Delivered-To)」
「両者は原則ズレる」「配送はエンベロープ、表示はメッセージ」
Gmailは+でエイリアス、.はあってもなくても同じ Gmailの新スパム規制対応全部書く