ようこそゲストさん

CPA-LABテクニカル

メッセージ欄

2008年7月の日記

2008/07/28(月) でるわでるわ伝説

Qdmailバージョン1系にて、バージョン0系のユーザーインタフェイス系のコードを見直している。

そこで驚愕の事実がっ!

続きを読む

2008/07/26(土) Qdmail 1系の開発に着手

おかげさまで、Qdmailは、ある程度の方々に使っていただいているようです。
機能的には問題ないと思うのですが、ユーザーインタフェイスに若干難がある部分があります。
ここでむやみに変更するとバージョンによって、引数の指定方法が変わったりしてしまうので、いったんバージョン0系は開発終了とし、新たなメジャーバージョンアップとして、バージョン1系に移行しようかと思っています。

もし、こんな機能が欲しい、いらない、というのがあればぜひお教え下さい。

バージョン0系からバージョン1系への変更点(予定)

  • qd_send_mail()関数の新設
  • easy * での引数指定の変更 array('address@example.com','日本語名')方式に統一。
  • replace機能の廃止

qd_send_mail

オブジェクト指向って何?という方のために、単純な関数形式を提供します。
例え、オブジェクト指向をわかっている方でも、たぶんこれを使ったほうが簡潔なプログラムがかけるようになると思います。
これがバージョン1系の一番の目玉です。

実は0系でもコードは埋め込んではいるのですが、正しく動作しない状態です。これを完成させたいと思っています。

引数指定の変更

これまで、easyText()などのeasyシリーズではメールアドレスにつける日本語名について
$mail -> easyText('address@examplle.com','日本語名',......)
という指定方法ですが、これだと、日本語名を指定しない場合は、
$mail -> easyText('address@examplle.com',null,......)
と、nullを置く必要があり、ちょっとスマートではありませんでした。
そこで、配列の要素0にはメールアドレス、要素1には、マルチバイト日本語名、とし、マルチバイト日本語名を指定しない場合は、配列でなくてもいいようにします。
つまり、通常はこのような指定方法になります。
$mail -> easyText(array('address@examplle.com','日本語名'),......)
日本語名が必要ない場合は、
$mail -> easyText('address@examplle.com',......)
となります。
こうすることで、第1引数が to ヘッダがらみ、ということになりすっきりします。

また複数指定するときは、
$to[]=array( 'address1@example.com' , '日本語名1');
$to[]=array( 'address2@example.com' , '日本語名2');

$mail -> easyText( $to ,......)
という感じになる予定です。

replace機能の廃止

マニュアル化もしていなかったので、たぶん使っている人はほとんどいないreplace機能を廃止しようかと思っています(まだ迷っているけど)。
これを実現するのは結構面倒&使っている人少ない、のであれば廃止しようかと。

というわけで、こんな方針でバージョン1系の開発を進めたいと思います。

2008/07/19(土) 0.9.0になったQdmail

はてなブックマークの情報 はてなブックマークに登録 はてなブックマーク数 qdmailspok
おかげさまで、先日、高機能日本語メールライブラリQdmailは、0.9.0aになりました。それなりに使えるようになっていると思います。

次回のメジャーバージョンアップでは、現在、qd_send_mail() としても使用できるよう、鋭意作業中です。

しかし、そのためには、若干、パラメータの指定方法を変えなければならない事態になりそうで、迷っています。Dynamic Drawの品格でも述べたように、ユーザーインタフェイスは、なるべく変えないほうがいいのはわかっているのですが。。。。
こういう設計は、もっと入念にやっておくべきでした。

2008/07/19(土) iPhoneのメールは一体どうなってしまうの

iPhoneは個人的には魅力はないけれども、Qdmailとしては対応しておきたい。
2年縛りの端末を契約する気になれないのだけど、誰かiPhone貸してくれないかな~。

iPhoneメールについては下記サイトの方々が大変詳しく調べているのだけれど、やっぱり実機がないとわからない部分もあり、どうしましょうかね~。

【iPhone 3Gまとめ】メールはiPhone1台で複数アドレスを利用可能!-め~んずスタジオ - me-n's STUDIOさんによると、@i.softbank.jpでは、デコメの一部については受信可能とのこと。


