Magento CE 1.9.1.x以降でメールキュー送信に失敗すると危険
この記事は公開から 1年以上が経過しています。現在の最新情報との整合性については弊社では一切の責任を負いかねます。
こちらのエントリで、Magento Community Edition 1.9.1.x(Enterprise 1.14.1.x)以降のメール送信はキューによる非同期配信になる、とご説明しました。
その後、実運用サイトで起きたトラブルがあり、対処を行いました。
再発を防止する意味でこのエントリでご説明いたしますので、参考にしていただければ幸いです。
メール送信キューの仕組み
キューの作成
メール送信キューは、注文の受付時や、請求書作成時などの注文に関する処理の時に最も多く作成されます。その他、メールテンプレートがデータベースに入っているメールについてもキューが作成されますが、大多数は注文関係が多くなるでしょう。
core_email_queue テーブルにメール本文やタイトル、受信者情報以外のヘッダ情報が入っています。
このテーブルにはそれ以外に、キューの作成日時と処理完了日時が記録されるようになっていて、キューが作成された時点では処理完了日時にはnullが入っています。
そして受信者情報は core_email_queue_recipients テーブルに、1受信者ごとに分かれたデータが記録されます。
こうして送信キューは作成されていきます。
キューデータの取り出しと送信
次に、キューデータは cron による定時処理が行われるたびに少しずつ処理されます。
1回の定時処理で、100件ずつキューデータが取り出され、 core_email_queue_recipients テーブルの受信者に向けて送信されていきます。
送信後の処理
キューの送信が成功すると、Magento は core_email_queue テーブルの送信完了日時を更新します。
これでこのキューは送信されたことになります。
その後、送信が完了したキューは別の定時処理によって、一定時間後に削除されていきます。
そのため、 core_email_queue や core_email_queue_recipients テーブルが肥大化するということはありません。
キューの処理に失敗するとどうなるか
2種類の失敗パターン
送信の失敗には2種類のパターンがあります。
1つは送信先アドレスなどのプログラム以外が理由の失敗。もう1つはプログラム的な送信の失敗。
送信先アドレスが間違っていたり、受信者のメールボックスが満杯だったりして送信がエラーになるケースは、Magentoが土台にしているPHPプログラムの外で起きる送信の失敗です。
この場合、Magento的には送信できたことになるので、メールキューは処理できたとみなされます。
実際にはメールが届かない可能性もありますが、それはメール送信サーバー同士の問題なので、WebアプリケーションであるMagentoにはもうわからない範囲なのです。
これに対し、プログラム的な送信の失敗が起きた場合、エラーは直接Magentoに影響します。要はそこで処理が止まります。
結果、送信キューは処理されていないまま放置されます。
リトライを続けるMagento
core_email_queue テーブルには「送信が失敗した理由」「失敗した回数」といった情報は記録されません。
送信ができなかった送信キューは「常に未処理」であるとみなされます。
従ってMagentoは次の定時処理で、失敗した送信キューを何度も何度も処理しようとします。
Magento的にはそのキューに問題があるかどうかはわかりませんし、自分でPHPプログラムを直すこともできません。
やがてリトライキューが1回の処理件数を超過
1回の定時処理では100件のメールキューが一度に処理される、と先ほど説明しました。
正常にキューが処理されている状態であれば、常に新しいキューが処理されていくわけですが、エラーがあって送信できなかったキューが発生すると、それらは次回の定時処理で再び処理されます。
しかし、結局そのキューは原因の根治がされていませんから、エラーになってしまいます。
それが積もり積もっていくと、エラーになったリトライキューだけが1回の定時処理の件数をうめつくすようになり、新しいキューはずっと送信されないままになります。
原因と対策
原因
メールキューがエラーになる原因は、大きく分けて2つ理由があります。
1つは受信者データに問題がある場合。もう1つはヘッダ情報にエラーがある場合。
特に受信者データに問題がある場合は、空の受信者アドレスが入っている場合に起きます。
空のアドレスがなぜ入るか、それはセールスメールの設定項目に用意されている、BCC送信先の設定に理由があります。
正しくBCC送信先を設定することで、この問題は簡単に防ぐことができます。
対策
セールスメールのBCC送信先には、カンマ「,」区切りで複数のメールアドレスを指定することができます。
2件以上送信先がある場合は、アドレスの区切りにカンマを入れるわけですが、誤って1件しか送信先がない場合にカンマを入れてしまうと、メールキューを作成する際に、空の受信者データが作成されてしまいます。
結果、送信エラーを引き起こすキューデータが作成されてしまい、無限に送信エラーを繰り返してしまいます。
開発中のサイトであれば良いのですが、運用中のサイトではやり直しのできない場合も有り得ますので、注意する必要があります。
この問題はMagento Community Edition 1.9.1.x(Enterprise Edition 1.14.1.x)以降でのみ起きます。
これより前のバージョンでは、そもそも送信エラーで処理全体が止まってしまうため、設定ミスに気がつくと思います。