使用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)

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

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Albert陈凯

Spark详解05架构Architecture架构

架构 前三章从 job 的角度介绍了用户写的 program 如何一步步地被分解和执行。这一章主要从架构的角度来讨论 master,worker,driver ...

3218
来自专栏C#

开源的C#实现WebSocket协议客户端和服务器websocket-sharp组件解析

  很久没有写文章了(至少自己感觉很长时间没有写了),没办法啊,楼主也是需要生活的人啊,这段一直都在找工作什么的。(整天催我代码的人,还望多多谅解啊,我会坚持写...

4.1K10
来自专栏公有云大数据平台弹性 MapReduce

yarn公平调度详细分析(一)

FairScheduler是yarn常用的调度器,但是仅仅参考官方文档,有很多参数和概念文档里没有详细说明,但是这些参明显会影响到集群的正常运行。本文的主要目的...

1.6K17
来自专栏工科狗和生物喵

FreeRTOS-Qemu 实现三任务同步通信机制以及API信息

---- 1. 本次作业的考察要点: 作业地址:https://github.com/HustWolfzzb/STM32F429DiscoveryFreeRTO...

1.1K6
来自专栏NetCore

[原创]Fluent NHibernate之旅(四)-- 关系(上)

经过了前面三篇的介绍,相信大家对Fluent NHibernate已经有一定的了解了,在我们学习中,Fluent 也已经进入了RTM版本。这次的版本发布离RC版...

2166
来自专栏Android 研究

APK安装流程详解7——PackageManagerService的启动流程(上)

我们看到在SystemServer无参构造函数里面就是初始化mFactoryTestMode

1851
来自专栏JAVA高级架构

分布式之延时任务方案解析

1262
来自专栏小尘哥的专栏

小程序(3):授权登录

判断是否授权,如果没有,则显示授权按钮。注意上面的open-type="getUserInfo",这个会自动调起授权框。看一下js

2444
来自专栏圣杰的专栏

ABP入门系列(10)——扩展AbpSession

源码路径:Github-LearningMpaAbp 一、AbpSession是Session吗? 1、首先来看看它们分别对应的类型是什么? 查看源码发现Ses...

3586
来自专栏刘望舒

Android PMS处理APK的复制

在上一篇文章Android包管理机制之PackageInstaller安装APK中,我们学习了PackageInstaller是如何安装APK的,最后会将APK...

2135

扫码关注云+社区

领取腾讯云代金券