iPhoneのメール全般については、こちらが詳しい。
iPhoneについて知っておくべきこと【メール編】-MOBILE POWER feat. iPhone

2008/07/13(日) Dynamic Drawの品格

知る人ぞ知る有名ソフトDynamic Draw

Dynamic Draw Professional

図を書くときにいつも使わせてもらっています。
とにかく操作が直感的なので、たいへん便利。
recursiveの正しい理解CakePHP」の図も、Dynamic Drawを使わせていただいています。

こちらの作者さんは、利用者の事を真剣に考えており、とても頭が下がります。
「直感で使える」というつくりにするのは、かなり大変だと思います。こうしたヒューマンインターフェイスが、ソフト設計では重要ですね。
これだけ便利なフリーソフトを提供していれば、様々な質問も来るかと思うのですが、それにとても丁寧に対応しています。
真に技術力のある方は、品格もあるということでしょう。

Qdmailシリーズも、メソッドを呼び出す時の引数の型や、並び順などにかなり気をつけているつもりなのですが、今から思えば、「しまった、別の指定方法の方がよかった」と思う部分もけっこうあります。しかし、一度リリースすると、インターフェイス部分は修正するのは、かえってユーザーを混乱させることになるため、なかなかできないんですね~。
ソフト内部は
結果が速く正しくでれば、構造、アルゴリズムや内部的なインターフェイスはどうでもいい。
ということなんでしょうけれども、
対人間部分は
体系的で理解しやすく、『変わらないこと』
が重要だと思うのですね。だから、ソフトの設計では、中身よりも、対人間部分を事前に検討することが大事なのでしょうね。
プロの方にとっては当たり前なのでしょうけれども、私のような者がソフトを作ると、どうしても作者オリエンティッドな、ユーザーを考えないインタフェイスを作りがちなんですよね。

こちらが処理しやすい入力をユーザー負担で求めてしまうのです。

なんせ、
人間にとって使いやすい入力 → コンピューターにとって扱いやすいパラメータ
というヒューマンインターフェイス部分は、プログラマにとって相当の負担だろうな、と思います。

Qdmailは、そのコードの約半分を構造的には本筋ではない、ユーザーからの入力対処&パラメータ分析に使っています。

ユーザーがプログラマでない一般ユーザーの場合は、プロトタイプをなるべく早くリリースしてユーザーからのフィードバックを得るというのは、大事なのでしょうね。
Qdmailは、対プログラマ相手なので、一般ユーザーほどシビアではないと思うのですが、それでもやはりライブラリとして統一感のあるインタフェイスを提供できているかというと、ちょっと反省点があります。


私が品格なぞ語ってはいかんのですが。
タイトルは「ホッテントリメーカー」でいただきました。

関連リンク
ファンクラブ
使い方事例
窓の杜レビュー

# tkk 『http://o-server.main.jp/dynamicdraw/set.html チップセット公開しています。』 (2008/10/06 12:24)

  • 0.9.0になったQdmail CPA-LABテクニカル spok
    おかげさまで、先日、高機能日本語メールライブラリQdmailは、0.9.0aになりました。それなりに使えるようになっていると思います。次回のメジャーバージョンアップでは、現在、qd_send_mail() としても使用できるよう、鋭意作業中です。しかし、そ...

2008/07/07(月) 今の新参は昔のホッテントリを知らないから困る

新参者のスポックです。
はじめて知りましたホッテントリメーカー。すごくおもしろいです。。。
ホッテントリメーカー

このタイトルは、ホッテントリメーカーでいただきました。。。。

qdmailでやってみたら、、、、
  • 文系のためのqdmail入門 46 users(推定)
  • 本当にヤバいqdmailの脆弱性3つ 5 users(推定)
  • qdmailにありがちな事
  • qdmail信者が絶対に言おうとしない3つのこと 10 users(推定)
  • リア充がひた隠しにしているqdmail 15 users(推定)
  • 全てを貫く「qdmail」という恐怖 
hal456でやってみたら、、、
  • モンスターペアレントからの視点で読み解くhal456 532 users(推定)
  • これは凄い! hal456を便利にする33のツール 9 users(推定)
  • hal456で年収が10倍アップ

おもしろすぎます。
Cake PHPで制作したそうで。。。。

