そろそろ本格的に symfony を...と勉強を始めて2日目。情報を漁っていくうちにメール周りがだいぶ面倒くさいことを知ったので、勉強がてらおやぢ組さんの jpMailPlugin に手を入れてみました。
調べた結果わかったこと
- 今後はPHPMailerでなくSwift Mailerに切り替わっていく → MLのログ
- jpMailPluginはsymfony1.1.5に対応してないっぽい&これから作ろうとしてる
- sfMailerを使う場合はsettings.ymlのcompat_10をonにしないとだめ
- sfMailerを使うとcontroller::sendEmail()でエラーログを吐く。なんか気持ち悪い
- sfMailerを使うとメール送りたいだけなのにHTTPヘッダが出てる。なんか気持ち悪い
調べた結果予想できたこと
"俺たちはSwift Mailerが使いたいんじゃない、PHPMailerが使いたいんだ"
"俺たちはSwift Mailerが使いたいんじゃない、PHPMailerが使いたいんだ"
"俺たちはSwift Mailerが使いたいんじゃない、PHPMailerが使いたいんだ"
...symfonyのメール周りで悩んでる(日本語圏の)人の多くが思っていそうだった。
目標にしたこと
- 慣れてるsfMailer / PHPMailerが使える
- compat_10がoffでも使える
- controller::sendEmail()でエラーログを吐かない
- HTTPヘッダは出さない
ということで、おやぢ組さんの jpMailPlugin をベースにsymfony1.1.5に対応して作ってみたプラグインはこちら。パッケージ方法がよくわからないので、とりあえずアーカイブで。
※制限事項として、メール処理を一つのモジュールに集約した場合しか動作確認してないというのがあります。
以下、アプリケーション名をfrontend、メール関連モジュールをmailとしてざっくり解説してみます。
インストール方法
plugins以下にjpMailPluginディレクトリを作って展開。
設定方法
apps/frontend/config/factories.yml に以下を追記
all:
controller:
class: sfFrontWebJpMailController
apps/frontend/modules/mail/config/module.ymlに以下を追記
all: is_internal: on ← 必要であればこれも view_class: jpMail
apps/frontend/modules/mail/config/view.yml に以下を追記
all: has_layout: off
呼び出し側
アクション(apps/frontend/modules/default/actions/actions.class.php)
public function executeIndex($request)
{
$this->getController()->sendEmail('mail', 'index');
}
呼び出される側
アクション(apps/frontend/modules/mail/actions/actions.class.php)
public function executeIndex($request)
{
$this->hoge = 'ほげ~';
$this->mail = new jpMail;
$this->mail->initialize();
$this->mail->setFrom('info@example.com', '山田 太郎');
$this->mail->setSubject('お問い合わせありがとうございました');
$this->mail->addAddress('info@example.net', '山田 花子');
}
テンプレート(apps/frontend/modules/mail/templates/indexSuccess.php)
メール本文がここに。
変数が使える。
<?php echo $hoge ?>
パーシャルも。
<?php include_partial('signature') ?>
内容物の解説
jpMailPlugin/config/config.php
$sf_symfony_lib_dir/plugins/sfCompat10Plugin/confg/config.php から必要そうな箇所だけ持ってきました。
<?php
// register config handler for config/mailer.yml files
sfProjectConfiguration::getActive()->getConfigCache()->registerConfigHandler('modules/*/config/mailer.yml', 'sfDefineEnvironmentConfigHandler', array('prefix' => 'sf_mailer_', 'module' => 'yes'));
jpMailPlugin/config/mailer.yml
おなじみのmailer.yml。apps/frontend/modules/mail/config/mailer.ymlでオーバーライドできます。
default:
deliver: on
mailer: smtp
domain: localhost.localdomain
hostname: localhost
port: 25
username: ''
password: ''
wordwrap: 0
.headers:
priority: 3
content_type: text/plain
charset: iso-2022-jp
encoding: 7bit
jpMailPlugin/lib/controller/sfFrontWebJpMailController.class.php
sfFrontWebController から sendEmail() だけオーバーライドしました。
- エラーログを吐かない(infoログを吐く)
- HTTPヘッダを出さない
に対応してます。
2つめのやつが厄介でしたが、sfWebResponseを見る限りではメール送信処理中のみsf_testをtrueにすればHTTPヘッダが出ないようなので、トリッキーですがgetPresentationFor() の間だけsf_testをtrueに設定するようにしてみました。
根本的な解決策はmailモジュールのときだけresponseオブジェクトをsfWebResponse以外のものに変えることでは?と思いはしたものの、factories.ymlでモジュールごとにresponseオブジェクトを変える方法がわからず...そもそもモジュールごとに変えられるような設計じゃないような気も...
<?php
/**
*
* @package jpMail.plugin
* @subpackage controller
* @author Yoshinori Ishii <ishii.yoshinori@itra.jp>
*/
class sfFrontWebJpMailController extends sfFrontWebController
{
/**
* Sends and email.
*
* This methods calls a module/action with the sfMailView class.
*
* @param string $module A module name
* @param string $action An action name
*
* @return string The generated mail content
*
* @see sfMailView, getPresentationFor(), sfController
*/
public function sendEmail($module, $action)
{
if (sfConfig::get('sf_logging_enabled'))
{
$this->dispatcher->notify(new sfEvent($this, 'application.log', array('sendEmail method called')));
}
$sf_test = sfConfig::get('sf_test');
sfConfig::set('sf_test', true);
$retval = $this->getPresentationFor($module, $action);
sfConfig::set('sf_test', $sf_test);
return $retval;
}
}
jpMailPlugin/lib/vendor/phpmailer/*
PHPMailerがゴソっと入っています。class.pop3.phpはいらないかな...
jpMailPlugin/lib/view/jpMailView.class.php
symfony1.1.5の $sf_symfony_lib_dir/plugins/sfCompat10Plugin/lib/view/sfMailView.class.php の 'sfMail' を 'jpMail' に変えてコメントをいじりました。
jpMailPlugin/lib/jpMail.class.php
jpMailPluginのものをそのまま持ってきました。
jpMailPlugin/lib/sfMail.class.php
$sf_symfony_lib_dir/plugins/sfCompat10Plugin/lib/sfMail.class.php のものをそのまま持ってきました。
お願い
個人的にはjpMailPluginの新バージョンの元ネタにでもなったらいいなと思っています。が、ライセンス的なものを全く考慮せずにいろんなところからコードを持ってきているので、コレやっちゃダメなどとご指摘いただけると助かります。
また、symfonyの作法的にNGだろ、という事をやってましたら教えて頂けると助かります。

1.1対応ありがとうございます。
これで1.1版は大丈夫ですね。
でも、1.2になるとgetPresentationForメソッドが廃止されているんですよね。。どうしたものやら^^;
コメントありがとうございます。
ちょうど今、メール送ろうと書いていた最中でした…
symfony1.2だとgetPresentationFor()がなくなっちゃうんですか。それはマズい。これから1.2を入れてこねくりまわしてみます。
おっと、廃止されたのではなくControllerに移ったんですね。失敬 ><
あ、じゃあ1.1系と同じだから問題なさそうですね。
となると、1.0系で動かないのか…
バージョンを見て、sfFrontWebJpMailController::sendEmail()内でコールするgetPresentationFor()を変えればよさげですね。
あ、controllerでactionインスタンスってどうやってアクセスすればいいんだろう…?