制作PHP';s mail()异步

制作PHP';s mail()异步,php,email,amazon-web-services,asynchronous,amazon-ses,Php,Email,Amazon Web Services,Asynchronous,Amazon Ses,我使用了PHP的mail(),它没有队列/假脱机,并且与AWS SES同步 我听说我可以用它来提供一个假脱机,但我不能像现在使用mail()那样,找到一个简单的方法来使用它 我希望用最少的代码来提供异步邮件。我不在乎电子邮件是否发送失败,但如果有日志就好了 有什么简单的技巧吗?没有运行完整的邮件服务器?我在想一个sendmail包装器可能是答案,但我无法确定nohup您有很多方法可以做到这一点,但处理线程不一定是正确的选择 :在发送响应后调用shutdown函数。它不是真正的异步,但至少不会减

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

我听说我可以用它来提供一个假脱机,但我不能像现在使用
mail()
那样,找到一个简单的方法来使用它

我希望用最少的代码来提供异步邮件。我不在乎电子邮件是否发送失败,但如果有日志就好了


有什么简单的技巧吗?没有运行完整的邮件服务器?我在想一个
sendmail
包装器可能是答案,但我无法确定
nohup

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

  • :在发送响应后调用shutdown函数。它不是真正的异步,但至少不会减慢您的请求。关于实现,请参见示例
  • :使用symfony,您可以轻松使用滑阀
  • 队列:在队列系统中注册要发送的邮件(可以使用RabbitMQ、MySQL、redis或任何工具),然后运行使用队列的cron。可以使用MySQL表这样简单的东西来完成,该表中有
    from
    to
    message
    sent
    (当您发送电子邮件时,布尔值设置为
    true
寄存器关闭函数示例
将AWS SES与PHP编译器一起使用

这种方式非常快(每秒数百条消息),并且不需要太多代码

$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; 
不确定我是否正确地解释了你的问题,但我希望这能有所帮助。

是你的朋友:)
这是我如何在生产应用程序中创建的示例

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中安装和使用线程的更多帮助,请与我联系
对于日志系统,我强烈建议您使用:功能强大、易于使用和配置

对于发送邮件,我还强烈建议您使用一种简单的方法,即调用异步处理邮件的代码

例如,如果您有一个名为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完成发送电子邮件的情况下完成。日志也可以添加到处理电子邮件的文件中

变量可以在被调用的文件名和
/dev/null
之间传递到exec中

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

确保这些变量在使用时是安全的。在被调用的文件中,这些变量可以与

一起使用,最好的选择是堆叠或假脱机模式。它相当简单,可以用两个步骤来描述

  • 将电子邮件存储在表中,并在当前线程上显示“已发送”标志
  • 使用cron或ajax反复调用邮件处理php文件,该文件将从数据库中获取前10或20封未发送的电子邮件,将它们标记为已发送,并通过您最喜欢的邮件方法实际发送它们

我正在使用异步php执行。
它是一个简单的消息队列,非常轻量级,易于集成

为php使用以下php包装器 您可以执行以下操作来实现电子邮件工作程序:

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的链接来解决)

我希望它能有所帮助。

php fpm 必须运行php fpm才能使用

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();
}
时髦的背景工作者 立即暂停一个curl,让新请求处理它。我是在共享主机上做这件事的。(从来都不酷)

欢迎使用异步PHP

$loop=\React\EventLoop\Factory::create();
$smtp=new\Shuchkin\ReactSMTP\Client($loop,'tls://smtp.google.com:465', 'username@gmail.com“,”密码“);
$smtp->send($smtp)username@gmail.com“谢尔盖。shuchkin@gmail.com“,”梅勒,“你好,谢尔盖!”)->(
函数(){
回显“通过谷歌SMTP发送的邮件”。PHP_EOL;
},
函数(\Exception$ex){
回显“SMTP错误”。$ex->getCode()。。$ex->getMessage().PHP\u EOL;
}
);
$loop->run();

exec('php maiscript.php…想法:将邮件作为队列存储在某处,而不是发送,并使用后台脚本从队列中发送。使用线程,它们是异步的:
我希望提供最少的代码量
-因此不是乞求代码的地方。这个“问题”应该已经结束。使用“赏金”要像你做的那样防止,这简直太糟糕了。如果你想对邮件进行排队并异步发送,只需切换到一个有smtpd的smtpd。为什么要重新发明轮子?代码执行得很快?它在关机时不是同步的吗?register\u shutdown\u函数是同步的,但它是在响应发送到客户端后执行的,所以我不在乎例如,发送需要10秒。在我的测试中,完成响应几乎需要5秒。:(您的测试可能错误。您可以粘贴整个测试
exit
不退出进程,并在注册关闭函数时关闭连接。如果您将最后2行代码替换为
MailSpool::send()
同样的事情也会发生。仍然需要4秒钟才能做出Web响应。:/这可能对这种情况没有帮助,但也是一个很好的解决方案
$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.";