60768


Gmail ではメールアドレスに `+`
記号を付けることでひとつのアカウントのメールアドレスに[タグを付けて扱うことができます](https://gmail.googleblog.com/2008/03/2-hidden-
ways-to-get-more-from-your.html)。しかしたとえばユーザー登録時のメールアドレスに `+`
記号が含まれていると「正しいアドレスを入力してください」とバリデーションエラーを出すウェブアプリにしばしば遭遇します。

RFC 5322 によると、メールアドレスのローカルパートには記号 `!#$%&'*+-/=?^_`{|}~`
を含むことができます。なのでバリデーション側が間違っていることになります。

ただもしかすると、メールアドレスの仕様では OK でも、裏側で動いているシステムにおいて NG
なことがあるのかもしれません。たとえば何かしらセキュリティリスクがあって許しておらず、そのエラーメッセージがたまたま「アドレスが間違っている」というものになっているのかもしれません。もしそうなのであれば自分でアプリを作る際に注意しておきたいです。逆に、単に歴史的理由や特定のライブラリのバグなのであれば気にする必要が無くなります。

そこで、質問です。メールアドレス内に記号（特に `+`）を許すことによるリスクはありますか？ あるならば、どのようなものでしょうか？
それは適切なエスケープを課すなどして避けられないものなのでしょうか？


CC BY-SA 4.0
2019-11-21T14:44:49.197
60742
2019-11-22T22:44:19.197
19110
question
security mail
メールアドレスに記号を許すことによるリスクはありますか？


「リスク」という文言に @nekketsuuu さんが何を期待というか想定しているのかわからないので答えにくいというか。

`+` 文字を含む「印刷可能な記号」が  
[RFC5322](https://www.rfc-editor.org/rfc/rfc5322) には使えるとありますが  
[RFC822](https://www.ietf.org/rfc/rfc822.txt) においては使えるとなっていない (RFC822 は 5322
の前身)  
ので  
「古い RFC822 にのみ対応していて RFC5322 に対応していない MTA/MUA/MDA
が経路にいて、そいつらが記号を含むメールアドレスを拒絶する」リスクはありそうです。（バリデータが拒絶した理由がそれなのかも）

今どきまともな ISP であれば RFC5322 に対応しているはずで問題ないと思いますが、古くてサポートすら切れている商用 UN*X を (MTA/MUA
として) 使わざるを得ないユーザーにおいて問題があるかもしれません。

メールアドレスにシングルクォーテーション文字を使ってよい関係で、メールアドレスをデータベースに格納する際に SQL
インジェクション脆弱性のあるシステムがバグるかもしれませんが、それはそれ、バグっているほうが悪いっすね。

エスケープで逃れられるか？
ですが、誰がエスケープして誰が危険から逃れられるのかがが微妙に不明です。データベースバックグラウンドのバグを、使う側ユーザーがメールアドレスをエスケープして入力することで避ける？
それはオイラたち一般「使う側ユーザー」が頑張って対処することではないと思いますし、バグっているソフトを使い続けているコンテンツ提供側が悪いっす。

というわけで敢えて「回答」にするなら RFC822 にしか対応していない何かがあると RFC5322 なメールが使えない可能性は０ではない、でしょうか。


CC BY-SA 4.0
2019-11-22T07:17:35.307
60764
2019-11-22T07:17:35.307
2021-10-07T07:34:52.683
-1
8589
60742
answer


私の立場は、メールアドレスを扱うシステム作る側でもありますが、組織内でどのようなメールアドレスを作っても良いか技術面から決める側でもあります。そのため、質問の趣旨と微妙にずれているかも知れませんが、どのようなメールアドレス生成を許可するのかが関心の中心となった回答になっている事にご配慮ください。

* * *

考えるべきリスクは二つかと思います。

  1. 自分のシステム上で不具合が起きる可能性があるかどうか。
  2. 他人のシステム上で送信できない・登録できない等の不都合が起きる可能性があるかどうか。

しかし、実際は1.ではなく2.についてのみ考えるべきです。なぜなら、どのようなメールアドレスでも、可能な限り扱えるべきであるし、拒否すべきでは無いためです。しかし、それがもっともな理由であれば、拒否することもやぶさかでは無いと思います。

そこでまずは、各システムや実装、その他において、どのような記号が許されるのかを見ていきたいと思います。

### RFC5322に準拠したメールアドレス

本来であれば、RFC5322に準拠したメールアドレスには対応すべきです。少なくともMTAについてそのような実装になっている事を期待することは悪いことではありません。しかし、その他全てが完全にRFC5322に準拠している期待できるほど、標準仕様は守られているものではありません。

RFC5322でのメールアドレスのローカル部にはdot-atom、quoted-string、obs-local-partの三つがあります。

  * dot-atomは私達がよく目にするメールアドレスであり、英数字と記号`.!#$%&'*+-/=?^_`{|}~`でから作られます。ただし、先頭の`.`、末尾の`.`、連続する`..`はできません。
  * quoted-stringは`"`で囲むことによって`.`の制限をなくし、ASCIIの他記号も使えるようにしています。ただし`"`と`\`は`\"`と`\\`のようにエスケープする必要があります。
  * obs-local-partは廃止された書き方であるため、使うべきでは無いでしょう。

