私はPHPのmail()
を使用しています ssmtp を使用しています。これにはキュー/スプールがなく、AWS SESと同期しています。
SwiftMail を使用してスプールを提供できると聞きましたが、mail()
で現在使用しているような簡単なレシピを使用してそれを使用することはできませんでした。
最小限のコードで非同期メールを提供したい。メールの送信に失敗したかどうかは気にしませんが、ログがあればいいでしょう。
簡単なヒントやコツはありますか?本格的なメールサーバーを実行するのに不足ですか? sendmail
ラッパーが答えになるかもしれないと思っていましたが、Nohup
を計算できませんでした。
fastcgi_finish_request を使用するには、php-fpmを実行する必要があります。
echo "I get output instantly";
fastcgi_finish_request(); // Close and flush the connection.
sleep(10); // For illustrative purposes. Delete me.
mail("[email protected]", "lol", "Hi");
ユーザーへのリクエストの終了後に処理する任意のコードをキューに入れるのは非常に簡単です。
$post_processing = [];
/* your code */
$email = "[email protected]";
$subject = "lol";
$message = "Hi";
$post_processing[] = function() use ($email, $subject, $message) {
mail($email, $subject, $message);
};
echo "Stuff is going to happen.";
/* end */
fastcgi_finish_request();
foreach($post_processing as $function) {
$function();
}
カールを瞬時にタイムアウトして、新しいリクエストに対応させます。クールになる前に、共有ホストでこれを行っていました。 (それはクールではありません)
if(!empty($_POST)) {
sleep(10);
mail($_POST['email'], $_POST['subject'], $_POST['message']);
exit(); // Stop so we don't self DDOS.
}
$ch = curl_init("http://" . $_SERVER['HTTP_Host'] . $_SERVER['REQUEST_URI']);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'email' => '[email protected]',
'subject' => 'foo',
'message' => 'bar'
]);
curl_exec($ch);
curl_close($ch);
echo "Expect an email in 10 seconds.";
これを行う方法はたくさんありますが、スレッドの処理は必ずしも正しい選択ではありません。
from
、to
、message
、sent
(メールを送信したときにブール値をtrue
に設定)のようなフィールドを持つMySQLテーブルのような単純なもので実行できます。_<?php
class MailSpool
{
public static $mails = [];
public static function addMail($subject, $to, $message)
{
self::$mails[] = [ 'subject' => $subject, 'to' => $to, 'message' => $message ];
}
public static function send()
{
foreach(self::$mails as $mail) {
mail($mail['to'], $mail['subject'], $mail['message']);
}
}
}
//In your script you can call anywhere
MailSpool::addMail('Hello', '[email protected]', 'Hello from the spool');
register_shutdown_function('MailSpool::send');
exit(); // You need to call this to send the response immediately
_
PHPMailerを指定してAWS SESを使用します。
この方法は非常に高速で(1秒あたり数百のメッセージ)、必要なコードはそれほど多くありません。
$mail = new PHPMailer;
$mail->isSMTP(); // Set mailer to use SMTP
$mail->Host = 'ssl://email-smtp.us-west-2.amazonaws.com'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'blah'; // SMTP username
$mail->Password = 'blahblah'; // SMTP password
$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted
$mail->Port = 443;
私があなたの質問を正しく解釈したかどうかわかりませんが、これが役に立てば幸いです。
Pthreads はあなたの友達です:)
これは、本番アプリケーションで作成した方法のサンプルです
class AsynchMail extends Thread{
private $_mail_from;
private $_mail_to;
private $_subject;
public function __construct($subject, $mail_to, ...) {
$this->_subject = $subject;
$this->_mail_to = $mail_to;
// ...
}
// ...
// you must redefine run() method, and to execute it we must call start() method
public function run() {
// here put your mail() function
mail($this->_mail_to, ...);
}
}
テストスクリプトの例
$mail_to_list = array('[email protected]', '[email protected]',...);
foreach($mail_to_list as $mail_to) {
$asynchMail = new AsynchMail($mail_to);
$asynchMail->start();
}
PHPでのスレッドのインストールと使用についてさらにヘルプが必要な場合はお知らせください
ロギングシステムでは、使用することを強くお勧めします Log4PHP :パワフルで使いやすく、設定も簡単
メールを送信する場合は、 PHPMailer を使用することも強くお勧めします
beanstalkd を使用して非同期のphp実行を使用しています。
これはシンプルなメッセージキューで、非常に軽量で統合が簡単です。
次のphpラッパーを使用してphp https://github.com/pda/pheanstalk を実行すると、次のようにしてメールワーカーを実装できます。
use Beanstalk\Client;
$msg="dest_email##email_subject##from_email##email_body";
$beanstalk = new Client();
$beanstalk->connect();
$beanstalk->useTube('flux'); // Begin to use tube `'flux'`.
$beanstalk->put(
23, // Give the job a priority of 23.
0, // Do not wait to put job into the ready queue.
60, // Give the job 1 minute to run.
$msg // job body
);
$beanstalk->disconnect();
次に、別のphpファイルに配置されたコードでジョブが実行されます。
何かのようなもの:
use Beanstalk\Client;
$do=true;
try {
$beanstalk = new Client();
$beanstalk->connect();
$beanstalk->watch('flux');
} catch (Exception $e ) {
echo $e->getMessage();
echo $e->getTraceAsString();
$do = false;
}
while ($do) {
$job = $beanstalk->reserve(); // Block until job is available.
$emailParts = explode("##", $job['body'] );
// Use your SendMail function here
if ($i_am_ok) {
$beanstalk->delete($job['id']);
} else {
$beanstalk->bury($job['id'], 20);
}
}
$beanstalk->disconnect();
このphpファイルは、独立したphpプロセスとして個別に実行できます。これをsender.phpとして保存すると、Unixでは次のように実行されます。
php /path/to/sender/sender.php & && disown
このコマンドはファイルを実行し、プロセスを停止せずにコンソールを閉じるか、現在のユーザーをログアウトすることもできます。
Webサーバーがphpコマンドラインインタープリターと同じphp.iniファイルを使用していることも確認してください。 (お気に入りのphp.iniへのリンクを使用して解決される可能性があります)
お役に立てば幸いです。
AsyncへようこそPHP https://github.com/shuchkin/react-smtp-client
$loop = \React\EventLoop\Factory::create();
$smtp = new \Shuchkin\ReactSMTP\Client( $loop, 'tls://smtp.google.com:465', '[email protected]','password' );
$smtp->send('[email protected]', '[email protected]', 'Test ReactPHP mailer', 'Hello, Sergey!')->then(
function() {
echo 'Message sent via Google SMTP'.PHP_EOL;
},
function ( \Exception $ex ) {
echo 'SMTP error '.$ex->getCode().' '.$ex->getMessage().PHP_EOL;
}
);
$loop->run();
あなたの最善の策は、スタックまたはスプールのパターンです。これはかなり単純で、2つのステップで説明できます。
これを行う簡単な方法は、メールを非同期で処理するコードを呼び出すことです。
たとえば、次のコードを含むemail.phpというファイルがあるとします。
// Example array with e-mailaddresses
$emailaddresses = ['[email protected]', '[email protected]', '[email protected]'];
// Call your mail function
mailer::sendMail($emailaddresses);
次に、これを通常のリクエストで非同期に呼び出すことができます
exec('Nice -n 20 php email.php > /dev/null & echo $!');
そして、email.phpが電子メールの送信を完了するのを待たずに、リクエストは完了します。電子メールを送信するファイルにログを追加することもできます。
変数は、呼び出されたファイル名と> /dev/null
の間でexecに渡すことができます。
exec('Nice -n 20 php email.php '.$var1.' '.$var2.' > /dev/null & echo $!');
escapeshellarg() を使用して、これらの変数が安全であることを確認してください。呼び出されたファイルでは、これらの変数は $ argv で使用できます