読者です 読者をやめる 読者になる 読者になる

終電23時15分って早くね?

都内のIT企業で働くカラオケ大好きエンジニアの雑記

Laravel4でローカル環境時でのメールログ出力のカスタマイズ

Laravel4では、ローカル環境時に(まぁそれ以外でもですが)
メールを送信せず、ログに出力するというオプションが備わっています。

■メール メールとローカル開発 - Laravel4 日本語ドキュメント
http://laravel4.kore1server.com/docs/mail#mail-and-local-development

app/config/mail.phpで、

'pretend' => true,

を設定する。

もしくは、

Mail::pretend();

をプログラム中に記述する。

という方法で、ログへの書き出しに変更できます。


ところで、どこに出力されるのか・・・?

pretendモードの場合、受取人に向け送信する代わりに、アプリケーションのログファイルに書き込まれます。

ということなのですが、具体的に「ここよ!」ってのが書いてなかったので、ちょっと探してしまいました。

とはいえ、

■エラーとログ ログ - Laravel4 日本語ドキュメント
http://laravel4.kore1server.com/docs/errors#logging

にも書いてある通り、

app/storage/logs

に、ログは出力されていたんですが、

[2013-07-27 19:40:51] log.INFO: Pretending to mail message to: foo@example.com [] []

この1文だけでした。
勝手に「タイトルとか本文とかもはいってるだろなーー」と思っていたので、
しばらく、ログが出てないじゃん!って右往左往してしまいました 笑


にしてもタイトルとか本文も確認したい。

ちょうどメールアドレス認証のようなことをやろうと思っていて、
「メール本文中に認証用URLをつけて、そこをクリックすると認証される。」
というようなことをやりたかったので、ログにも本文(+タイトル)を入れたいなぁと思ってソースコードを追ってみました。

するとメールのログ出力を行っている部分が、

vendor/laravel/framework/src/Illuminate/Mail/Mailer.php

の305行目

protected function logMessage($message)
{
    $emails = implode(', ', array_keys($message->getTo()));

    $this->logger->info("Pretending to mail message to: {$emails}");
}

で出力していました。上で記述したログとも文言が一致します。
ここらをゴニョゴニョすればいけるかなーという方針。



解決策その1

引数を配列で渡す。

$this->logger->infoのメソッドですが、
引数を追加することができます。

$this->logger->info("Pretending to mail message to: {$emails}", array( 'subject' => 'hoge' ));

http://laravel4.kore1server.com/docs/errors#logging

すると、出力されるログはこんな感じ。

[2013-07-27 19:50:28] log.INFO: Pretending to mail message to: foo@example.com {"subject":"hoge"} []

引数に渡す変数を事前に配列にして渡してあげると、

protected function logMessage($message)
{
    $emails = implode(', ', array_keys($message->getTo()));

    $context['subject'] = $message->getSubject();
    $context['body']    = $message->getBody();

    $this->logger->info("Pretending to mail message to: {$emails}", $context);
}

こんな感じでログが出力されるようになります。

[2013-07-29 20:05:01] log.INFO: Pretending to mail message to: foo@example.com {"subject":"テストタイトル","body":"テスト本文"} []

こんな感じで、タイトル、本文をログに出力できるようになりました。


解決策その2

解決策その1のようにメソッドに配列を渡せば、
それを自動的に展開してログ出力してくれるのですが、
正直自分的には見にくい!と感じたので、
最終的には下記のように修正しました。

protected function logMessage($message)
{
   
   $mail_info = "";
   $mail_info .= "■ To : " . implode(', ', array_keys($message->getTo())) . "\n";
   $mail_info .= "■ Subject : " . $message->getSubject() . "\n";
   $mail_info .= "■ Body : \n" . $message->getBody() . "\n";

   $this->logger->info("Pretending to mail message\n{$mail_info}");
}

ログ出力

[2013-07-29 20:12:39] log.INFO: Pretending to mail message
■ To : foo@example.com
■ Subject : テストタイトル
■ Body :
テスト本文
[] []

引数を渡す処理方法ではなく、
実際にメッセージを作ってそれを出力するという形にしましたとさ。

一応機能的には満足なんですが、
Laravel4のフレームワークのファイルを直接いじってしまっているので、
その部分だけ何とかしたいなぁ。。という感じだったのですが、
何かいい書き方がありましたらご教授願いたいです。

また、ログのフォーマット的にデファクトスタンダード的なものがあるのかなぁ・・・
とちょっと探してみたんですがそれも見つからなかったのでこんな感じになっています。。

そんな点で、ご指摘ある方はどしどしいただければと!!笑