2008/07/05(土) PHPでPOP受信サーバー操作

メールの受信(POP)サーバーの操作ライブラリ&マルチバイトメールデコーダーのご紹介。

簡単受信サーバー操作ライブラリQdmailReceiver
hal456トップページ

応用すれば、こんなことができます

  • 空メール処理
  • ブログへのメール投稿
  • Spamフィルター
  • gmailライクなWEBメール

もちろん、QdmailReceiverは、メールを解析したり、POPサーバーを操作するライブラリなので、上記のことをやろうと思えば、他に自分でプログラムを組まなくてはなりません。
しかし、マルチバイト(日本語処理)やメールの解析処理は意外にやっかいなので、それをQdmailReceiverに任せていただければ、かなり労力半減することでしょう。

2008/07/02(水) CakePHP(RC1.2)のemailコンポーネントで日本語はまだ厳しい

はてなブックマークの情報 はてなブックマークに登録 はてなブックマーク数 cakephpspok

CakePHP(1.2RC2)のemailコンポーネント評価

CakePHP 1.2 RC2 がリリースされたので、新しいemailコンポーネントを評価してみた。全般的に言えば、改行コード&英文周りはかなり改善されており、英語メールを送る分には、大丈夫かと思う。
しかし、一部でマルチバイト非対応となっており、日本語の場合、若干の問題点がある。
  1. Content-Transfer-Encoding:ヘッダーは7bit固定&charsetはutf-8なので、charsetをiso-2022-jpに変更し、本文、ビュー、レイアウトのすべてを自前でiso-2022-jpに変換する必要がある。*1
  2. ワードラップ処理がマルチバイト非対応
    __wrapメソッドがマルチバイト非対応なので、文字化けする可能性が大きい。また、「日本語文字列のバイト数取得にstrlenだけではダメな理由-PHP」でも述べたとおり、マルチバイト環境では、文字列のバイト数を得るのに、strlenだけを使うのは、問題がある。
  3. MIMEエンコードが、マルチバイト文字の途中で強制改行される可能性のあるスクリプトとなっており、長いsubject&Gmailやbeckeyでタイトルが文字化けする可能性が大きい。*2
  4. qmail用がデフォルト?
    mail関数で送る際には、MTAがqmailであればLF,qmail以外のsendmailやPostFixであれば、CRLFである必要があるが、LFがデフォルトとなっている。
    これはこれで賢いやり方で、CRLFをデフォルトにするとqmailの時にエラーがでるけれど、LFがデフォルトであれば、sendmailやPostFixがエラーを出すことはないだろうからだ。
  5. SMTP送信の場合、 名前<address@example.com> の形式が使えず、<address@example.com> というメールアドレスのみのヘッダーとなる。
    う~ん。どうしてこうしたのでしょうかね。

その他の制約

  • 本文base64エンコードできない。
  • Quoted-Printable非対応
  • デコメ送信不可能*3
  • MHTL(インラインHTML)メール不可
  • 添付ファイルの日本語不可

全般的な感想

相当がんばれば、デフォルトでも日本語は送れないことはないと思うけど、メールひとつ送るのに、がんばりたくないでしょ。

う~ん。mb_send_mail単体のほうがましかな。

Qdmailなら。。。。

高機能マルチバイトメールライブラリQdmailなら、CakePHPのコンポーネントとしても動作します。
上記のemailコンポーネントの弱点はすべて克服されておりますので、一度お試し下さい。

*1 : 7bitなのに、8bitコードのUTF-8をデフォルトにするのはよくないです。。。

*2 : 私もハマったところ

*3 : これは仕方ないよね

2008/07/01(火) mb_encode_mimeheaderの都市伝説を検証する

はてなブックマークの情報 はてなブックマークに登録 はてなブックマーク数 php5spok

mb_encode_mimeheader都市伝説

mb_encode_mimeheaderは、なんか使いにくい。文字化けする。とあまり良い評判を聞きません。私も、「使うのはちょっと怖いな」と思っていました。しかし、mb_encode_mimeheaderは正しく設定すれば、きちんと働いてくれます。それを検証したいと思います。

間違ったバッドノウハウ

