php > framework > symfony > plugin
このプラグインで日本語環境では一般的なJIS(iso-2022-jp)でのメール送信が簡単に行えます。
symfonyでは日本語でメールを送信することができますが、標準のsfMailクラスで日本語メール(iso-2022-jp)を送信しようとすると、毎回エンコーディングの変換処理を意識しなければなりません。そこで、標準のsfMailと同じ手順でエンコーディング処理まで行ってくれるsfMailクラスの拡張クラスであるjpMailを利用します。
また、symfonyは標準でテンプレートのビューをメールの本文として利用できるsendEmailメソッドがコントローラに用意されています。しかし、このメソッドはsfMailを強制的に利用するため、そのままでは本文部分がどうしてもiso-2022-jpに指定できません。そこで、jpMailを利用するようにしたjpMailViewクラスを用意しています。
プロジェクトルートディレクトリでsymfonyコマンドでプラグインをインストールします。 お使いのsymfonyのバージョンで使い分けてください。
$ symfony plugin-install http://develop.ddo.jp/symfony/jpMailPlugin-0.0.3.tgz
$ symfony plugin:install http://develop.ddo.jp/symfony/jpMailPlugin-0.1.0.tgz
また、symfony1.2以降ではPHPMailerがバンドルされていませんので、PHPMailerからダウンロードし、<アプリケーション>/lib/venderなどのautoloadされる領域に配置してください。
$ symfony plugin-upgrade http://develop.ddo.jp/symfony/jpMailPlugin-0.0.3.tgz
インストール後はプラグインが読み込まれるように、キャッシュをクリアします。
$ symfony cc
以下のようにアクションで簡単に日本語メール送信が行えます。
function executeSimpleSend() { mb_internal_encoding("UTF-8"); # UTF-8の場合 // class initialization $mail = new jpMail(); // definition of the required parameters $mail->setSender('webmaster_sender@example.com'); # Return-Path: $mail->setFrom('webmaster_from@example.com', 'ナナシさん'); # From: $mail->addReplyTo('webmaster_copy@example.com'); # Reply-to: $mail->addAddress('toaddress@example.com'); # To: $mail->setSubject(" メール送信テスト"); $mail->setBody("メール本文です"); $mail->send(); }
PHPMailerのバージョンが5.0以上の場合、'$mail→prepare()'を呼び出すとアクセス権のエラーが発生します。ソースを見る限りはsend()処理時にprepareで行っている処理は行われているので、$mail→prepare()を利用する必要はありません。
テンプレートをメール本文として指定するためには、アクション内でgetPresentationForメソッドを使用します。このときに第3引数にjpMailを指定することで日本語(iso-2022-jp)メールで送信が行えるようになります。
ただし、第3引数が有効になるのはsymfony1.0系までで1.1系以降では有効になりません。 そのため、1.0系と1.1系以降のそれぞれで説明します。
# 使用したいテンプレートを呼び出すためのモジュールとアクションを指定します
$this->getPresentationFor('モジュール', 'アクション', 'jpMail');
以下は、mailモジュールのindexアクションが呼び出されたときに、mailモジュールのsimpleSendアクションのテンプレートがメール送信に使用される場合の例です。
class mailActions extends sfActions { /** * ブラウザから呼ばれるアクション */ public function executeIndex(){ # メソッドの戻り値には送信したメールのヘッダ、本文をあわせた文字列です $raw_email = $this->getPresentationFor('mail','simpleSend','jpMail'); return sfView::SUCCESS; } /** * メール処理専用のアクション(内部からのみ利用されることを想定) */ public function executeSimpleSend() { mb_internal_encoding("UTF-8"); # UTF-8の場合 // class initialization $mail = new jpMail(); // definition of the required parameters $mail->setSender('webmaster_sender@example.com'); # Return-Path: $mail->setFrom('webmaster_from@example.com', 'ナナシさん'); # From: $mail->addReplyTo('webmaster_copy@example.com'); # Reply-to: $mail->addAddress('toaddress@example.com'); # To: $mail->setSubject(" メール送信テスト"); $this->mail = $mail; }
そして、テンプレートを用意します。
これはメール本文です。パーシャル、コンポーネントも利用できます。 レイアウトは使用されません。
# 使用したいテンプレートを呼び出すためのモジュールとアクションを指定します
$this->getController()->getPresentationFor('モジュール', 'アクション');
以下は、mailモジュールのindexアクションが呼び出されたときに、mailモジュールのsimpleSendアクションのテンプレートがメール送信に使用される場合の例です。
class sendmailActions extends sfActions { /** * ブラウザから呼ばれるアクション */ public function executeIndex(){ # メソッドの戻り値には送信したメールのヘッダ、本文をあわせた文字列です $raw_email = $this->getController()->getPresentationFor('mail','simpleSend'); return sfView::SUCCESS; } }
class mailActions extends sfActions { /** * メール処理専用のアクション(内部からのみ利用されることを想定) */ public function executeSimpleSend() { mb_internal_encoding("UTF-8"); # UTF-8の場合 // class initialization $mail = new jpMail(); // definition of the required parameters $mail->setSender('webmaster_sender@example.com'); # Return-Path: $mail->setFrom('webmaster_from@example.com', 'ナナシさん'); # From: $mail->addReplyTo('webmaster_copy@example.com'); # Reply-to: $mail->addAddress('toaddress@example.com'); # To: $mail->setSubject(" メール送信テスト"); $this->mail = $mail; }
そして、テンプレートを用意します。
これはメール本文です。パーシャル、コンポーネントも利用できます。 レイアウトは使用されません。
そして、jpMailViewクラスがmailモジュールで利用されるようにmodule.ymlを用意します。
all: is_internal: on view_class: jpMail
また、getPresentationForを使用した場合は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
上記例のままであれば、ブラウザから直接executeSimpleSendアクションを呼ばれた場合に、メール送信は行われなくても、画面にメール本文が表示されてしまうでしょう。このための対策として次の方法があります。
symfonyはモジュール単位でブラウザから直接呼ばれないように設定することができます。 たとえば、myMailモジュールを別途作成し上記のsimpleSendアクションを移動させ、
all: is_internal: on
とすれば、ブラウザからmyEmailモジュールは呼び出すことができなくなります。
わざわざモジュールに切り出すのもなぁ。。という場合で、セッションが利用できるのであればflash変数で制御するのが簡単です。
たとえば、上記例であれば以下のようにします。
class mailActions extends sfActions { /** * ブラウザから呼ばれるアクション */ public function executeIndex(){ $this->setFlash('is_call_simpleSend', true); $raw_email = $this->getPresentationFor('mail','simpleSend','jpMail'); ... 以下同じ ... } /** * メール処理専用のアクション(内部からのみ利用されることを想定) */ public function executeSimpleSend() { $this->forward404Unless($this->getFlash('is_call_simpleSend', false)); $this->setFlash('is_call_simpleSend', false); ... 以下同じ ... }
getPresentationForを呼び出す直前に、flash変数に呼び出し宣言のフラグ(is_call_simpleSend)を有効にしておきます。そして、呼び出されたsimpleSendアクションではフラグが有効かどうかを判断し、無効であれば404モジュールへフォワードします。 そして、有効だった場合は2度目の呼び出しが処理されないように、宣言を無効にします。