現在進行形で嵌っているのですが、原因はともかく朧気ながら状況が把握できてきたので自分的まとめ。


やりたいこと: sfMailクラスにGMailのSMTPを設定してメールを送信したい

処理としては特に難しいことではありません。
適切に設定すれば動く…はず。



問題点その1: PHPMailer 1.7系では上手く動かない

「The following From address failed」エラーが出てメール送信処理が止まります。

sfMailクラスはPHPMailerのラッパークラス。

なので別にPHPMailerを持ってきて送信テストをしてみると… → 送信OK。GMailの設定自体は合ってる。
Symfony1.0のsfMailクラスはPHPMailer 5.1系ではなくPHPMailer 1.7系を使っているのでそれが問題っぽい。
(そういえば前任者がPHPMailer 5.1系を使おうとした形跡がある(コミットログを読んだ))



問題点その2: sfMailクラスの二重呼び出し

というわけで、sfMailクラスをカスタマイズ。
1.7系と5.1系の互換性に自信が持てなかったので、コンストラクタに引数を渡してこんな感じに。

public function __construct($php5=true)
{
  if($php5):
    require_once(sfConfig::get('sf_symfony_lib_dir').'/vendor/phpmailer/class.phpmailer.php');
    require_once(sfConfig::get('sf_symfony_lib_dir').'/vendor/phpmailer/class.smtp.php');
  else:
    require_once(sfConfig::get('sf_symfony_lib_dir').'/vendor/phpmailer/5.1/class.phpmailer.php');
    require_once(sfConfig::get('sf_symfony_lib_dir').'/vendor/phpmailer/5.1/class.smtp.php');
  endif;
  $this->mailer = new PHPMailer();
}

この状態でアクションから直接送信してみる → 送信OK。
ところが他のアクションからsendEmail()を使って送信してみる → 画面が真っ白に。

メッセージを表示せずに落ちるのは大体、引数のタイプヒンティングか同じクラスを呼び出そうとしてるか。
sendEmail()を読んでみると、getPresentationFor()を使ってsfMailViewクラスを呼び出してるらしい。

sfMailViewクラスのレンダリングの中でnew sfMailer()してる個所を発見。
当然引数無しで呼び出されているので1.7系が重ねてrequireされる → クラス名重複 → エラー


工エエェェ(´д`)ェェエエ工



ここまで書いて思いついたので、以下追記。



結論: クラス「PHPMailer」のチェックを行う

sfMailクラスのコンストラクタをさらにカスタマイズしてこんな感じに。

public function __construct()
{
  if(!class_exists('PHPMailer', false)):
    require_once(sfConfig::get('sf_symfony_lib_dir').'/vendor/phpmailer/class.phpmailer.php');
    require_once(sfConfig::get('sf_symfony_lib_dir').'/vendor/phpmailer/class.smtp.php');
  endif;
  $this->mailer = new PHPMailer();
}

5.1系の呼び出しはsfMailを継承したクラスを作ってそこで行うことに。
例えばMyMailクラスとかにして、コンストラクタだけ設定する。

class MyMail extends sfMail
{
  public function __construct()
  {
    require_once(sfConfig::get('sf_symfony_lib_dir').'/vendor/phpmailer/5.1/class.phpmailer.php');
    require_once(sfConfig::get('sf_symfony_lib_dir').'/vendor/phpmailer/5.1/class.smtp.php');
    $this->mailer = new PHPMailer();
  }
}

メール送信アクションでこのMyMailクラスを使わない場合(直接sfMailクラスを指定するなど)には、
PHPMailer 1.7系で送信することになる。


テスト → 送信OK。ktkr!

やれやれ。



ちなみに、Symfony1.4では…

sfMailクラスなんかなかった。Symfony1.1からバンドルされなくなったとか。
代わりにSwift Mailerを拡張したsfMailerクラスが定義されてた。

そうなのか…

まぁ、このエントリの需要は限りなく小さいとは思うけど、Symfony1.0を使った開発は当分続く予定なので、
自分的には重要な発見と言うことで残しておきます。疲れた。