mb_encode_mimeheaderの有名なバッドノウハウに
PHPmb_encode_mimeheaderは事前にmb_internal_encodingが必要-akiyan.com
というのがあります。その中身は
PHPのmb_encode_mimeheader関数で文字列をエンコードするときは、直前にmb_internal_encoding関数で変換したい文字列のエンコーディングをセットしてから呼ばないとうまく動作しないもよう。エンコードした文字列の後ろのほうが化け化けになってしまう。
というものです。
そして、
// 元のエンコーディングを保存
$orgEncoding = mb_internal_encoding();
// 変換したい文字列のエンコーディングをセット
mb_internal_encoding($targetEncoding); 
// エンコーディング実行
$encodedString  = mb_encode_mimeheader($targetString, $targetEncoding, 'B', "\n");
// 保存しておいたエンコーディングに戻す
mb_internal_encoding($orgEncoding); 
というコードが掲載されています。
それを検証しようとした、
mb_internal_encoding()は必須か?」に対しての疑問と検証-よくきたblog
というのもあります。

しかしながら、このバッドノウハウは間違っており、検証した方も、残念ながら、検証になっていません。

正しいバッドノウハウ

そこでPHP5.2.4のソースコードを読みつつ、動作検証をしてみました。
その結果、mb_encode_mimeheaderを使う時の正しいバッドノウハウは、
mb_encode_mimeheaderに渡す文字列の文字コードとmb_internal_encodingは一致させておかなければならない。
というものです。
必ずしも、最終のターゲットエンコーディングとmb_internal_encodingを一致させる必要はありません。
ん、最初のノウハウと何が違うのかって?
次章でよ~く考えてみましょう。

結論から

文字コードが3つでてきますので、整理しましょう。
  1. mb_internal_encodingの文字コード
  2. mb_encode_mimeheaderに渡す文字列の文字コード
  3. mime変換する最終文字コード
この中で、1と2が一致している必要があるだけであって、3は独立していてOKです。
2→3の文字コード変換は、mb_encode_mimeheaderがきちんとやってくれます。
正しくいえば、mb_encode_mimeheaderは「2の文字コードは1と同じであるとして、1→3のパラメータでもって、2の文字列を変換」します。つまり、 

mb_convert_encoding($word,$target_encoding,mb_internal_encoding());

という動作が、mb_encode_mimeheaderには含まれています。
(特殊な条件の時のみ、無変換となる)
間違っているバッドノウハウは、1と3を一致させようというもので、2についての言及がありません。偶然に2についても同じ文字コードであれば文字化けすることはないのですが、2が(1,3)と違うコードの場合、正しくエンコードされません。
1=2となるように、文字コードを設定しましょう。
(さらに、mb_languageもjaに設定しておけば間違いがありません。)

本来は、mb_encode_mimeheader関数にて 2の「渡す文字列の文字コード」を指定できるような仕組みがあればいいのですが、残念ながらそうなっていません。
1のmb_internal_encodingを指定することで、2の「渡す文字列の文字コード」を間接的に指定することになります。
この結論は、下記テストコードと、PHP5.2.4本体のmb関係のソースを読んでのことですが、C言語のソースは私も理解できない部分もあり、結論が間違っている可能性もあるかも知れません。その際はご指摘いただければ幸いです。

テストコード

続きを読む

長文でテストしてみる。

続きを読む

PHPの本体コードを読んでみる。

続きを読む

WEB上の間違った情報(主なもの)

以下は、googleで、mb_encode_mimeheader のキーワードで検索した時に、比較的上位に出てくるページや、他に多く引用されているページにつき、私の見解を書いています。決して、けなしているわけではありません。ただ、私の得た結論が正しいとするならば、間違った情報をそのままにしておくと、また私のような無駄な時間を費やしてしまう人がでてくるであろう、という予測のもとに、「この情報は私が正しいと思う結論に対して、間違っている」ということを指摘するものです。
PHPのバージョン違いによるものもあるかも知れません。私が検証したのはPHP5.2.4ですので、それより前のPHPでは挙動が違うのかも知れません。(一応、PHP4.4.7でもテストコードを動かしてみて、結論は変わらないという心証はえているのですが、4.4.7についてはPHPソースまでは読んでいません。)
またPHP5.2.4であっても私の見解が間違っている可能性もあります。その際は、ご指摘いただければ幸いです。

