2

現在、PHP と Zend Framework を使用して、SMTP と GMail の SMTP サーバーでメールを送信しています。これは、すべてのメールを処理するために Google Apps ドメインを設定しているため、メールが mailer@mycompany.com から送信されているように見えるためです。

ユーザーが登録するか、Web サーバーにメールを送信する必要があることを行うと、PHP 側で SMTP 接続を開始してメールを送信するのに 5 秒ほどかかることがあります。プロセスは次のようになります。

  1. ユーザーが登録フォームに記入する
  2. ユーザーがフォームを送信
  3. PHP スクリプトが情報をデータベースに保存し、メールを送信します (5 ~ 10 秒)
  4. ユーザーが別のページにリダイレクトされました

彼らがフォームを送信したばかりのとき、ユーザーがそこに10秒間座っている間、Webサーバーから大きな遅延が発生することはありません。基本的に、電子メールの送信プロセスはシングル スレッドであるため、サーバーは電子メールの送信が完了するまで他に何もできません。これは 5 ~ 10 秒で、電子メール アドレスにエラーがある場合は 20 秒かかることもあり、これは長すぎます。

人々は通常、このような問題をどのように回避しますか?

もともと私はいくつかのことを試しました:

  1. SwiftMailer のような別のライブラリを使用します。それでも同じ問題。余分な時間がかかるのは SMTP/TLS ハンドシェイクだと思います。

  2. 電子メール データをデータベースに保存し、fsockopen を使用して別のページへの非同期要求を開始し、データベースから電子メール データを取得して電子メールを送信します。その間、私の PHP スクリプトは同期的に続行でき、ユーザーはフォームの送信直後に次のページにリダイレクトされます。問題は、メールが送信されたかどうか、または失敗したかどうかを確認する方法がなかったことです。データベース テーブルにフラグを設定することはできたと思いますが、メールが送信されたことをユーザーに即座にフィードバックしたかったのです。つまり、次のページで 10 秒後に Ajax リクエストを別のページに送信し、データベース テーブルのフラグをチェックして送信されたかどうかを確認し、そのページに応答をユーザーに表示します。メールを間違って入力した場合、これは機能せず、メールを送信できませんでした。

  3. 私が思いついた別のオプションは、電子メールデータを $_SESSION 配列に入れることでした。そのため、ページを送信した後、ユーザーはリダイレクトされたページにいて、セッションデータを取得して送信する別のページに ajax リクエストを送信します。電子メールを送信してから、ユーザーが表示していたページに応答を送り返し、電子メールが送信されたことを伝えます。これはかなりうまく機能しますが、おそらく最善の方法ではないと思います。

だから私はそれを行うためのベストプラクティスの方法は何だろうと思っていますか? GMail は TLS ハンドシェイクを行う必要があるため、この種の処理には遅すぎますか? すべての電子メールをデータベースのキューに入れ、数分ごとに CRON ジョブを実行して送信し、送信後にデータベースから削除する必要がありますか? 問題は、電子メールが正しく送信されたというユーザーへの即時フィードバックがないことです。それともとにかくそれを気にする必要はありませんか?彼らは電子メールを受け取るかどうかのどちらかです。

4

4 に答える 4

1

実際、私は同じコンポーネントを使用してメールを送信しています。しかし、私はZend_Queueこの場合、訪問者が待つ必要がないことを使用して、バックグラウンドで電子メールを送信しています。これは私がこのタスクを達成する方法です(Zend_Queueで初期化されますBootstap.php):

1.ジョブの作成

class My_Job_SendEmail extends My_Job
{
    /**
     * Message subject:
     * 
     * @var string|null 
     */
    protected $_subject = null;

    /**
     * Message body:
     * @var string|null 
     */
    protected $_message = null;

    /**
     * Message To:
     * @var string|null 
     */
    protected $_to = null;

    public function __construct(Zend_Queue $queue, array $options = null)
    {
        if (is_array($options)) {
            $this->setOptions($options);
        }

        parent::__construct($queue);
    }

    public function job()
    {
        $mail = new Zend_Mail();
        $mail->addTo($this->_to);
        $mail->setSubject($this->_subject);
        $mail->setBody($this->_message);
        return $mail->send();
    }
}

2.My_Jobのソース

3.キューへのジョブの追加(おそらくサービス内のどこか)

$backgroundJob = new My_Job_SendEmail(Zend_Registry::get('queue'), array(
    'to'      => $to,
    'bcc'     => $bcc,
    'subject' => $subject,
    'message' => $message,
));

$backgroundJob->execute();

4.バックグラウンドスクリプトの例については、この回答を参照してください。

5.バックグラウンドスクリプトをcronジョブに追加します

*/1 * * * * php /path/to/project/background/emailQueue.php

于 2013-01-06T22:29:13.157 に答える
1

アプリスクリプトを作成し、それをWebアプリとして使用して電子メールを処理するのはどうでしょうか。HTTP Get with paramsを使用すると、ベースメールサービスを使用してアプリスクリプトに電子メールを送信させることができます。MailApp.sendEmail()

私は独学のAppsScriptの人なので、ここで推測しているだけですが、理論的には機能するはずです。こんな感じになると思います。

e.parameterの最後にあるキーをwebAppURLを介して渡すことができるはずです。

function doGet(e){
var userEmail = e.parameter.email;

var body = 'message here';//could even pass params for the body also.

MailApp.sendEmail(userEmail, 'Subject', 'body', {noReply: true});
}

私たちのすべてのものはアプリスクリプトに基づいて構築されており、私は何十もの電子メール通知を送信しており、アプリスクリプトではその瞬間です。

お役に立てれば。

于 2013-01-06T00:39:07.003 に答える
1

私はこの正確な問題を抱えていました.私が実際に行っているのは、それらをデータベースにキューに入れるだけで、毎分実行してデータベースにキューに入れられた電子メールを送信するcronjobを持っていることです.

ところで、多くの中規模のサイトはこれを行っており、(5 分) またはまもなくメールを受信する必要があると伝えています。

データベースに保存する利点は、追加の列を追加して、送信されたかどうかを示し、次の cronjob で送信されなかった場合に再試行できることです。


Cronjob をロックするための更新:

これはシーケンシャル ロジックのみであり、ステップ 1、2、および 4 は Cron #1 に関するものであることに注意してください。

1-Cron #1 runs at 12:05, reads the locking table and finds it empty so it creates a db record in a pre-created table "locking" with 1 field "cronlock": holding the value 12345678910, which is the current time stamp.

2-Cron #1 at 12:06 (Still sending emails, but it completed 6 emails so far) so it updates the record of locking again with the current time-stamp to extend the locking period.

3-Cron #2 runs at 12:07, reads the locking table and find a value, compares this value with the current timestamp if the difference is less than 120 seconds, then it terminates itself.

4-Cron #1 finishes sending some emails at 12:08, it deletes the locking record and quits.**

5-Cron #3 runs at 12:09 and finds no locking record so it creates a new one and starts sending.... and so on.
于 2013-01-06T00:45:06.140 に答える
1

ホストの電子メール smtp サーバーを使用して、差出人アドレスを手動で設定することを検討しましたか? これは通常、私にとってはうまくいきました。それがオプションでない場合、私の最初の反応はオプション 3 です。これは、Web UI で遅延送信のオプションを選択したときに Google メールが行うことと似ています。

于 2013-01-05T23:40:12.753 に答える