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

ダメプログラマの技術メモ

プログラミングの技術メモや駄文など

突然、ロリポップ!で動かしているEC-CUBEのメールが送信できなくなった

EC-CUBE

私は以前、本業とは別に知人に依頼を受けてEC-CUBEでサイト構築をしたことがあります。

(詳しくは、EC-CUBEのカート機能を既存のHTMLに組み込む(その1)にあります。)

2012年4月から運用を開始して、今まで大きな問題がなかったのですが、2012年8月下旬のある日から突然メールが送信できなくなったと連絡がありました。

 

具体的にどのような問題が発生したのか?

注文決済メール、会員登録メール、お問い合わせメール等々のメール送信が一切できなくなりました。

メール送信時のログを調査したところ、次のようなエラーメッセージが出力されていました。

2012/08/29 20:33:56 [/xxxxx/shopping/confirm.php] Failed to connect to 127.0.0.1:25 [SMTP: Failed to connect socket: 接続を拒否されました (code: -1, response: )] from IPアドレス

完全に拒否られています(汗

ロリポップ!の障害情報を見る限り、メール送信できなかった日には障害が発生していませんでした。

なお、EC-CUBEのバージョンは2.11.5で、メールの設定はインストール時のまま(定数MAIL_BACKENDの値は「smtp」)で特に変更していません。

 

最初にとった対応は?

原因は全く不明。

しかし、ネットでそれらしき対応策を見つけることができました。

半信半疑で試してみたところ、、、

なんとかメール送信することができるようになりました。

 

実はダメだった。。。

上記の対応をとった翌日、再度、サイト運営者の方から連絡がありました。

それによると新たに問題が発生しているとのことでした。

  • 会員登録メールのみが送信できない

 ゴメンナサイ的な感じで、急いで再調査を行いました。

 会員登録メールを送信した際のログには、次のようなエラーメッセージが出力されていました。

2012/08/30 19:47:46 [/XXXXX/entry/index.php] sendmail returned error code 127 from IPアドレス

う~ん(汗

ググってもログに関する有益な情報が出てこない。。。

 

次にとった対応は?

定数MAIL_BACKENDの値を「mail」に変更しました。

この修正により、会員登録メールは送信できるようになりました。

しかし、メールのReturn-PathにはFromと異なるメールアドレス(XXXXX@users038.phy.lolipop.jp)が設定されていました。

このままではエラーメールが返ってきませんし、スパムメール扱いされる可能性も高くなります。

どうやら真剣にソースを見ないといけないようです(最初からそうしろよ)

 

真の解決策は?

SC_SendMail.phpのgetBackendParamsメソッドを修正します。

/data/class/SC_SendMail.php

/**
* メーラーバックエンドに応じたパラメーターを返す.
*
* @param string $backend Pear::Mail のバックエンド
* @return array メーラーバックエンドに応じたパラメーターの配列
*/
function getBackendParams($backend) {
switch ($backend) {
case 'mail':
$arrParams = array('-f[Fromメールアドレス]'); // ここを修正します。
break;
case 'sendmail':
$arrParams = array('sendmail_path' => '/usr/bin/sendmail',
'sendmail_args' => '-i'
);
break;
case 'smtp':
default:
$arrParams = array(
'host' => $this->host,
'port' => $this->port
);
break;
}
return $arrParams;
}

switch文のcase 'mail'に合致した時に、$arrParamsに-fオプション+Fromメールアドレスを配列で渡すようにします(-fとFromメールアドレスの間にスペースは必要ありません、括弧[ ]も不要です

私は早くアニメが見たかったので分かりやすさを考慮してSC_SendMail.phpを直接修正してしまいましたが、本来は/data/class_extends/SC_SendMail_Ex.phpでgetBackendParamsメソッドをオーバーライドしてやるべきです。

あと、定数MAIL_BACKENDの値を「mail」に設定するのをお忘れなく。

この修正によりReturn-PathにFromメールアドレスが設定されるようになります。

 

どうしてReturn-PathにFromメールアドレスが設定されるようになったのか?

EC-CUBEのメール送信処理はPEAR::Mailを使用しています。

getBackendParamsメソッドはPEAR::Mailのfactoryメソッド(インスタンス生成)に渡すパラメータを定義します。

マニュアルとgetBackendParamsメソッドを見比べて頂いたら、getBackendParamsメソッドの役割がわかると思います。

今は、定数MAIL_BACKENDが「mail」なので、パラメータ「array('-f[Fromメールアドレス]')」がfactoryメソッドの第2引数に渡され、その時の挙動はマニュアルによると次のように定義されています。

セーフモードが無効の場合、 $params は PHP mail() 関数の 5 番引数として渡されるでしょう。 $params が配列の場合、 その要素はスペース区切りの文字列として連結されるでしょう。

つまり、mail関数の第5引数に「array('-f[Fromメールアドレス]')」が渡されます。

これにより何が起きるかというと、その答えは次のブログに書かれています。

はい、Return-PathにFromメールアドレスが設定されます^^

 

まとめると

  1. SC_SendMail.php(あるいはSC_SendMail_Ex.php)のgetBackendParamsメソッドを修正する。
  2. 定数MAIL_BACKENDの値を「mail」に変更する。

 以上2点の修正により正常なメール送信が可能になりました。

 

とりあえず同様の事例で困っている人がいるかもしれないので記事にしました。

対応方法は明確なのですが、原因自体ははっきりせず非常にモヤモヤした気持ちです(´・д・`)

もし、原因が判明するようなことがあれば、この記事に追記します。