実際の所、MTAを除けば、後述のHTML5のようにdot-
atomしか考慮されていない場合がほとんどです。また、docomoでメールアドレスに連続する`..`が昔は設定できた等、準拠しないメールアドレスがしばしば使われる事もあったことも注意すべきです。メールアドレスを扱うシステムを作る側としては準拠するパターン全てを考慮したいところですが、メールアドレスを作る側としては、dot-
atomに準拠した場合であればだいたいうまくいくと期待できると考えるべきでしょう。

### HTML5の[valid email
address](https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-
address)

HTML5では`<input>`で`type="email"`を使うことができます。この時、ブラウザでは妥当なメールアドレス(valid e-mail
address)であるのかの判定が行われます。その時のローカル部については非常に単純で英数字と記号`.!#$%&'*+-/=?^_`{|}~`からなります。

この妥当なメールアドレスはRFC5322のdot-atomに似ていますが、完全には **準拠していません**
。準拠していない部分は、先頭の`.`、末尾の`.`、連続する`..`を許しているところです。さらに、qutode-stringは一切考慮していません。

今後、Web入力において、`<input
type="email">`は積極的に使われていくと考えられます。Webシステムが当たり前になっていく現代において、この仕様は無視できるものではありません。HTML5において妥当なメールアドレスになるように、つまりqotued-
stringは使わず、dot-atomを生成すべきでしょう。

### Postfixの`allow_min_user=no`による制限

Postfixには[allow_min_user](http://www.postfix.org/postconf.5.html#allow_min_user)という設定があり、この設定が`yes`でない限り、ローカル部が`-`から始まるメールアドレスの場合は、受け取りを
**拒否します** 。デフォルトは`no`であり、つまり、 **インストール直後の何も設定していない(何も書いていない)状態では拒否します** 。

このPostfixのデフォルトの動作はセキュリティ上の理由です。そして、多くのPostfixのサーバーではこの設定は有効になっていると考えられます。RFC5322では`-`について特に制限はありませんでしたが、先頭に使うべきではありません。

### 特別な置き換えに使われる記号

Postfixでは、設定次第では、ローカル部にある`%`や`!`を`@`に置き換えて解釈される場合があります。これはさらに内部へリレーする場合やUUCPネットワークに対応するためのものです。`%`も`!`も問題なく使える記号のはずですが、意図せぬ置き換えを避けるために、通常の利用には避けた方が良いと考えるべきでしょう。

### 拡張アドレスの区切り記号

MTAの設定次第では記号`+`が拡張アドレスの区切り記号として使われる場合があります。例えば、Postfixで[recipient_delimiter](http://www.postfix.org/postconf.5.html#recipient_delimiter)が`+`の場合、`user+ext`は`user+ext`という名前以外にも`user`という名前でも存在や配送先を確認します。

Postfixではデフォルトでは「空」のため無効のようです。しかし、拡張アドレスについて言及しているところのほぼ全てで、サンプルとして`+`が区切り文字として使われています。(@ernix
さんの回答にある歴史的経緯によるものかと思われます)

### メーリングリストでの特別なアドレス

mailman等でメーリングリストを作成した場合、メーリングリストアドレスのローカル部に`-bounce`等とつけたアドレスが特別な意味を持つアドレスになる場合があります。つまり、任意の`-`を許してしまうと、他のメーリングリストアドレス用の特別なアドレスと被る可能性があるということです。利用者が任意の名前を申請し、自動的に登録されるようなシステムでは、そのようなことがないように注意が必要になります。

### シェルやバッチで特別な意味を持つ記号の考慮

Postfixの先頭`-`禁止に近いのですが、メールアドレスを処理するプログラムがシェル呼び出しで処理すると言った場合、不用意なシェル展開で思わぬバグを起こす可能性があります。たとえば、次のようなRubyプログラムを想像してみてください。

[code]

    temp = "/tmp/temp.mail"
    addr = 'a`shutdown`b@exmaple.jp'
    system("/usr/lib/sendmail #{addr} < #{temp}")
    
[/code]

もちろん、このプログラム自体が質の悪い(プログラムの内容によっては脆弱性がある)と言ってもいいと思いますが、内部用の処理に作られるプログラムは、しばしばこういった点の考慮が抜けていることがあります。そう言うことを事前に防ぐ意味で、シェル展開時に単独で意味がある記号`#$&'*?`|~`等は除外した方が良いかもしれません。

