Home > PHP
PHP Archive
PHPのmail()関数で日本語メールを送信するとSubjectの20文字目から文字化けする
- 2010-01-12 (火)
- PHP
PHPのmail()関数に渡すSubjectに漢字をMIMEエンコードしたものを渡すと、長いタイトルの時に20文字目から文字化けすることに気が付いた。
ターゲットはPHP 5.2.1。
問題のメールのSubject(タイトル)を生成する部分
これだと
「開発者ブログる。投稿者さんからメールテストです」
が20文字目から文字化けして以下のようになる。
「開発者ブログる。投稿者さんからメールテ9%H$G$9」
PHPスクリプトファイルはUTF-8。
mail()関数のバグの可能性もあると思ったが、
そろそろ枯れているはず(と思いたい)なので、調べてみた。
結論を書くと、mail()関数のせいではない。
mail()関数に渡すMIMEエンコードしたSubjectに問題があった。
つまりmb_encode_mimeheader()が原因である。
対処方法は以下のとおり。
次のようにmb_encode_mimeheader()を使う前に、internal_encodingを変更すると
正しくマルチバイト文字をエンコードできるようになった。
以下のブログが参考になった。
どうもありがとう。
PHPのmb_encode_mimeheaderは事前にmb_internal_encodingが必要
[編集履歴]
ターゲットはPHP 5.2.1。
問題のメールのSubject(タイトル)を生成する部分
$subject = mb_encode_mimeheader(mb_convert_encoding($subject, "ISO-2022-JP", "UTF-8"),"ISO-2022-JP","B","\r\n");
これだと
「開発者ブログる。投稿者さんからメールテストです」
が20文字目から文字化けして以下のようになる。
「開発者ブログる。投稿者さんからメールテ9%H$G$9」
PHPスクリプトファイルはUTF-8。
mail()関数のバグの可能性もあると思ったが、
そろそろ枯れているはず(と思いたい)なので、調べてみた。
結論を書くと、mail()関数のせいではない。
mail()関数に渡すMIMEエンコードしたSubjectに問題があった。
つまりmb_encode_mimeheader()が原因である。
対処方法は以下のとおり。
次のようにmb_encode_mimeheader()を使う前に、internal_encodingを変更すると
正しくマルチバイト文字をエンコードできるようになった。
$org = mb_internal_encoding(); // 元のエンコーディングを保存 mb_internal_encoding("ISO-2022-JP");// 変換したい文字列のエンコーディングをセット $subject = mb_encode_mimeheader(mb_convert_encoding($subject, "ISO-2022-JP", "UTF-8"),"ISO-2022-JP","B","\r\n"); mb_internal_encoding($org);// エンコーディングを戻す問題なくタイトルや長い文字列でもエンコードできるようになった。
以下のブログが参考になった。
どうもありがとう。
PHPのmb_encode_mimeheaderは事前にmb_internal_encodingが必要
[編集履歴]
- 2010-02-18 修正後のソース中、mb_convert_encoding中のsubjectに$が付いていなかったので付加
hetemlでupload_max_filesizeを変更
- 2009-06-18 (木)
- PHP
仕事でWebページ(ホームページ)の構築のお手伝いをしている。
私はプログラムが関係するところを担当している。
Webページから、自社商品の写真(でっかい写真もある)を登録すると、適切なサイズに縮小して、自動的に新商品ページや、該当カテゴリーページ、特記事項のページなどに掲載される。
商品を登録したら、あとは、システムが画面を作ってくれるので、手間がかからずラクチン。
自分の作ったプログラムが役に立つと思うと何か嬉しいものだ。
ページデザインもシンプルで、わかりやすく、使い勝手もよく、これは使える。(デザインは別の人の仕事だ)
さて、システム開発は社内のLinuxマシンで行ない、ひととおり動くようになってから、外部のレンタルサーバーで動作確認している。
多くの場合、うまくいくのが、そうでない場合もたまにある。そういう時は、思いがけないことだったりするわけだが。(今回の話ではないが、思えば、GD,socket,XMLを使いたいのにライブラリが入ってなかったり、.htaccessが置けなかったり・・・と様々なことがあった。)
さて、話を戻して
今回、レンタルサーバーでの動作確認は自社で契約しているレンタルサーバー ヘテムル(heteml)で行なった。
動作テストをしてみると、大きなファイルサイズがアップロードできない。
小さいサイズは問題ない。他に大きな問題はなさそうだ。
結論を言うと、upload_max_filesizeの値が”5M”と小さかったため、大きなファイルの転送ができなかった。
システムの既定値はこんな感じ。
デジカメで撮影した高画質版の場合には5Mを越えることもあるが、まあ、10Mもあれば十分だろうから、10Mにする。
まずは、php.iniの設定値を変更するため、ファイル「.htaccess」に次の記述を入れ、スクリプトのディレクトリに入れてみた。
php_value upload_max_filesize 10M
php_value post_max_size 16M
スクリプトを起動すると、
エラーページが表示され、プログラムは正常に動作しない。
ページの案内文に「ご利用中のユーザー様は 【 よくある質問 】 をご参照ください。」とあったので、参照してみた。
ふむふむ、きちんと説明がありました。
ヘテムル(heteml)では、.htaccessにphp_flag, php_valueで始まる設定はできない。
php.iniの設定をしたい場合は、コントロールパネルから行うようだ。
コントロールパネルにログインしてみてみると、
upload_max_filesize
が5Mから5M刻みで50Mまで設定できる。折角なので^^;、50Mにしてみよう。
さて、PHP4 / PHP5とも最大値の50Mになっているか、設定値を(ini_getで)確認してみた。
ばっちし、きちんと変更が反映されている。
これで、ファイルサイズの問題は解決しそうだ。
他の設定値を確認してみると、アップロードの実行時間(max_input_time)がデフォルトで60秒になっていた。
この値はコントロールパネルには項目がないし、もちろんini_set()でも設定変更ができない。
ADSL回線からアップロードする時は回線状況によっては低速やから、アップロード時間がかかることがある。
時間切れでアップロードできないことがあるかもしれない。
それだけ気になるが、まあよいでしょう。60秒でいったい何Mアップできるんやろ。
今回、調べていて設定値の大きさに関する次の式を見つけた。
memory_limit > post_max_size > upload_max_filesize
もともとの情報がファイルで情報伝送にあたってカプセル化され、カプセルの分だけ情報量が増えるので、その通りだと思う。
ちなみにヘテムル(heteml)の管理画面でいったんupload_max_filesizeを設定して元の値5Mにしてもpost_max_sizeはupload_max_filesizeと同じ値(5M)になる。
設定変更前はpost_max_sizeは8Mだったので、なんか少しまずいような気がする・・・
落ち着いたらレンタルサーバーのサポートに確認してみようと思う。
「そういう仕様です」 と言われたら、
「ハイ、そうですね」 としかいいようはないが・・・
ちなみに、スクリプトの実行時間(秒数)はphpスクリプトから
ini_set( ‘max_execution_time’, 60 );
で変更できる。デフォルトは30秒だった。
私はプログラムが関係するところを担当している。
Webページから、自社商品の写真(でっかい写真もある)を登録すると、適切なサイズに縮小して、自動的に新商品ページや、該当カテゴリーページ、特記事項のページなどに掲載される。
商品を登録したら、あとは、システムが画面を作ってくれるので、手間がかからずラクチン。
自分の作ったプログラムが役に立つと思うと何か嬉しいものだ。
ページデザインもシンプルで、わかりやすく、使い勝手もよく、これは使える。(デザインは別の人の仕事だ)
さて、システム開発は社内のLinuxマシンで行ない、ひととおり動くようになってから、外部のレンタルサーバーで動作確認している。
多くの場合、うまくいくのが、そうでない場合もたまにある。そういう時は、思いがけないことだったりするわけだが。(今回の話ではないが、思えば、GD,socket,XMLを使いたいのにライブラリが入ってなかったり、.htaccessが置けなかったり・・・と様々なことがあった。)
さて、話を戻して
今回、レンタルサーバーでの動作確認は自社で契約しているレンタルサーバー ヘテムル(heteml)で行なった。
動作テストをしてみると、大きなファイルサイズがアップロードできない。
小さいサイズは問題ない。他に大きな問題はなさそうだ。
結論を言うと、upload_max_filesizeの値が”5M”と小さかったため、大きなファイルの転送ができなかった。
システムの既定値はこんな感じ。
upload_max_filesize: | 5M |
post_max_size: | 8M |
デジカメで撮影した高画質版の場合には5Mを越えることもあるが、まあ、10Mもあれば十分だろうから、10Mにする。
まずは、php.iniの設定値を変更するため、ファイル「.htaccess」に次の記述を入れ、スクリプトのディレクトリに入れてみた。
php_value upload_max_filesize 10M
php_value post_max_size 16M
スクリプトを起動すると、
500 error Internal Server Error |
エラーページが表示され、プログラムは正常に動作しない。
ページの案内文に「ご利用中のユーザー様は 【 よくある質問 】 をご参照ください。」とあったので、参照してみた。
ふむふむ、きちんと説明がありました。
ヘテムル(heteml)では、.htaccessにphp_flag, php_valueで始まる設定はできない。
php.iniの設定をしたい場合は、コントロールパネルから行うようだ。
コントロールパネルにログインしてみてみると、
upload_max_filesize
が5Mから5M刻みで50Mまで設定できる。折角なので^^;、50Mにしてみよう。
さて、PHP4 / PHP5とも最大値の50Mになっているか、設定値を(ini_getで)確認してみた。
upload_max_filesize: | 50M |
post_max_size: | 50M |
ばっちし、きちんと変更が反映されている。
これで、ファイルサイズの問題は解決しそうだ。
他の設定値を確認してみると、アップロードの実行時間(max_input_time)がデフォルトで60秒になっていた。
この値はコントロールパネルには項目がないし、もちろんini_set()でも設定変更ができない。
ADSL回線からアップロードする時は回線状況によっては低速やから、アップロード時間がかかることがある。
時間切れでアップロードできないことがあるかもしれない。
それだけ気になるが、まあよいでしょう。60秒でいったい何Mアップできるんやろ。
今回、調べていて設定値の大きさに関する次の式を見つけた。
memory_limit > post_max_size > upload_max_filesize
もともとの情報がファイルで情報伝送にあたってカプセル化され、カプセルの分だけ情報量が増えるので、その通りだと思う。
ちなみにヘテムル(heteml)の管理画面でいったんupload_max_filesizeを設定して元の値5Mにしてもpost_max_sizeはupload_max_filesizeと同じ値(5M)になる。
設定変更前はpost_max_sizeは8Mだったので、なんか少しまずいような気がする・・・
落ち着いたらレンタルサーバーのサポートに確認してみようと思う。
「そういう仕様です」 と言われたら、
「ハイ、そうですね」 としかいいようはないが・・・
ちなみに、スクリプトの実行時間(秒数)はphpスクリプトから
ini_set( ‘max_execution_time’, 60 );
で変更できる。デフォルトは30秒だった。
- Comments (Close): 0
- Trackbacks (Close): 0
ホーム > PHP