专栏首页后端技术探索使用Swoole异步发送邮件

使用Swoole异步发送邮件

最近做公司的一个管理系统,需要把每天的统计信息发送到领导的邮箱。由于使用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

<?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并发送数据:

<?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();
    }
}

使用:

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

本文分享自微信公众号 - nginx(nginx-study)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2015-12-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 七夕最污代码,单身慎入

    2.找不到对象说爱(Fatal error: Call to a member function on a non-object), 他怎么才能说出爱?

    后端技术探索
  • nginx实现图片防盗链-技术精短文

    前几天讲了《nginx下载防盗链》,今天继续说下图片防盗链. 他们两个使用的指令不同,前者使用secure link,并且需要程序配合,但是效果非常好;后者不需...

    后端技术探索
  • php进阶

    基本数据类型和数组都为真复制,即为真副本,当属性为对象时,为假复制,改变副本仍会影响原对象.解决方案:

    后端技术探索
  • 你知道 android 的 MessageQueue.IdleHandler 吗?

    干货!干货!或许可以是一种处理问题的新思路哟!

    serena
  • 你知道android的MessageQueue.IdleHandler吗?

    前言 我们知道android是基于Looper消息循环的系统,我们通过Handler向Looper包含的MessageQueue投递Message, 不过我们...

    腾讯Bugly
  • Laravel源码分析之Session

    由于HTTP最初是一个匿名、无状态的请求/响应协议,服务器处理来自客户端的请求然后向客户端回送一条响应。现代Web应用程序为了给用户提供个性化的服务往往需要在请...

    KevinYan
  • 【Netty大动脉之ChannelPipeline】

    1、Channel NioServerSocketChannel.class 每一个channel 对应唯一一个Channelpipeline

    用户5640963
  • NGROK内⽹穿透实现本地微信公众号开发

    用户2475223
  • hadoop完全分布式之集群时间同步

    找一个机器,作为时间服务器,所有的机器都和这台机器时间进行定时的同步,比如每隔十分钟,同步一次时间。

    绝命生
  • 完善你的Laravel异常处理

    异常处理是编程中十分重要但也最容易被人忽视的语言特性,它为开发者提供了处理程序运行时错误的机制,对于程序设计来说正确的异常处理能够防止泄露程序自身细节给用户,给...

    KevinYan

扫码关注云+社区

领取腾讯云代金券