### 数字のみの危険性

非常に私事ですが、私の所の組織では、その昔`0`から始まる数字のみのユーザーが登録されようとしたことがあり、内部処理の途中で数値として変換され、その後、`0`を除いた数字のみユーザーとして一部のシステムに登録されたという事態が発生しました。そのユーザーは削除して、別の名前になったのですが、削除処理も途中でおかしくなって連携するシステム群にゴミが残り続けたというのがありました。

プログラムのバグと言えばその通りですが、当時はシェルやPerlを組み合わせて作られたプログラムだったので、あまりそういった点は考慮せずに作られていました。そういった古いプログラムがあることを考慮するとユーザー名の先頭は英字のみに限定するなどした方が良いかもしれません。(実際に、内の組織はそれ以降先頭は英字のみになりました。)

### 主なクラウドサービスで使用できる記号

いまやオンプレでメールサーバーを運用することは、莫大なコストの割に可用性が高められず、セキュリティ等のリスクが高くなるばかりで割に合わなくなっています。法的なリスクを飲めるのであれば、G
SuiteやOffice 365等のクラウドサービスへの移行を真剣に検討することが求められることも少なくありません。

将来、G SuiteまたはOffice
365に移行するとなったとき、問題になるのは今のメールアドレスをそのまま使えるかどうかです。もし、使えないメールアドレスがあった場合、利用者にメールアドレスの変更を依頼する必要があり、継続して使えないメールアドレスはビジネス機会の損失にも繋がります。全員ドメインを変えて、旧アドレスを転送するサーバーが永遠に残るという事例も珍しくありません。ですので、ユーザー名がメールアドレスとなるときは、ユーザー名に使える記号を調べておくのは必須です。

  * G Suiteで使えるユーザー名は下記に記載されています。  
