[PHP-users 26920] Re: mb_send_mail()の処理

Y.Watanabe haward99 @ yahoo.co.jp
2005年 9月 17日 (土) 23:00:38 JST


渡辺です。

荒木 満 wrote on 2005/09/16 19:43
with Subject: [PHP-users 26908] mb_send_mail()の処理

> 早速ですが、自社のデータベース(ホスティングサービスのサーバー上のMySQL)の中から、メールアドレス
> を抽出しDMを発送するスクリプトを作っ
> ているのですが、件数が多く(5000件くらい)処理に時間がかかり、また、エラーとなり途中で止まってし
> まう場合があります。(抽出件数が少な
> い場合問題ないようなのですが・・・)
> そこで、少しでも処理の負担を減らしたいと考えています。

まず、環境を書きましょう。
PHPのバージョンとか。OSとか。CGI型なのかApacheモジュール型なのかとか。
メールもからむのであればメールサーバの種類とか。sendmail?postfix?

Apache+mod_phpによる共用ホスティング型で、
その5000件メール送信処理をブラウザからsubmitボタンを押すような
形でやっているのだとすれば、
たぶん処理件数が多くなって処理時間がかかるにつれて
ある時点でApacheのtimeoutに引っかかってしまって処理が止まるのでしょう。
たいていの場合timeout値は300秒(5分)前後になっています。

> mb_send_mail() の場合、あて先は複数指定できるとなっていますが、以下の2つのやり方では、どちらの方
> が良いのでしょうか?
> 
> 1.----------------------------------------------------
> while($rec = mysql_fetch_array($result)){
>    mb_send_mail($rec[0], $subject, $text, $header);
>     }
> -------------------------------------------------------
> 2.----------------------------------------------------
> while($rec = mysql_fetch_array($result)){
>     $to = $to.$rec[0].",";
>     }
> $to = rtrim($to, ",");
> mb_send_mail($to, $subject, $text, $header);
> -------------------------------------------------------

2の方法だとメールのTO:ヘッダに5000件くらいのメールアドレスが
羅列されることになってそのままメール送ると「情報漏えいだ!」などと
騒がれることになるような・・・。
それ以前に、5000個ものメールアドレスだと
メールサーバが「too many recipients」で受け付けてくれない
ケースが十分ありうるでしょう。

ブラウザを通じた処理ではなくshell上からの手作業ないしcronなどで
1の方法を用いたPHPスクリプトをコマンドラインで叩くのが
一番確実でよく使われる方法ですが、シェルの利用やcronが許可されて無い
レンタルサーバだと無理な相談。

そこで、500件ずつくらいで分けて送信するロジックを考えたほうがいいでしょう。

1.最初の処理でとりあえずメールアドレス等必要情報を5000件分、
  テンポラリファイルなりセッション情報なりに書き出す。

2.次にそのうちの500件をループでひとつひとつmb_send_mailする。
  500個終わったらそのぶんをテンポラリ情報から消して、ブラウザには 
  <META HTTP-EQUIV="refresh" CONTENT="5; URL=スクリプトのURL">
  とでも返しておく。これでブラウザが勝手にリクエストしなおしてくれる
  のでApacheのtmeoutをくぐり抜けることができる。

3.以降、テンポラリ情報がなくなるまで繰り返す。
4.テンポラリ情報が無くなったらブラウザに「<h1>おわったよ</h1>」を返す

こんな感じかなあ。
なお、無限ループ防止や二重起動防止をよく考えたほうがいいです。




PHP-users メーリングリストの案内