携帯の空メールで、拡張アドレスのデリミタをプラスにしているとauではまる

久々にはまったので、メモ兼ねて調べてみました。


携帯サイトで空メールを受け取るとういのは、アプリを作る上でよくある手段だと思います。
ユーザにメールアドレスを手入力してもらう手間を防ぐという理由以外に、確実に有効なアドレスを登録してもらえるという利点もあるからです。
また、画像投稿についても、一部のdocomoの新しい端末などを除き、ブラウザからは投稿が出来ないので、メールに添付をしてもらうというのはよくある手です。


それらの場合に、送信先をメールアドレスを複数用意しなければならない場合に出くわします。
そんな場合に使うのが拡張アドレスです。

user-ext@example.com
user+ext@example.com

user-、user+ 以降は自由になにを指定されても受け取るという仕組みです。
gmailでは+(プラス記号)が実際に使うことができます。


うちでは、もともとqmailを使用していたという理由から、拡張アドレスの区切り記号はハイフンを使用していました。
その後、MTAをpostfixに切り替えた時も、その設定を引き継ぎ、拡張アドレスの区切り記号はハイフンで通していました。


今回、とある案件を構築したのですが、サーバ環境側の都合で、MTAにsendmailを使用することになり、出来るだけ初期設定のままということで、拡張アドレスの区切り記号もプラス記号になることになりました。
まぁ、gmailでもやってるし大丈夫だろう。思えばこの判断が大きな誤りでした。
はまったはまった。はまりまくりました。

プラス記号が使えないau

結論から言うと、プラス記号だとau端末で空メールをhtmlのmailtoを使うと、普通の方法ではできません。

簡単なhtmlを作ってみます。

<html>
<head>
</head>
<body>
<a href="mailto:[email protected]">[email protected]</a><br />
<br />
<a href="mailto:user%[email protected]">user%[email protected]</a><br />
</body>
</html>


パターン1は、プラス記号をそのまま書いたパターン。
パターン2は、プラス記号をurlencodeした「%2B」を書いたパターン。

どうなると思いますか?ちなみに、検証した限りでは、docomo、softbank、willcom(WX330K)では、どちらでも正常に動きました。


結果

パターン1を開くと、プラス記号が空白になってしまう端末があります。つまり、メーラーは開くのですが、宛先の中身が
「user ext@example.com」になってしまっています。
そのまま送信しようとしても、端末のメーラー側のエラーが発生していまいます。


パターン2を開くと、urlencodeしている文字がちゃんとプラス記号として認識されて開く端末がありますが、逆にurlencodeしている文字のままメール作成画面が開いてしまう端末もあります。当然、そのまま送信しても宛先不明でサーバ側で受け取ることができません。

  • パターン1([email protected])
    • 空白になってしまう端末
    • 正常に動く端末
      • W61T、SH001
  • パターン2(user%2Bext@example.com)
    • 正常に動く端末
    • urlencodeがそのまま出てしまう端末
      • W61T、SH001


この記事を書く段階でテストに使用できる最新の端末が少なかったのですが、実案件で検証した範囲では、最新の世代ではプラス記号そのままで動くが、旧世代はurlencodeしないとダメみたいでした。
どこかで仕様を変更したのは明白ですが、探した範囲では、どこにも情報がありません。


解決方法

sendmailで拡張アドレスのデリミタを変更する方法がわからず、調査を続行することも、MTAをpostfix等にいまさら切り替えるわけにもいかず。。。
Win系以前は旧式、新形式は新世代だとわかりやすいのですが、K002とかが微妙な感じです。


あれやこれやテストを繰り返していたところ、ある法則を発見しました。

UserAgent

  • A5401CA
    • KDDI-CA23 UP.Browser/6.2.0.3.111 (GUI) MMP/2.0
  • W21S
    • KDDI-SN31 UP.Browser/6.2.0.7.3.129 (GUI) MMP/2.0
  • W31KII
    • KDDI-KC33 UP.Browser/6.2.0.9 (GUI) MMP/2.0
  • W41H
    • KDDI-HI36 UP.Browser/6.2.0.10.4 (GUI) MMP/2.0
  • W61T
    • KDDI-TS3I UP.Browser/6.2_7.2.7.1.K.1.5.1.120 (GUI) MMP/2.0
  • K002
    • KDDI-KC3O UP.Browser/6.2.0.15.1.1 (GUI) MMP/2.0
  • SH001
    • KDDI-SH38 UP.Browser/6.2_7.2.7.1.K.3.341 (GUI) MMP/2.0


よーくみるとUserAgentの規則が変わっています!

http://www.au.kddi.com/ezfactory/tec/spec/4_4.html
KDDIの仕様によると、ブラウザバージョンをしめす部分が変わっています。

  • 6.2.0.3.111
  • 6.2.0.7.3.129
  • 6.2.0.9
  • 6.2.0.10.4
  • 6.2.0.15.1.1
  • 6.2_7.2.7.1.K.1.5.1.120  !区切りがアンダーバーになってる
  • 6.2_7.2.7.1.K.3.341  !区切りがアンダーバーになってる

対策

ブラウザバージョンが \d.\d. (数字+ドット+数字+ドット)の場合だけurlencodeしてあげるようにしました。


うちでは、Ethna+Smartyなので、こーいうめんどくさいキャリアしばりは smartyのプラグインで回避しました。

<?php
/**
* Smarty修正子ラグイン
*/

/**
* mailtoで au旧端末で使えないプラス記号をエスケープする
*
* <pre>
* ex.)
*
* </pre>
*/
function smarty_modifier_mailtoescape($string)
{
    if (strlen($string)) {
        // + をエスケープするUA
        // KDDI-KC33 UP.Browser/6.2.0.9
        // KDDI-KC3O UP.Browser/6.2.0.15.1.1
        // そのままでOKなUA
        // KDDI-SH3K UP.Browser/6.2_7.2.7.1.K.5.205
        // KDDI-TS3I UP.Browser/6.2_7.2.7.1.K.1.5.1.120
        // 6.2の後ろがドットのみ置換
        if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('!^KDDI-[^ ]+ UP\.Browser/6\.2\.!', $_SERVER['HTTP_USER_AGENT'])) {
            $string = str_replace('+', '%2B', $string);
        }
    }
    return $string;
}

使い方

<html>
<head>
</head>
<body> <a href="mailto:{'[email protected]'|mailtoescape}">[email protected]</a><br />
</body>
</html> 

まとめ

auさん、仕様変えるなら言ってください。変えるとしても後方互換性を多少は気にしてください。
今回の件で言えば、docomo、softbankと同じように、プラス記号直書きでも、urlencodeした「%2B」でも動くようにしてもらえればすんだ話だと思うのは、考えが浅いだけでしょうか?


というわけで、auの新しい世代が出る前に作ったサイトで、空メールアドレスに拡張アドレスを使い、urlencodeしているサイトは、新端末で動いていないかもしれません。
逆に、auの新世代でだけ動作確認をしていると、旧端末で動いていないかもしれません。


最善の手は、postfixにして、デリミタはハイフンにすることだと思います。
sendmailは、他にも送信元情報等がphpで受けた時に環境変数で取得ができなかったりしたので、次回からはpostfixに絶対してもらおうと思います。