最近做公司的一个管理系统,需要把每天的统计信息发送到领导的邮箱。由于使用SMTP
协议发送邮件的速度太慢,所以只能异步发送。使用swoole
扩展来实现异步。
swoole
的模式大致是,写一个server
端,通过cli
模式运行,实现守护进程。然后在通过一个client
端去连接server
端,并发送信息,server端收到信息后,通过回调函数,执行相应的程序。
发送邮件使用了swiftmailer,可以通过composer安装它:php composer.phar require swiftmailer/swiftmailer
使用server响应请求,并发送邮件:
<?php require __DIR__ . '/vendor/autoload.php'; class MailServer { const MAIL_USERNAME = '[email protected]'; const MAIL_PASSWORD = 'your-password'; private $logger = null; private $server = null; public function __construct() { $this->server = new swoole_server('127.0.0.1', 9501); $this->server->set([ 'worker_num' => 8, 'daemonize' => false, 'max_request' => 10000, 'dispatch_mode' => 2, 'debug_mode'=> 1, ]); $this->server->on('Start', [$this, 'onStart']); $this->server->on('Connect', [$this, 'onConnect']); $this->server->on('Receive', [$this, 'onReceive']); $this->server->on('Close', [$this, 'onClose']); $this->server->start(); } public function onStart() { } public function onConnect($server, $descriptors, $fromId) { } public function onReceive(swoole_server $server, $descriptors, $fromId, $data) { $msg = json_decode($data, true); $sent = $this->sendMail($msg['address'], $msg['subject'], $msg['body']); printf("%s mail is sent.\n", $sent); } public function onClose($server, $descriptors, $fromId) { } public function sendMail($address, $subject, $body) { $body = htmlspecialchars_decode($body); $transport = Swift_SmtpTransport::newInstance('smtp.partner.outlook.cn', 587, 'tls'); $transport->setUsername(self::MAIL_USERNAME); $transport->setPassword(self::MAIL_PASSWORD); $mailer = Swift_Mailer::newInstance($transport); $message = Swift_Message::newInstance(); $message->setFrom([self::MAIL_USERNAME=>'××管理系统']); $message->setTo($address); $message->setSubject($subject); $message->addPart($body, 'text/html'); $message->setBody($body); return $mailer->send($message); } } $server = new MailServer();
使用cli启动服务端:php mail_server.php, 如果想服务端后台执行,修改配置数组'daemonize' => false为'daemonize' => true。
使用client连接server并发送数据:
<?php class MailClient { private $client; public function __construct() { $this->client = new swoole_client(SWOOLE_SOCK_TCP); } public function connect() { if (!$this->client->connect('127.0.0.1', 9501, 1)) { throw new Exception(sprintf('Swoole Error: %s', $this->client->errCode)); } } public function send($data){ if ($this->client->isConnected()) { if (!is_string($data)) { $data = json_encode($data); } return $this->client->send($data); } else { throw new Exception('Swoole Server does not connected.'); } } public function close() { $this->client->close(); } }
使用:
<?php $data = array( 'address' => $mails, 'subject' => $subject, 'body' => htmlspecialchars($body), ); $client = new MailClient(); $client->connect(); if ($client->send($data)) { echo 'success'; } else { echo 'fail'; } $client->close();
asdfas