この記事の冒頭で紹介したページです。1=3という間違った結論です。多くのWEBサイトがこのページを引用しています。この記事のバージョン5.1.2ではこうだったのでしょうか?
私と同様の疑問を持ち、akiyan.comさんの記事を検証しています。しかし、環境が、internal='euc-jp',input='utf-8',target='utf-8'では文字化け、internal='utf-8',input='utf-8',target='utf-8'で文字化けなし、ということを検証しているのみで、十分ではありません。
1=2=3と設定しないと文字化けする、という間違った情報です。丁寧に「mb_encode_mimeheader() ですが、文字コードの変換まではしてくれない為」と書かれていますが、これも間違いです。上のほうに書いたように、むしろ原則として、文字コードの変換をします。

非常に有益なテストコードです。この記事の次の記事の方が
しかも、これらの結果が異なるんですね。
mb_encode_mimeheader($str, 'ISO-2022-JP');
mb_encode_mimeheader(mb_convert_encoding($str,'JIS','EUC'),'ISO-2022-JP');
と述べていらっしゃいますが、mb_internal_encoding('EUC-JP');なので、スクリプトをEUC-JPで保存していれば、上段は1=2となり正常稼働しますが、下段は1≠2なので当然文字化けします。もし、このスクリプトをUTF-8で保存して実行すれば、上段も文字化けするでしょう。
また、同じスレッドで、
mb_encode_mimeheader 自体は、文字コードの変換はしてくれないと思っていたんですが。
という発言もありますが、このように思っている人は多いのではないでしょうか。
繰り返しになりますが、原則として文字コードの変換がなされます。

こちらは逆に、「mb_encode_mimeheader()に渡す文字列はISO-2022-JPに変換するな。」という結論を導いていらっしゃいますが、間違いです。最初のスクリプトが、1≠2になっているだけであり、2=iso-2022-jpとしているからではありません。しかも、次のスクリプトでは、1=2=iso-2022-jp と設定し、結果も正しいのに、「mb_encode_mimeheader()に渡す文字列はISO-2022-JPに変換するな。」というのは、論理的に正しくありません。mb_encode_mimeheader()に渡す文字列はISO-2022-JPに変換しても、1=2を守る限り大丈夫です。

正しい考察
PHPのmb_encode_mimeheaderは事前に-ryuzi_kambe の?D
こちらは、私と同じ結論です。そちらにも書いてある通り、mb_encode_mimeheaderに”from-encoding”を指定するパラメータがないのが、混乱のもとになっていると思います。

混乱する考察
mb_encode_mimeheaderについては、そのソースコードのエンコードを書いていないスクリプトの場合、情報が不足するため混乱の元となります。mb_encode_mimeheaderに言及する多くのWEBサイトでは、ソースコードの文字コードに触れおらず、暗黙のうちにEUC-JPやShift_Jisが前提だったりします。
おまけに、inputされる文字列の文字コードさえも記載のないページもあります。
そのようなページはあまりに多いので、ここでの引用は省略します。

開発者さま

ぜひ、このようなバッドノウハウをなくすために、mb_encode_mimeheaderにて、引数に渡す文字列のエンコードであるfrom-encodingを指定できるようにお願いいたします*2
たったこれだけで、この大混乱を収束することができます。。。


しかしながら、マルチバイト関係のPHP本体のソースをみると、すごく複雑です。c言語で、マルチバイトを自在に処理するのは至難の業ですね。mb_convet_encodingをおっかけると、あの組み合わせの多さに、それだけで萎えてしまいます。それに果敢に挑戦された開発者の方はすごいです。mb*関係に係わった関係者の方々に感謝と尊敬の意を表します。


*2 : こういうのってどこに要望ださばいいのだろう

# ELF 『よくきたblogな人ですが,私の件の記事は網羅性は高くないです. もっと細かいことを書いたものがありまして,「超・極める! PH...』 (2008/07/15 17:01)

# spok 『ELFさん はじめまして。プロの方からコメントをいただけて光栄です。 私の記事が間違っていなかったようで安心しております。 さっ...』 (2008/07/17 24:22)