[インデックス 17090] ファイルの概要
このコミットは、Go言語の標準ライブラリであるnet/mail
パッケージにおけるメールアドレスのパースに関するバグ修正です。具体的には、メールアドレスの表示名(display name)部分にドット(.
)が含まれる場合に、AddressList
関数が正しくアドレスを解析できない問題に対処しています。
コミット
commit 73b8baa1bdd76e0e5d898243c9d1d4ee2e6268e3
Author: Ryan Slade <ryanslade@gmail.com>
Date: Thu Aug 8 10:00:24 2013 -0700
net/mail: AddressList fails to parse addresses with a dot
Fixes #4938.
R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/12657044
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/73b8baa1bdd76e0e5d898243c9d1d4ee2e6268e3
元コミット内容
このコミットの元の内容は、net/mail
パッケージがメールアドレスの表示名にドットを含む場合に解析に失敗するというバグを修正するものです。具体的には、consumeAtom
関数の呼び出しにおいて、permissive
フラグをtrue
に設定することで、より柔軟な解析を可能にしています。また、この修正を検証するためのテストケースが追加されています。
変更の背景
この変更は、GoのIssue #4938「net/mail: AddressList fails to parse addresses with a dot」に対応するものです。この問題は、net/mail
パッケージがメールアドレスの「atom」部分(通常、表示名やローカルパートの一部)に、先頭、末尾、または連続したドットが含まれる場合に、正しく解析できないというものでした。RFC 5322などのメールアドレスの仕様では、これらのドットの使用には特定の制限がありますが、現実世界のメールアドレスには、これらの制限に厳密に従わない形式も存在します。特に、表示名のような人間が読みやすい部分では、より緩やかな解釈が求められることがあります。このバグにより、一部の有効なメールアドレスがGoのnet/mail
パッケージで処理できないという問題が発生していました。
前提知識の解説
- RFC 5322 (Internet Message Format): インターネットメールメッセージの標準フォーマットを定義するRFC(Request For Comments)文書です。メールアドレスの構文、ヘッダーフィールド、メッセージ本文の構造などが規定されています。メールアドレスの「atom」や「quoted-string」などの要素に関するルールも含まれます。
- メールアドレスの構文: 一般的なメールアドレスは
local-part@domain
の形式を取ります。- local-part:
@
記号の前の部分。ユーザー名などを表します。 - domain:
@
記号の後の部分。メールサーバーのドメイン名を表します。 - display name (表示名): メールアドレスの前に付加される、人間が読みやすい名前(例:
John Doe <john.doe@example.com>
のJohn Doe
部分)。RFCでは、表示名も特定の構文規則に従う必要があります。
- local-part:
net/mail
パッケージ: Go言語の標準ライブラリの一部で、RFC 5322に準拠したメールメッセージの解析と生成を行うための機能を提供します。ParseAddress
、ParseAddressList
などの関数が含まれます。atom
とquoted-string
: RFC 5322におけるメールアドレスの構文要素です。atom
: 特殊文字を含まない連続した文字のシーケンス。例えば、john.doe
のjohn
やdoe
はatomになりえます。quoted-string
: ダブルクォーテーションで囲まれた文字列。内部に特殊文字を含むことができます。例えば、"John Doe"
はquoted-stringです。
addrParser
:net/mail
パッケージ内部で使用される、メールアドレスの文字列を解析するための構造体です。このパーサーが、入力文字列をatom
やquoted-string
などの要素に分解していきます。consumeAtom
関数:addrParser
のメソッドの一つで、入力ストリームからatom
を消費(解析し、読み進める)する役割を担います。この関数が、ドットの扱いに厳密すぎたために問題を引き起こしていました。
技術的詳細
このコミットの核心は、net/mail
パッケージ内のaddrParser
構造体のconsumePhrase
メソッドにおけるconsumeAtom
関数の呼び出し方法の変更です。
元のコードでは、consumePhrase
メソッド内で、メールアドレスの表示名の一部を解析する際に、consumeAtom(false)
と呼び出していました。ここで渡されるfalse
は、consumeAtom
関数が「厳密な」モードで動作することを意味していました。厳密なモードでは、RFC 5322の規定に従い、atom
の先頭、末尾、または連続したドットを許可しません。
しかし、Issue #4938で報告されたように、Asem H. <noreply@example.com>
のような表示名(Asem H.
の部分)は、RFCの厳密な解釈では問題があるかもしれませんが、現実には広く使われています。特に、表示名のような人間が読みやすい部分では、より柔軟な解析が望ましい場合があります。
このコミットでは、consumeAtom(false)
をconsumeAtom(true)
に変更しています。true
を渡すことで、consumeAtom
関数は「許容的な(permissive)」モードで動作するようになります。許容的なモードでは、atom
内のドットの配置に関する一部の厳密なルールが緩和され、先頭、末尾、または連続したドットが含まれていても解析が失敗しなくなります。これにより、Asem H.
のような表示名も正しく解析できるようになります。
この変更は、net/mail
パッケージがRFCの精神を尊重しつつも、現実世界の多様なメールアドレス形式に対応するためのバランスを取るものです。特に、表示名のようなユーザーフレンドリーな部分では、厳密な構文チェックよりも実用性が優先されることがあります。
コアとなるコードの変更箇所
変更は以下の2つのファイルにわたります。
-
src/pkg/net/mail/message.go
:func (p *addrParser) consumePhrase() (phrase string, err error)
メソッド内のp.consumeAtom(false)
がp.consumeAtom(true)
に変更されました。
-
src/pkg/net/mail/message_test.go
:TestAddressParsing
関数に、ドットを含む表示名を持つメールアドレスの新しいテストケースが追加されました。具体的には、Asem H. <noreply@example.com>
という形式のアドレスが正しく解析されることを確認するテストです。
--- a/src/pkg/net/mail/message.go
+++ b/src/pkg/net/mail/message.go
@@ -342,7 +342,7 @@ func (p *addrParser) consumePhrase() (phrase string, err error) {
word, err = p.consumeQuotedString()
} else {
// atom
- word, err = p.consumeAtom(false)
+ word, err = p.consumeAtom(true)
}
// RFC 2047 encoded-word starts with =?, ends with ?=, and has two other ?s.
diff --git a/src/pkg/net/mail/message_test.go b/src/pkg/net/mail/message_test.go
index 2e746f4a72..3c037f3838 100644
--- a/src/pkg/net/mail/message_test.go
+++ b/src/pkg/net/mail/message_test.go
@@ -225,6 +225,16 @@ func TestAddressParsing(t *testing.T) {
},
},
},
+ // Custom example with "." in name. For issue 4938
+ {
+ `Asem H. <noreply@example.com>`,
+ []*Address{
+ {
+ Name: `Asem H.`,
+ Address: "noreply@example.com",
+ },
+ },
+ },
}
for _, test := range tests {
if len(test.exp) == 1 {
コアとなるコードの解説
-
src/pkg/net/mail/message.go
の変更:consumePhrase
関数は、メールアドレスの表示名(例:John Doe
)を解析する際に使用されます。表示名は、atom
(例:John
)の連続、またはquoted-string
(例:"John Doe"
)で構成されます。- 変更前の
p.consumeAtom(false)
は、atom
を解析する際にRFCの厳密なルールを適用していました。これにより、Asem H.
のように名前にドットが含まれる場合に、そのドットがRFCのatom
のルールに違反すると判断され、解析エラーが発生していました。 - 変更後の
p.consumeAtom(true)
は、consumeAtom
関数に「許容的な」モードで動作するよう指示します。このモードでは、atom
内のドットの配置に関する一部の厳密なチェックが緩和されます。これにより、Asem H.
のような表示名もエラーなく解析できるようになり、より多くの現実世界のメールアドレス形式に対応できるようになります。
-
src/pkg/net/mail/message_test.go
の変更:- 追加されたテストケースは、
Asem H. <noreply@example.com>
という文字列が、Name: "Asem H."
とAddress: "noreply@example.com"
を持つAddress
構造体として正しく解析されることを検証します。 - このテストケースは、まさにIssue #4938で報告された問題のシナリオを再現し、修正が正しく機能していることを確認するためのものです。テストが追加されることで、将来の回帰を防ぎ、コードの堅牢性を高めます。
- 追加されたテストケースは、
この変更は、net/mail
パッケージがRFCの仕様に準拠しつつも、実用的な観点から柔軟性を持たせるための重要な調整と言えます。
関連リンク
- Go Issue #4938: https://github.com/golang/go/issues/4938
- Go CL 12657044: https://golang.org/cl/12657044 (Goのコードレビューシステムへのリンク)
参考にした情報源リンク
- Go Issue #4938のGitHubページ
- Goのソースコード(
src/pkg/net/mail/message.go
およびsrc/pkg/net/mail/message_test.go
) - RFC 5322 (Internet Message Format) - 特にメールアドレスの構文に関するセクション
- Go 1.2 リリースノート (関連する変更が言及されている可能性)
- Goの
net/mail
パッケージのドキュメント