Bug(バグ) #1331
完了PHPのsafe modeを使用している環境でmail_envelope_fromを設定するとメールが送信できない
100%
説明
Overview (現象)¶
PHP の safe mode が有効な環境で、config/OpenPNE.yml の設定で mail_smtp_host を指定せずに mail_envelope_from を指定している場合に、招待メール送信などのメールを送信するアクションを実行すると 500 Internal Server Error が発生する。
エラー内容は以下の通り。
500 | Internal Server Error | Zend_Mail_Transport_Exception Unable to send mail
mail_envelope_from の設定をしていない場合は正常にメールが送信される。
CORESERVER Bプラン、OpenPNE 3.6beta11で現象を確認。詳細は note-12 のコメント。
Causes (原因)¶
safe mode が有効な状態で PHP の mail() 関数に第5引数を指定して実行しているため。
Way to fix (修正内容)¶
safe mode が有効かつ外部のSMTPサーバを利用しない( mail_smtp_host を指定していない)状態では mail_envelope_from の設定が利用できないことを前提とし、その説明を設定ファイルに加え、ソースコード上で safe mode の設定値を取得して有効な場合には mail_envelope_from を利用しないようにした。
元のバグ報告内容¶
http://sns.openpne.jp/communityTopic/6047
OpenPNE 3.5.2を利用していますが、 「友人を招待する」から招待メールを送信しようとすると、 メールアドレスと本文を入力する画面までは出るのですが、 「送信」ボタンを押すと、「500 Internal Server Error」となってしまいました。 デバッグモードで試してみても、Internal Server Errorの画面が出るだけでした。 これはバグなのでしょうか? どうか調査お願い申し上げます。 (1)OpenPNEのバージョン : 3.5.2 (2)サーバー情報 : 「CORESERVER.jp Bプラン」を使用 PHPバージョン:5.2.5 MySQL : 5.1.22-rc (3)エラー概要 : 招待メールを送信するとき、フォーム入力画面は表示されるが、「送信」ボタンを押すとInternal Server Errorとなる。
Shingo Yamada さんが13年以上前に更新
- ステータス を New(新規) から Accepted(着手) に変更
- 担当者 を Shingo Yamada にセット
調査します。
まず「CORESERVER.jp Bプラン」にて再現するかの確認を行います。
Rimpei Ogawa さんが13年以上前に更新
CORESERVER Bプラン
b33.coreserver.jp
CGI版PHP
OpenPNE 3.6beta11
で検証してみましたが、報告されている現象は再現できず、招待メールは正常に送信できました。
Safe mode が原因だとにらんでいたため、CGI版ではなくApacheモジュール版PHPで動かすつもりでしたが、以下のようなエラーが出たため一旦あきらめてCGI版で検証を進めました。
Warning: realpath() [function.realpath]: SAFE MODE Restriction in effect. The script whose uid is 10144 is not allowed to access /usr/local/lib/php owned by uid 0 in /virtual/***/lib/vendor/symfony/lib/util/sfToolkit.class.php on line 592 Warning: realpath() [function.realpath]: SAFE MODE Restriction in effect. The script whose uid is 10144 is not allowed to access /usr/local/lib/php owned by uid 0 in /virtual/***/lib/vendor/symfony/lib/util/sfToolkit.class.php on line 592 Warning: realpath() [function.realpath]: SAFE MODE Restriction in effect. The script whose uid is 10144 is not allowed to access /usr/local/lib/php owned by uid 0 in /virtual/***/lib/vendor/symfony/lib/util/sfToolkit.class.php on line 592 Fatal error: Uncaught exception 'sfCacheException' with message 'Failed to write cache file.' in /virtual/***/lib/util/opToolkit.class.php:569
CGI版PHP で動作させるために .htaccess に以下の記述を追加して動作確認しています。
AddHandler application/x-httpd-phpcgi .php
もし、なんとかして safe mode のままで動かしているのであればそれが原因かもしれません。
safe mode の方で動かせるかどうかもう少しやってみる予定です。
参考:
PHPをCGIとして動かす方法について - CORESERVER.JP:コアサーバー
http://www.coreserver.jp/help/index.php/phpcgi/
Rimpei Ogawa さんが13年以上前に更新
CORESERVER BプランのApacheモジュール版PHP(safe_mode=On)で検証した結果を報告します。
config/OpenPNE.yml で mail_smtp_host
を指定せず mail_envelope_from
を指定している場合のみ、メール送信時に以下のエラーが発生した。
500 | Internal Server Error | Zend_Mail_Transport_Exception Unable to send mail
mail_envelope_from
の設定をしていない場合は正常にメールが送信された。
エラーが発生した原因は、safe mode が有効な状態でPHP の mail() 関数に第5引数を指定して実行していることである。
これに関しては safe mode が有効かつ外部のSMTPサーバを利用しない( mail_smtp_host
を指定していない)状態では mail_envelope_from
の設定が利用できないことを前提とし、その説明を設定ファイルに加えるか、ソースコード上で safe mode の設定値を取得して mail_envelope_from
を利用しないようにするかのどちらかもしくは両方の対応をおこなうのが望ましい。
safe_mode による分岐条件を追加するための修正パッチ:
--- a/lib/util/opMailSend.class.php +++ b/lib/util/opMailSend.class.php @@ -32,7 +32,7 @@ class opMailSend $tr = new Zend_Mail_Transport_Smtp($host, sfConfig::get('op_mail_smtp_config', array())); Zend_Mail::setDefaultTransport($tr); } - elseif ($envelopeFrom = sfConfig::get('op_mail_envelope_from')) + elseif ($envelopeFrom = sfConfig::get('op_mail_envelope_from') && !ini_get('safe_mode')) { $tr = new Zend_Mail_Transport_Sendmail('-f'.$envelopeFrom); Zend_Mail::setDefaultTransport($tr);
ただ、safe mode が有効な環境での動作のためにはこのメール送信の問題以外にも、後述の「【補足2】CORESERVER の safe mode 下で OpenPNE を動作させるためにやったこと」の内容やその他にも対処が必要と思われるため、safe mode が有効な環境のみで発生する不具合をどこまで対応するかは検討が必要かもしれません。
CORESERVER においては、 note-11 に書いたように safe mode が無効な状態で動作させることも可能なため、このような環境では safe mode を利用しないことを推奨した方がよいと思います。
【補足1】CORESERVER の safe mode 関連の設定値
safe_mode | On |
safe_mode_gid | Off |
safe_mode_include_dir | /usr/local/lib/php |
safe_mode_exec_dir | /usr/local/php/bin |
safe_mode_allowed_env_vars | PHP_ |
safe_mode_protected_env_vars | LD_LIBRARY_PATH |
【補足2】CORESERVER の safe mode 下で OpenPNE を動作させるためにやったこと
- キャッシュディレクトリ下に作成されうるサブディレクトリをあらかじめ作成し、webディレクトリのPHPスクリプトファイルの所有者と一致させた
- safe_mode のファイルアクセスの制限を回避するため、キャッシュディレクトリ下に作成されうるすべてのサブディレクトリの所有者がwebディレクトリのPHPスクリプトファイルの所有者と一致している必要がある
- PHPスクリプトファイルの所有者がPHP実行ユーザーと異なる状態で動作させる場合、キャッシュディレクトリ下にあらかじめPHPスクリプトファイルの所有者がサブディレクトリを作成しておく必要がある
- 今回は招待メールの送信に必要なキャッシュディレクトリのみを事前に作成した状態で検証を行った
- ただし、この方法でOpenPNEの全機能を正常に動作させるためには、キャッシュディレクトリ下に作成されうるすべてのサブディレクトリを事前に推測する必要があり、非常に困難である
- PHPスクリプトファイルの所有者の方をPHPの実行ユーザーにする方法を取る場合
- CORESERVER においては Apache 経由でディレクトリ、ファイルの所有者を変更する必要がある(未検証)
- 初期状態の include_path が "." のみになるようにした
- CORESERVER 側の設定にあらかじめ含まれている
/usr/local/lib/php
への realpath() 関数の適用で Warning が発生したため - config/ProjectConfiguration.class.php の冒頭に以下の記述を追加した
set_include_path('.');
- CORESERVER 側の設定にあらかじめ含まれている
- セッションストレージの設定を DB に変更した(これはおそらく必須ではない)
# config/OpenPNE.yml session_storage: name: "database" options:
Rimpei Ogawa さんが13年以上前に更新
- 題名 を OpenPNE 3.5.2で招待メールが送信できません から PHPのsafe modeを使用している環境でmail_envelope_fromを設定するとメールが送信できない に変更
Subject および Description を更新
Shingo Yamada さんが13年以上前に更新
@Rimpei Ogawa
#note-12 に添付のパッチの適用をお願いします。
パッチの適用とともに、 safe_mode が有効な環境では mail_envelope_from の設定が無効になる旨を OpenPNE.yml.sample に追記する必要があります。
Rimpei Ogawa さんが13年以上前に更新
- ステータス を Accepted(着手) から Pending Review(レビュー待ち) に変更
- 進捗率 を 0 から 50 に変更
Kousuke Ebihara さんが13年以上前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 進捗率 を 50 から 70 に変更
Mutsumi Imamura さんが約13年前に更新
- ステータス を Pending Testing(テスト待ち) から Fixed(完了) に変更
- 進捗率 を 70 から 100 に変更