質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.34%

PHPでメールマガジンの送信を考えております。

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 1,556

manamana620

score 14

<?php

                            try
                            {


                            require_once('./function.php');
                            require_once('./config.php');

                            $title=$_POST['title'];
                            $naiyou=$_POST['naiyou'];

                                $dbh=new PDO(DSN,DB_USER,DB_PASSWORD);
                                $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
                                $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);

                                $sql='select mail from hon_table';


                                print 'メールマガジンの送信登録しました。<br><br>';



                                print'タイトル';
                                print'<br>';

                                print $title;
                                print'<br>';
                                print '~内容~<br><br>';
                                print nl2br(h($naiyou));

                            $count = 0;

                                foreach ($dbh->query($sql) as $row) {
                                $honbun = "$naiyou\n\n\n";

                                $title=$title;
                                $header = 'From:info@hogehoge.com';
                                //メールヘッダーインジェクション対策
                                $header = str_replace(array("\r\n", "\r", "\n"), "", $header);
                                $honbun = html_entity_decode($honbun, ENT_QUOTES, 'UTF-8');
                                mb_language('japanese');
                                mb_internal_encoding('UTF-8');
                                mb_send_mail($row['mail'], $title, $honbun, $header);

                                $count++;
                                if ($count > 50 && $count % 50 == 1) { // 51, 101, 151, ... の場合30秒停止
                                    sleep(30);
                                }

                                $dbh = null;
                            }
                            }
                            catch (Exception $e)
                            {
                                print '取得に失敗しました。ただいま障害により大変ご迷惑をお掛けしております。';
                                exit();
                            }
                            ?>

$count = 0;置き場所で悩んでいます。

foreachの手前に書いてますが、

繰り返し処理の中でないので、カウント0が機能するのでしょうか?

うまくsleepが機能するのでしょうか?

仮想開発環境なので実際メールを大量に送る実験をしてません。

この書き方でよいのか不安です。

アドバイス願います。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+2

メールの大量配信は自己開発するには難易度高めです。
大量メール配信の仕組みに関して、まず勉強されることをおすすめします。

難易度低めの壁:メール配信の流量コントロール、登録個人情報の保護手順の確立等
難易度高めの壁:携帯アドレスの処理、ブラックリスト登録の解除等

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+1

まず、合っているかどうかを教えることは、非常に簡単ですが、
あえて、厳しい意見となってしまいますが、うるさい年寄りだと思わず、お聞きください。

ということで、意地悪ですが、
メール送信、云々、の前に、基本的な、PHP(というより、そもそものプログラミングの基本)の、forなどの、ループの動作について、学習・確認されたほうがよいかと思います(PHPの言語学習はされていない?どこかから持ってきたソース?でしょうか?)。

理解できていれば、うまく動くかどうかは、すぐに、わかるはずです。

あと、ついでに、苦言となってしまいますが、
プログラムの、インデントをきちんと、守ってください。
インデントのくずれているプログラムは、たとえ動作したとしても、信頼できません。
プログラムを書く人間同士での、最低限のルールです。


以下追記です。
まずは、元のソースを整形しました。

<?php

try
{
  //
  require_once('./function.php');
  require_once('./config.php');

  //
  $title = $_POST['title'];
  $naiyou = $_POST['naiyou'];

  //
  $dbh = new PDO(DSN,DB_USER,DB_PASSWORD);
  $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
  $dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);

  //
  $sql = 'select mail from hon_table';

  //
  print 'メールマガジンの送信登録しました。<br><br>';
  //
  print'タイトル';
  print'<br>';
  //
  print $title;
  print'<br>';
  print '~内容~<br><br>';
  print nl2br(h($naiyou));

  //
  $count = 0;

  foreach ($dbh->query($sql) as $row) {
    //
    $honbun = "$naiyou\n\n\n";
    //
    $title=$title;
    $header = 'From:info@hogehoge.com';

    //メールヘッダーインジェクション対策
    $header = str_replace(array("\r\n", "\r", "\n"), "", $header);
    $honbun = html_entity_decode($honbun, ENT_QUOTES, 'UTF-8');
    //
    mb_language('japanese');
    mb_internal_encoding('UTF-8');
    mb_send_mail($row['mail'], $title, $honbun, $header);

    $count++;
    if ($count > 50 && $count % 50 == 1) { // 51, 101, 151, ... の場合30秒停止
      sleep(30);
    }

    $dbh = null;
  }

}
catch (Exception $e)
{
  print '取得に失敗しました。ただいま障害により大変ご迷惑をお掛けしております。';
  exit();
}
?>

