Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 17110] ファイルの概要

このコミットは、Go言語のnet/mailパッケージにおけるメールアドレスのパース処理に関して、RFC 5322の仕様からの意図的な逸脱を明確にするためのコメント追加です。具体的には、dot-atomのパースにおいて、RFC 5322よりも許容度の高い(より広範な形式を許容する)実装になっていることをコード内に明記しています。

コミット

commit d2bff757f6043d9a6f61616ac7dd78ca30442cb4
Author: David Symonds <dsymonds@golang.org>
Date:   Fri Aug 9 10:17:57 2013 +1000

    net/mail: comment our divergence from RFC 5322.
    
    R=golang-dev, bradfitz
    CC=golang-dev, ryanslade
    https://golang.org/cl/12588044

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/d2bff757f6043d9a6f61616ac7dd78ca30442cb4

元コミット内容

net/mail: comment our divergence from RFC 5322.

R=golang-dev, bradfitz
CC=golang-dev, ryanslade
https://golang.org/cl/12588044

変更の背景

net/mailパッケージは、電子メールメッセージの解析と生成を扱うGoの標準ライブラリの一部です。電子メールのフォーマットは、RFC 5322 (Internet Message Format) によって厳密に定義されています。しかし、現実世界の電子メールは、RFCの仕様に完全に準拠していない場合が多々あります。特に、メールアドレスのローカルパート(@より前の部分)のパースにおいて、RFC 5322が定義するdot-atomの規則は厳格です。

このコミットの背景には、net/mailパッケージが、より多くの「不正な」メールアドレスもパースできるように、RFC 5322のdot-atomの定義よりも許容度の高い実装を採用していたという事実があります。このような実装は、現実世界の多様なメールアドレスに対応するために必要ですが、RFCからの逸脱であるため、その事実をコードのコメントとして明記し、将来のメンテナや利用者がこの挙動を理解できるようにすることが目的でした。これにより、なぜ特定の形式のメールアドレスがパースできるのか、あるいはできないのか、という疑問に対する明確な説明を提供します。

前提知識の解説

RFC 5322 (Internet Message Format)

RFC 5322は、インターネット上で電子メールメッセージがどのようにフォーマットされるべきかを定義する標準規格です。これには、メッセージヘッダー(From, To, Subjectなど)、メッセージ本文、そしてメールアドレスの構文などが含まれます。

メールアドレスの構文と local-part

メールアドレスは一般的に local-part@domain の形式を取ります。このコミットで特に言及されているのは、local-partの構文です。RFC 5322では、local-partは主に以下の2つの形式で表現されます。

  1. dot-atom: これは、ピリオド (.) で区切られた1つ以上のatext文字のシーケンスです。atext文字とは、英数字と特定の記号(!, #, $, %, &, ', *, +, -, /, =, ?, ^, _, {, |, }, ~)の集合です。dot-atomには以下の厳格なルールがあります。

    • ピリオドは最初または最後の文字であってはならない。
    • 2つのピリオドが連続して出現してはならない。
    • 例: john.doe, user-name, a!b#c
  2. quoted-string: これは、ダブルクォーテーション (") で囲まれた文字列です。quoted-stringは、dot-atomでは許可されないスペースやその他の特殊文字を含むことができます。

    • 例: "John Doe", "user name"

net/mailパッケージの役割

Goのnet/mailパッケージは、これらのRFCの仕様に基づいてメールメッセージを解析し、Goのデータ構造にマッピングする機能を提供します。これにより、開発者はメールのヘッダーや本文、アドレスなどを簡単に操作できます。

技術的詳細

このコミットが追加された時点のnet/mailパッケージのaddrParser構造体内のconsumePhraseメソッドは、メールアドレスのlocal-partをパースする際に、dot-atomの規則をRFC 5322よりも緩やかに解釈していました。具体的には、RFC 5322では許可されない形式のdot-atomもパースできるように実装されていました。

RFC 5322の厳格なdot-atomの定義は、メールアドレスの有効性を保証するために重要ですが、現実世界では、この定義に完全に準拠していないメールアドレスが多数存在します。例えば、一部のシステムでは、RFCで禁止されている連続したピリオドや、ピリオドで始まる/終わるローカルパートを許容する場合があります。

net/mailパッケージがこのような「より許容度の高い」パースを行うことで、RFCに厳密には準拠していないが、実用上は有効なメールアドレスも処理できるようになります。これは、堅牢なメール処理システムを構築する上で重要なトレードオフです。しかし、この挙動はRFCの仕様とは異なるため、コードの可読性と保守性を高めるために、その逸脱を明示的にコメントとして残すことが決定されました。

この変更は、パースロジック自体を変更するものではなく、既存の挙動に対する説明を追加するものです。これにより、将来のコードレビューやデバッグの際に、なぜ特定のメールアドレスがパースされるのか、あるいはなぜRFCに準拠していない形式が受け入れられるのか、といった疑問に対する手がかりとなります。

コアとなるコードの変更箇所

--- a/src/pkg/net/mail/message.go
+++ b/src/pkg/net/mail/message.go
@@ -342,6 +342,8 @@ func (p *addrParser) consumePhrase() (phrase string, err error) {
 	\t\t\tword, err = p.consumeQuotedString()\n \t\t} else {\n \t\t\t// atom\n+\t\t\t// We actually parse dot-atom here to be more permissive\n+\t\t\t// than what RFC 5322 specifies.\n \t\t\tword, err = p.consumeAtom(true)\n \t\t}\n \n```

## コアとなるコードの解説

変更は`src/pkg/net/mail/message.go`ファイルの`consumePhrase`メソッド内で行われています。このメソッドは、メールアドレスのフレーズ(通常は`local-part`または表示名の一部)を消費(パース)する役割を担っています。

元のコードでは、`consumeQuotedString()`が引用符で囲まれた文字列を処理し、それ以外の場合は`consumeAtom(true)`がアトム(`dot-atom`を含む)を処理していました。

追加された2行のコメントは、`consumeAtom`が呼び出される直前に挿入されています。

```go
// We actually parse dot-atom here to be more permissive
// than what RFC 5322 specifies.

このコメントは、以下の重要な情報を伝えています。

  1. We actually parse dot-atom here: ここでdot-atomのパースが行われていることを明確に示しています。
  2. to be more permissive than what RFC 5322 specifies.: 最も重要な点として、このdot-atomのパースがRFC 5322の仕様よりも「より許容度が高い」ことを明記しています。これは、RFC 5322が定義する厳格なdot-atomのルール(例: ピリオドの連続、先頭/末尾のピリオドの禁止)を、この実装では一部緩和していることを意味します。

このコメントにより、コードの意図が明確になり、なぜ特定のRFC非準拠のメールアドレスがnet/mailパッケージで正常にパースされるのかという疑問に対する説明が提供されます。これは、ライブラリの挙動を理解し、将来の変更やデバッグを行う上で非常に価値のある情報です。

関連リンク

参考にした情報源リンク