使用Swoole异步发送邮件

2018-08-09 15:56:09 浏览数 (1)

最近做公司的一个管理系统,需要把每天的统计信息发送到领导的邮箱。由于使用SMTP协议发送邮件的速度太慢,所以只能异步发送。刚开始实现了一个基于php-reque redis的异步发送,但后来我觉得实现得不够优雅,可控性也不是很高,所以后面选择了使用swoole扩展来实现异步。 Swoole简介极安装请参见文档:http://www.swoole.com/ swoole的模式大致是,写一个server端,通过cli模式运行,实现守护进程。然后在通过一个client端去连接server端,并发送信息,server端收到信息后,通过回调函数,执行相应的程序。

使用server响应请求并发送邮件: 发送邮件使用了swiftmailer,可以通过composer安装它:php composer.phar require swiftmailer/swiftmailer @stable

代码语言:javascript复制
<?php
/**
 * @author  fatrbaby
 * @created 2015/4/29 9:10
 */
require __DIR__ . '/vendor/autoload.php';

class MailServer
{
    const MAIL_USERNAME = 'user@example.com';
    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并发送数据:

代码语言:javascript复制
<?php
/**
 * @author  fatrbaby
 * @created 2015/4/29 9:20
 */

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 CException(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 CException('Swoole Server does not connected.');
        }
    }

    public function close()
    {
        $this->client->close();
    }
}

使用:

代码语言:javascript复制
$data = array(
    'address' => $mails,
    'subject' => $subject,
    'body' => htmlspecialchars($body),
);

$mailClient = new MailClient();
$mailClient->connect();

if ($mailClient->send($data)) {
    echo 'success';
} else {
    echo 'fail';
}

$mailClient->close();

0 人点赞