使えるクラウド上からメールを送信する場合の注意点
数あるレンタルサーバー業者がある中、お気に入りは使えるねっと株式会社。
同じ長野市にある会社ということもありますが、サポートは他のどこよりも丁寧なのでは無いでしょうか。
使い方がわからない時や期待した動作ができない場合など、サポート宛にメールするとすぐに返信してくれます。
内容もとても親切で具体的な対応方法など手順を明示して教えてくれます。
ネット上のマニュアルページが充実するとより良くなるのではないでしょうか。
使えるねっと株式会社のページはこちら
そんな使えるねっとのサービスに「使えるクラウド」、「使えるCloud VPS」があるのですが、セキュリティを強化しているということで、ひと手間加えないと期待する動作が行えないといったことがあります。
そんな「使えるクラウド」上でPHPからSMTPを介してメールを送ろうとした場合、エラーで送れない現象がありました。
SMTPのホストがSSLの場合メールが送れない!
CodeIgniterで普通にシステム構築して、他と同じようにSMTPでメール送信してもメールが飛ばない現象が発生。
ログを見てみるとSSL周りでエラーが発生しているのがわかります。
Severity: Warning --> stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
CodeIgniterのEmailライブラリに関するマニュアルを読んでもネットで調べても、どうも設定するところはなさそう。
ネットで散々調べてわかったキーワードは「verify_peer」や「stream_context_set_option」。
これらのキーワドを頼りに行き着いたサイトがこちら。
英語のページですが、同じ現象で困っている人のスレッドらしい。しかも運良くCodeIgniterに関するフォーラムの記事でした。
送れない原因は!?
上記のサイトの他、調べてみると、原因はPHP5.6からSSLコンテキストオプションの「verify_peer」がデフォルトでtrueになっているとのこと。これはPHPのマニュアルページにもありますが、「SSLサーバーの証明書の検証を要求します」というのがデフォルトだということ。
このオプションを無効にしたい!ということでCodeIgniterでの対応策はこちら
CodeIgniterでの対応策
protected function _smtp_connect()
{
if (is_resource($this->_smtp_connect))
{
return TRUE;
}
$ssl = ($this->smtp_crypto === 'ssl') ? 'ssl://' : '';
$this->_smtp_connect = fsockopen($ssl.$this->smtp_host,
$this->smtp_port,
$errno,
$errstr,
$this->smtp_timeout);
if ( ! is_resource($this->_smtp_connect))
{
$this->_set_error_message('lang:email_smtp_error', $errno.' '.$errstr);
return FALSE;
}
stream_set_timeout($this->_smtp_connect, $this->smtp_timeout);
$this->_set_error_message($this->_get_smtp_data());
if ($this->smtp_crypto === 'tls')
{
$this->_send_command('hello');
$this->_send_command('starttls');
// この3行を追加
stream_context_set_option($this->_smtp_connect, 'ssl', 'verify_host', FALSE);
stream_context_set_option($this->_smtp_connect, 'ssl', 'verify_peer_name', FALSE);
stream_context_set_option($this->_smtp_connect, 'ssl', 'verify_peer', FALSE);
// ここまで
$crypto = stream_socket_enable_crypto($this->_smtp_connect, TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT);
if ($crypto !== TRUE)
{
$this->_set_error_message('lang:email_smtp_error', $this->_get_smtp_data());
return FALSE;
}
}
return $this->_send_command('hello');
}
「CodeIgniter/system/libraries/Email.php」の2042行目からの「_smtp_connect()」メソッドの上記コメント箇所3行を追加してみて下さい。
これでSMTP経由でもメールが遅れるようになると思います。
普段開発で触ることはないCoreのファイルを触るのでバージョンアップする時など上書きしないよう注意しましょう。
上記解決に至るまで参考にさせていただいた日本語のサイトはこちらになります。
先人の皆さんに感謝しつつ。
CodeIgniter利用者の皆さんに役に立てれば嬉しく思います。