あーさーの備忘録

ゆっくり自由に生きてます

FuelPHPのEmailパッケージでSMTP-AUTHを使用して送信する

Emailパッケージ

久々にFuelPHPの話です。FuelPHPには便利なEmailパッケージが同梱されていて、メールをphp標準のmail()関数を使わなくてもメールが送れます。使用方法は以下の通り。

<?php
$email = Email::forge();
$email->subject(mb_convert_encoding('テストメール', 'ISO-2022-JP'))
      ->body(mb_convert_encoding(View::forge('mail', [], false), 'ISO-2022-JP'))
      ->to('hoge@hoge.com')
      ->from('huga@huga.com', mb_convert_encoding('ぽよぽよ', 'ISO-2022-JP'));
try
{
    $email->send();
}
catch (\EmailValidationFailedException $e)
{
    // メールアドレスが正しい形式じゃないとき
}
catch (\EmailSendingFailedException $e)
{
    // ドライバがメールの送信に失敗したとき
}

同様の方法でbccやccを設定したり、添付ファイルをつけたりなんてこともできます。View::forge()の第2引数に配列を渡したり、予めViewオブジェクトを生成し$view->hoge = 'hoge';とプロパティを指定してあげることで、変数を使ってメール本文を生成することもできます。詳しくは、FuelPHPのドキュメントを読んでください。

Usage - Email Package - FuelPHP Documentation

Emailパッケージのデフォルト設定の問題

さて、このEmailパッケージを導入する手順で、APPPATH/configにemail.phpというEmailパッケージの設定ファイルを設置します。こちらの設定ファイルは、文字コードISO-2022-JPエンコードを7bitにする以外に弄ることがなかったのですが、ある時急に思い出しました。

あれ、SMTP認証してなくね?

すぐさまconfigファイルを覗くとこんな設定がありました。

APPPATH/config/email.php

<?php
return array(
    //117行目付近
    /**
     * SMTP settings
     */
    'smtp' => array(
        'host'     => '',
        'port'     => 25,
        'username' => '',
        'password' => '',
        'timeout'  => 5,
        'starttls' => false,
    ),
);

今更ですけどPHPってプログラム部分が<?php ?>で囲われてるせいで、ブログでsyntax highlightするのにいちいち<?phpってつけなきゃいけないんですよね。見た目が煩雑になるので嫌ですね。

そんなことはさておき、SMTP settingsという設定を見つけ、その中には25の文字が!あ~、25番ポートで送ってたのか~。じゃあこの設定をちゃんと埋めればいいんですね。

Configを弄る

だいたいの環境ではメールアドレスごとにusernameが異なるはずなのですが、デフォルト設定を書き換えるだけだと1種類のアドレスからしか送れない…。もちろんこちらのConfigファイルに新しいプロファイルを作成(setupのところに配列を追加)すればいいのですが、この設定そんなにたくさん使わない!ということもあるでしょうし、今回はEmail::forge()の第2引数に設定を追記していく形で設定していきます。

<?php
$email = Email::forge('default', [
    'smtp' => [
        'host'     => 'poyopoyo.com',
        'port'     => 587, //サブミッションポート
        'username' => 'poyo@poyopoyo.com',
        'password' => '********',
        'timeout'  => 5,
        'starttls' => false,
    ],
]);

メールソフトを設定するような気持ちで入力すればOKです。これで送ってみたのですが、ポートが変わらない……どころかパスワードが違っても送れてしまう始末。たしかにこのEmailインスタンスには設定情報が入っているのですが……。

driver設定を追加

FuelPHPのEmailパッケージのドキュメントはお世辞にもしっかりしているとは言えない(情報量が少ない)ので、仕方なくコードをひたすら読んでいきました。すると、こんな設定があることがわかりました。

APPPATH/config/email.php

<?php
return array(
    //48行目付近
    /**
     * Mail driver (mail, smtp, sendmail, noop)
     */
    'driver' => 'mail',
);

この値をsmtpにしないとsmtpの設定が反映されないようですね。

先程のconfig配列に追記します。

<?php
$email = Email::forge('default', [
    'smtp' => [
        'host'     => 'poyopoyo.com',
        'port'     => 587,
        'username' => 'poyo@poyopoyo.com',
        'password' => '********',
        'timeout'  => 5,
        'starttls' => false,
    ],
]);

これでメールを送ってみると、見事にSMTP-AUTHを使用して587ポートからの送信に成功しました。

おまけ①SSLを使う

<?php
$email = Email::forge('default', [
    'smtp' => [
        'host'     => 'poyopoyo.com',
        'port'     => 465,
        'username' => 'poyo@poyopoyo.com',
        'password' => '********',
        'timeout'  => 5,
        'starttls' => true,
    ],
]);

これでSTARTTLSで接続できるかなぁと思ったのですが、残念ながら、私の環境では以下のエラーが発生し、認証ができませんでした。

ERROR - ***time*** –> Notice - fputs(): send of 6 bytes failed with errno=32 Broken pipe in ***path*** on line ***line***

私の設定が間違っている可能性のほうが高いので、またいつか試してみます。誰か原因が分かる人がいたら教えてください。

2017/09/26 16:37追記(できました)

hostsの値の前にssl://をつけたらふつうにできました。おかしいな、朝はこれでダメだったのにな。

<?php
$email = Email::forge('default', [
    'smtp' => [
        'host'     => 'ssl://poyopoyo.com',
        'port'     => 465,
        'username' => 'poyo@poyopoyo.com',
        'password' => '********',
        'timeout'  => 5,
        'starttls' => true,
    ],
]);

おまけ②mailドライバーは何だったのか

デフォルトで指定されていたdriver => 'mail'はどんな処理をしているのかな、と思ってソースを覗いてみました。そこには@mailの文字が…!!。結局mail()使ってるんか~い。まぁ確かに認証情報ないなら使わないと送れないんですけどね。初めてお目にかかった関数前の@ですが、エラーを出力しないようにするエラー制御演算子というものらしい。なるほど。あまり使用は推奨されていないようだけど。