そして、このソースへのコメントです。

  1. まずそもそもの質問の、「$count」の場所ですが、特に問題ないと思います。
    もし、foreachのループ内においてしまったら、ループの度に、$count==0になってしまいますので、いつになって、Sleepは実行されません。
  2. foreachかwhileかという話ですが、どちらでも結構です。好きな方で。もちろん、明確に使い分けをする必要があるループを構成することもありますが、この処理ではどちらでもかまわないかと思います。

なお、このソースの指摘で動作しないんだけど?と言われても困りますので(というか、申し訳ないですがたぶん動きません。)、以下に、このソースが動かない可能性を指摘します。

  1. require_onceで、2つのファイルを取り込んでいますが、内容がわからないため、影響などがわかりません。
  2. $title,$naiyouについて、POST以外でアクセスされた場合、$_POSTがnullになりエラーとなる可能性があります。
  3. PDOの操作をしておりますが、ターゲットのDBの種類や、そもそもスキーマがわかりませんので、動作するかどうかわかりません。
  4. printで、いろいろ出力されていますが、HTMLヘッダとかが存在しないのか、他で定義されているのか?わかりません。
  5. $title=$title;の行、この行の操作の意味がわかりません。
  6. mb_関連関数を利用されていますが、mb_stringがPHPに導入されているかどうかわかりません(大半の国内レンサバなら大丈夫ですが、自前環境などだと入っていないことも)。
  7. mb_sendmailを使っていますが、SMTP関連の設定状況がわかりませんので、無事に送信されるかどうかわかりません。
  8. sleep(30)となっているようで、30秒の待ちが50メール送信毎に発生するようですが、メールの数が多い場合には、クライアント側でタイムアウトしてしまう可能性があります。
  9. $dbh = null;としてしまっていますので、ループの2回目で、$dbhが無くなってしまい、エラーになりそうです。

以上、がんばってください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/16 11:10

    ご回答ありがとうございます、

    稚拙なプログラムで誠にすみません。

    私は、プログラムは超初心者です。

    PHPがプログラム勉強の最初の言語です。

    田舎のため、近くにプログラムを教えてくれる学校はないです。

    googleで検索のみの状態です。

    ソースの元は、
    http://www.phppro.jp/qa/1371

    となります。

    データーベースで取得のみをしたい時によく

    foreach ($dbh->query($sql) as $row)

    こちらのコードをみかけるので、
    (ドットインストールhttp://dotinstall.com/などで)

    foreachにした次第です。

    whileの方がよいのでしょうか?

    foreachでは使い方がちがうのでしょうか?

    プロの方の意見をお聞かせください。


    キャンセル

  • 2016/04/16 11:37

    超初心者の方が、ネットの情報でプログラムを覚えるというのは、無理ではないですが、やめておくのが吉です。かなりの高い確率でネットの情報は、曖昧な情報、間違えた情報、動かないサンプルなどなど、役立たないばかりか、曖昧なまた間違った情報を飲み込んでしまいます。スレ主様はそこにハマってしまい、ここで質問されているのだとは思いますが)。
    そして、本人が学習意欲があるなら、学校などで、教わる必要はないでしょう。
    現在は、Amazonなどでも、優良な書籍などが手に入ります。
    ぜひ、どのような本でもよいので、書籍を読んで、まずは基礎知識をつけるべきと思います。
    そうすれば、$countが合っているのか、foreachなのか、whileなのか?分かるはずです。

    なお、もし、答えだけを求めるのであれば、言ってください。
    解答を書くことは、先にもかきましたが、特段難しいことではありませんので。

    キャンセル

  • 2016/04/16 11:56

    ご回答ありがとうございます、

    書籍等検索してみますが、下記サイトをみてから不安だらけになりました。

    http://blog.tokumaru.org/2013/12/php12sql.html
    よい書籍がありましたら、お教えください。

    答えは、今後のためにも知りたいです。教えてください。

    キャンセル

  • 2016/04/16 13:08

    ご丁寧にありがとうございます、基礎をがんばってみます。

    キャンセル

+1

はじめまして。こんにちは。

他の方が仰っているように基本から学習された方が良いと思います。
DBやメール送信の箇所はひとまずコメントしておいて、
実際にどのような挙動をするのか、デバッグ(echo/print/var_dump等)で
ひとつひとつ確認するのがいいですね。

またメルマガ送信等、時間のかかるプログラムは
大抵コマンドラインからのバッチ実行だと思いますので、
サーバー(linux等)の知識も必要になってくるでしょう。

先は長いかもしれませんが、プログラムは楽しいものです。
ゆっくりしっかり進めてみて下さい。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る