使 PHP 的邮件() 异步

我有使用ssmtp的PHP,它没有队列/假脱机,并且与AWS SES同步。mail()

我听说我可以使用SwiftMail来提供线轴,但是我无法像目前那样制定出使用它的简单配方。mail()

我希望提供最少数量的代码。我不在乎电子邮件是否无法发送,但有一个日志会很好。

任何简单的提示或技巧?缺少运行完整的邮件服务器?我在想包装器可能是答案,但我无法解决。sendmailnohup


答案 1

你有很多方法可以做到这一点,但处理线程不一定是正确的选择。

  • register_shutdown_function:发送响应后调用关机功能。它不是真正的异步,但至少它不会减慢您的请求速度。关于实现,请参阅示例。
  • Swift pool:使用symfony,你可以很容易地使用spool。
  • 队列:在队列系统中注册要发送的邮件(可以使用RabbitMQ,MySQL,redis或任何东西完成),然后运行使用队列的cron。可以使用像MySQL表这样简单的东西来完成,其中包含诸如,,,(布尔值设置为发送电子邮件时)。fromtomessagesenttrue

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

答案 2

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.";

推荐