[ユーザー名とグループ名のガイドライン - G Suite 管理者
ヘルプ](https://support.google.com/a/answer/9193374?hl=ja)  
記号は`-_'.`のみです。そして、`.`についてはRFC5322と同じ制限があります。

  * Office 365で使えるユーザー名の情報は下記に記載されています。  
[Azure AD セルフサービスによるパスワード リセット ポリシー - Azure Active Directory \| Microsoft
Docs](https://docs.microsoft.com/ja-jp/azure/active-
directory/authentication/concept-sspr-policy)  
[特殊文字を含むユーザー名を作成すると、エラーが発生する \| Microsoft Docs](https://docs.microsoft.com/ja-
jp/office/troubleshoot/error-messages/username-contains-special-character)  
使えると明記されている文字は`.-_`のみです。ただし、`.-`は先頭と末尾には使えません。

なお、これらはユーザー名としてであることに注意してください。エイリアスとしては他の記号をメールアドレスに設定できる可能性はあります。(詳細は未確認ですが、gmailのタグ付けのように特別な意味になる記号も注意すべきです。)

また、ユーザー名としては大文字小文字は無視されることに注意してください。大文字小文字無視はメールアドレスとして必須という訳ではありませんが、ほとんどのシステムでは無視されます。

### まとめ

もし、ユーザー名としても使うようなメールアドレスであれば、次のようにするとほとんどのリスクが回避できるかと思います。

  1. 英小文字と数字と三つの記号`-`と`_`と`.`のみとする。
  2. 先頭および末尾は英小文字と数字と記号`_`のみとする。※先頭は英小文字のみというのもあり。
  3. 連続する`..`は含めてはいけない。
  4. 同一ドメインでメーリングリストを運用する場合は、自動生成されるアドレスと被らないように考慮する。

ユーザー名と独立しているエイリアスやメーリングリスト等であれば、記号`#$&'*+/=?^`{|}~`も許可しても良いかもしれませんが、G
SuiteやOffice 365への移行を考えているのであれば、事前に調査をしておいた方が良いでしょう。

逆の立場、つまり、任意のメールアドレスを扱うシステムを作るのであれば、HTML5のvaild email-
address準拠が一番現実的かも知れません(少なくともWebシステムの場合はフロント側の実装が一番楽です)。quoted-
stringを使っているメールアドレスは(私が知る限り)見たことがないからです。ただ、`.`の扱いは内部のMTAによっては対応しきれない場合がありますので、注意が必要ですし、それがPostfixの場合は`-`から始まるメールアドレスは弾かれてしまうかも知れません。(MTAに渡す段階でquoted-
stringにするという方法も無い事は無いですが)


CC BY-SA 4.0
2019-11-22T15:04:53.243
60768
2019-11-22T22:44:19.197
2019-11-22T22:44:19.197
7347
7347
60742
answer


どの場面で許すかによって回答は変わってきます。

[sendmail](https://docstore.mik.ua/orelly/other/Sendmail_3rd/1565928393_ch04-77101.html#ch04-77101)や[postfix](http://www.postfix.org/postconf.5.html#recipient_delimiter)
は、その設定によって `+` 記号によるタグ付けを許容するかスイッチすることができます。あなたがタグ付けが可能なメールサーバーを運営しているなら、`+`
記号のついたメールアドレスを新規ユーザーアカウントとして認めたいとは思わないでしょう。 `john@example.com`
がすでにユーザーとして存在するのに `john+tag@example.com` を別のユーザーに割り当てれば混乱が生じるのは明らかです。

バーチャルドメインを使って一つのメールサーバーに複数のドメインを持たせ、それをMySQLで管理したとします。たとえば[このような設定例](https://www.howtoforge.com/virtual_postfix_mysql_quota_courier_p2)に従ってpostfixのセットアップを行った場合、メールアドレスを実際にサーバーのディレクトリ構成にコンバージョンするクエリがRFCに準拠せず、やっつけの
`SUBSTRING_INDEX` で端折っているのが分かります。

[code]

    user = mail_admin
    password = mail_admin_password
    dbname = mail
    table = users
    select_field = CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/')
    where_field = email
    hosts = 127.0.0.1
    
[/code]

`"@@@@@@"@example.com`
は完全にRFCに準拠した「正しい」メールアドレスですが、上のクエリがこのアドレスを正しく解釈できるわけがありません。正しく解釈するにはエスケープではなく適切なパースをやる必要があるのですが、MySQLのクエリ上でそれを実装するのが割に合うかは疑問です。

かつて[日本の一部のケータイキャリアはRFC822に準拠しないメールアドレスを登録することが可能でした](https://www.asobou.co.jp/blog/web/mail-
rfc)。ケータイ同士で送受信できれば事足りる多くのユーザーがこれを逆手に取って、スパムメールを遠ざける為にわざとRFC違反のアドレスを登録していたと記憶しています。（ソースが見つかりませんでした。もしあれば追記お願いします。）

`john.@example.com`
は完全にRFCに準拠していない「不正な」メールアドレスですが、ユーザーはPCから送信されたスパムメールがリレーサーバー上でエラーになることを期待して、あるいはこのようなアドレスがスパム避けになるという話を聞いて、こぞって使われました。これはもちろん、大問題になりました。

RFCは単なるフォーマット仕様であり、サービスのリスクとフォーマット仕様は直接関係しているわけではありません。リスクに見合うメリットがあれば事業者はフォーマット仕様でも破ります。メールのような相手の居るシステムの場合は特にそうです。

自分が送信するときはできる限り素直に送るようにし、逆に受信するときは寛容に構える事がリスクを回避するコツだと思います。

ちなみにローカルパートの `+` 記号の利用は `拡張メールアドレス`/`plus addressing`/`sub-addressing`
などと呼ばれ、実はかなり歴史があり、古くは [sendmail 8.7 の頃に実装されていた事が当時の RELEASE NOTE や README
から読み取れます](ftp://ftp.sendmail.org/pub/sendmail/past-
releases/)。Gmailはその伝統に則っているだけで、他のサービスで利用できるかまでは担保していません。これもリスクの一つと言えるかもしれません。

[code]

    8.7.1/8.7.1 95/10/01 
    ...
        CONFIG: Allow "user+detail" to be aliased specially: it will first
            look for an alias for "user+detail", then for "user+*", and
            finally for "user".  This is intended for forwarding mail
            for system aliases such as root and postmaster to a
            centralized hub.
    
[/code]

[code]

    The local mailer accepts addresses of the form "user+detail", where
    the "+detail" is not used for mailbox matching but is available
    to certain local mail programs (in particular, see FEATURE(local_procmail)).
    For example, "eric", "eric+sendmail", and "eric+sww" all indicate
    the same user, but additional arguments <null>, "sendmail", and "sww"
    may be provided for use in sorting mail.
    
[/code]


CC BY-SA 4.0
2019-11-22T15:15:17.877
60769
2019-11-22T15:15:17.877
62
60742
answer