email — делает PHP mail () асинхронным

У меня есть PHP mail() с помощью SSMTP который не имеет очереди / очереди и синхронизирован с AWS SES.

Я слышал, я мог бы использовать SwiftMail чтобы получить катушку, но я не мог выработать простой рецепт, чтобы использовать его, как в настоящее время с mail(),

Я хочу, чтобы наименьшее количество кода обеспечивало асинхронную почту. Мне все равно, если письмо не отправляется, но было бы неплохо иметь журнал.

Какие-нибудь простые советы или хитрости? Не хватает полноценного почтового сервера? Я думал sendmail Обертка может быть ответом, но я не мог разобраться nohup,

14

Решение

PHP-FPM

Вы должны запустить php-fpm для fastcgi_finish_request быть доступным.

echo "I get output instantly";
fastcgi_finish_request(); // Close and flush the connection.
sleep(10); // For illustrative purposes. Delete me.
mail("test@example.org", "lol", "Hi");

Довольно просто поставить в очередь любой произвольный код для обработки после завершения запроса к пользователю:

$post_processing = [];
/* your code */
$email = "test@example.org";
$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' => 'noreply@example.org',
'subject' => 'foo',
'message' => 'bar'
]);

curl_exec($ch);
curl_close($ch);

echo "Expect an email in 10 seconds.";
8

Другие решения

У вас есть много способов сделать это, но обработка потока не обязательно является правильным выбором.

  • register_shutdown_function: функция выключения вызывается после отправки ответа. Это не совсем асинхронно, но по крайней мере это не замедлит ваш запрос. Что касается реализации, см. Пример.
  • Свифт бассейн: используя Symfony, вы можете легко использовать катушку.
  • Очередь: зарегистрируйте письма, которые будут отправлены в системе очередей (это можно сделать с помощью RabbitMQ, MySQL, Redis или чего-либо еще), затем запустите cron, который использует очередь. Может быть сделано с помощью чего-то такого простого, как таблица MySQL с такими полями, как from, to, message, sent (логическое значение установлено на true когда вы отправили письмо).

Пример с функцией register_shutdown_function

<?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', 'contact@example.com', 'Hello from the spool');register_shutdown_function('MailSpool::send');

exit(); // You need to call this to send the response immediately
16

Используйте AWS SES с PHPMailer.

Этот способ очень быстрый (сотни сообщений в секунду), и не требуется много кода.

$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;

Не уверен, правильно ли я интерпретировал ваш вопрос, но надеюсь, что это поможет.

5

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('Shigeru.Miyamoto@nintendo.com', 'Eikichi.Kawasaki@neogeo.com',...);
foreach($mail_to_list as $mail_to) {
$asynchMail = new AsynchMail($mail_to);
$asynchMail->start();
}

Дайте мне знать, если вам нужна дополнительная помощь для установки и использования потока в PHP
Для системы регистрации, я настоятельно советую вам использовать Log4PHP : мощный и простой в использовании и настройке
Для отправки почты я также настоятельно рекомендую вам использовать PHPMailer

2

Я использую асинхронное выполнение PHP с помощью beanstalkd.
Это простая очередь сообщений, действительно легкая и легко интегрируемая.

Использование следующей оболочки 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

Эта команда запустит файл, а также позволит вам закрыть консоль или выйти из системы текущего пользователя, не останавливая процесс.
Убедитесь также, что ваш веб-сервер использует тот же файл php.ini, что и ваш интерпретатор командной строки php. (Может быть решена с помощью ссылки на ваш любимый php.ini)

Я надеюсь, что это помогает.

1

Лучше всего делать ставку с укладкой или намоткой. Это довольно просто и может быть описано в 2 этапа.

  • Храните ваши электронные письма в таблице с флагом отправлено в вашей текущей теме.
  • Используйте cron или ajax, чтобы повторно вызывать php-файл обработки почты, который будет получать первые 10 или 20 неотправленных писем из вашей базы данных, помечать их как отправленные и фактически отправлять через ваш любимый метод рассылки.
0

Самый простой способ сделать это — вызвать код, который обрабатывает ваши письма асинхронно.

Например, если у вас есть файл с именем email.php со следующим кодом:

// Example array with e-mailaddresses
$emailaddresses = ['example1@test.com', 'example2@example.com', 'example1@example.com'];

// Call your mail function
mailer::sendMail($emailaddresses);

Затем вы можете вызвать это асинхронно в обычном запросе, как

exec('nice -n 20 php email.php > /dev/null & echo $!');

И запрос будет завершен, не дожидаясь email.php завершить отправку электронных писем. Ведение журнала также может быть добавлено в файл, который выполняет электронную почту.

Переменные могут быть переданы в exec между вызываемым именем файла и > /dev/null лайк

exec('nice -n 20 php email.php '.$var1.' '.$var2.' > /dev/null & echo $!');

Убедитесь, что эти переменные безопасны с escapeshellarg (). В вызываемом файле эти переменные могут быть использованы с $ ARGV

0

Добро пожаловать в асинхронный PHP
https://github.com/shuchkin/react-smtp-client

$loop = \React\EventLoop\Factory::create();

$smtp = new \Shuchkin\ReactSMTP\Client( $loop, 'tls://smtp.google.com:465', 'username@gmail.com','password' );

$smtp->send('username@gmail.com', 'sergey.shuchkin@gmail.com', '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();
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector