swoole发邮件

Swoole:面向生产环境的 PHP 异步网络通信引擎

很早就知道了swoole,但一直没有实际用到生产中,最近在重构博客,就想着做点东西,先swoole发邮件练练手。

回顾下发邮件,我们使用PHPMailer来发送。

<?php
/**
 * Created by PhpStorm.
 * User: puresai
 * Date: 2018/11/29
 * Time: 11:16
 */
require '../vendor/autoload.php';

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;


$mail = new PHPMailer(true);
try {
    //Server settings
    // $mail->SMTPDebug = 2;                                 // Enable verbose debug output
    $mail->isSMTP();                                      // Set mailer to use SMTP
    $mail->Host = 'smtp.163.com';  // Specify main and backup SMTP servers
    $mail->SMTPAuth = true;                               // Enable SMTP authentication
    $mail->Username = '[email protected]';                 // SMTP username
    $mail->Password = '*';                           // SMTP password
    $mail->SMTPSecure = 'tls';                            // Enable TLS encryption, ssl also accepted
    $mail->Port = 25;                                    // TCP port to connect to


    //收件人
    $mail->setFrom('[email protected]', 'puresai');
    $mail->addAddress('[email protected]');               // Name is optional
    $mail->addReplyTo('[email protected]', 'Information');
//    $mail->addCC('[email protected]');
//    $mail->addBCC('[email protected]');


    //附件
    $mail->addAttachment('/var/file.tar.gz');         // Add attachments
    $mail->addAttachment('/tmp/image.jpg', 'new.jpg');    // Optional name


    //html
    $mail->isHTML(true);                           
    $mail->Subject = 'Here is the subject';
    $mail->Body    = 'This is the HTML message body <b>in bold!</b>';
    $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';


    $mail->send();
    echo 'Message has been sent';
} catch (Exception $e) {
    echo 'Message could not be sent.';
    echo 'Mailer Error: ' . $mail->ErrorInfo;
}

运行发送,收到邮件。

主程序

<?php
/**
  Created by PhpStorm.
  User: puresai
  Date: 2018/11/29
  Time: 14:06
/

require dirname(DIR).'/vendor/autoload.php';

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;


class Mailer
{
    protected $server;
    protected $host = '127.0.0.1';
    protected $port = 9502;
    // 进程名称
    protected $taskName = 'swooleMailer';
    // PID路径
    protected $pidPath = '/run/swooleMail.pid';
    // 设置运行时参数
    protected $options = [
        'worker_num' => 4, //worker进程数,一般设置为CPU数的1-4'daemonize' => true, //启用守护进程
        'log_file' => '/data/logs/swoole.log', //指定swoole错误日志文件
        'log_level' => 0, //日志级别 范围是0-50-DEBUG,1-TRACE,2-INFO,3-NOTICE,4-WARNING,5-ERROR
        'dispatch_mode' => 1, //数据包分发策略,1-轮询模式
        'task_worker_num' => 4, //task进程的数量
        'task_ipc_mode' => 3, //使用消息队列通信,并设置为争抢模式
        //'heartbeat_idle_time' => 600, //一个连接如果600秒内未向服务器发送任何数据,此连接将被强制关闭
        //'heartbeat_check_interval' => 60, //启用心跳检测,每隔60s轮循一次
    ];
    // 邮件服务器配置
    protected $mailConfig = [
        'smtp_host' => 'smtp.163.com',
        'username' => '[email protected]',
        'password' => 'xmw1015',// SMTP 密码/口令
        'secure' => 'ssl', //Enable TLS encryption, ssl also accepted
        'port' => 465, // tcp邮件服务器端口
    ];


    public function __construct($mailConfig, $options = [])
    {
        // 构建Server对象,监听端口
        $this->server = new swoole_server($this->host, $this->port);


        if (!empty($options)) {
            $this->options = array_merge($this->options, $options);
        }
        $this->server->set($this->options);


        $this->mailConfig = $mailConfig;


        // 注册事件
        $this->server->on('Start', [$this, 'onStart']);
        $this->server->on('Connect', [$this, 'onConnect']);
        $this->server->on('Receive', [$this, 'onReceive']);
        $this->server->on('Task', [$this, 'onTask']);
        $this->server->on('Finish', [$this, 'onFinish']);
        $this->server->on('Close', [$this, 'onClose']);


        // 启动服务
        //$this->server->start();
    }


    protected function init()
    {
        //
    }


    public function start()
    {
        // Run worker
        $this->server->start();
    }


    public function onStart($server)
    {
        // 设置进程名
        cli_set_process_title($this->taskName);
        //记录进程id,脚本实现自动重启
        $pid = "{$server->master_pid}
{$server->manager_pid}";
        file_put_contents($this->pidPath, $pid);
    }


    //监听连接进入事件
    public function onConnect($server, $fd, $from_id)
    {
        $server->send($fd, "Hello {$fd}!" );
    }


    // 监听数据接收事件
    public function onReceive(swoole_server $server, $fd, $from_id, $data)
    {
        $res['result'] = 'success';
        $server->send($fd, json_encode($res)); // 同步返回消息给客户端
        $server->task($data);  // 执行异步任务


    }


    /*
      @param $server swoole_server swoole_server对象
      @param $task_id int 任务id
      @param $from_id int 投递任务的worker_id
      @param $data string 投递的数据
     /
    public function onTask(swoole_server $server, $task_id, $from_id, $data)
    {
        $res['result'] = 'failed';
        $req = json_decode($data, true);
        $action = $req['action'];
        echo date('Y-m-d H:i:s')." onTask: [".$action."].
";
        switch ($action) {
            case 'sendMail': //发送单个邮件
                $mailData = [
                    'emailAddress' => $req['to'], //接收方,改成自己的邮箱可以测试接收邮件
                    'subject' => $req['subject'],
                    'body' => $req['body'],
                ];
                $this->sendMail($mailData);
                break;


            default:
                break;
        }
    }


    /*
      @param $server swoole_server swoole_server对象
      @param $task_id int 任务id
      @param $data string 任务返回的数据
     */
    public function onFinish(swoole_server $server, $task_id, $data)
    {
        //
    }


    // 监听连接关闭事件
    public function onClose($server, $fd, $from_id) {
        echo "Client {$fd} close connection
";
    }


    public function stop()
    {
        $this->server->stop();
    }


    private function sendMail($mailData = [])
    {
        $mail = new PHPMailer(true);


        try {
            $mailConfig = $this->mailConfig;
            $mail->isSMTP();                                   // TCP port to connect to
            $mail->Host = $mailConfig['smtp_host'];  // SMTP服务
            $mail->SMTPAuth = true;                  // Enable SMTP authentication
            $mail->Username = $mailConfig['username'];    // SMTP 用户名
            $mail->Password = $mailConfig['password'];     // SMTP 密码/口令
            $mail->SMTPSecure = $mailConfig['secure'];     // Enable TLS encryption, ssl also accepted
            $mail->Port = $mailConfig['port'];    // TCP 端口


            //Recipients
            $mail->setFrom('[email protected]', 'puresai');
            $mail->addAddress('[email protected]');               // Name is optional
            $mail->addReplyTo('[email protected]', 'Information');


            //Content
            $mail->isHTML(true);                                  // Set email format to HTML
            $mail->Subject = 'Here is the subject';
            $mail->Body    = 'This is the HTML message body <b>in bold!</b>';
            $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';


            $mail->send();
            echo 'Message has been sent';
        } catch (Exception $e) {
            echo 'Message could not be sent.';
            echo 'Mailer Error: ' . $mail->ErrorInfo;
        }


        try {
            $mailConfig = $this->mailConfig;
            $mail->isSMTP();   // Set mailer to use SMTP
            $mail->Host = $mailConfig['smtp_host'];  // SMTP服务
            $mail->SMTPAuth = true;                  // Enable SMTP authentication
            $mail->Username = $mailConfig['username'];    // SMTP 用户名
            $mail->Password = $mailConfig['password'];     // SMTP 密码/口令
            $mail->SMTPSecure = $mailConfig['secure'];     // Enable TLS encryption, ssl also accepted
            $mail->Port = $mailConfig['port'];    // TCP 端口


            $mail->CharSet  = "UTF-8"; //字符集
            $mail->setFrom($mailConfig['username'], 'puresai'); //发件人地址,名称
            $mail->addAddress($mailData['emailAddress'], '亲');     // 收件人地址和名称
            //$mail->addCC('[email protected]'); // 抄送


            if (isset($mailData['attach'])) {
                $mail->addAttachment($mailData['attach']);         // 添加附件
            }


            //$mail->addAttachment('/tmp/image.jpg', 'new.jpg');    // Optional name


            //Content
            $mail->isHTML(true);                                  // Set email format to HTML
            $mail->Subject = $mailData['subject'];
            $mail->Body    = $mailData['body'];


            $mail->send();
            return true;
        } catch (\Exception $e) {
            echo 'Message could not be sent. Mailer Error: '. $mail->ErrorInfo;
            return false;
        }
    }
}

服务:

<?php
/*
  Created by PhpStorm.
  User: puresai
  Date: 2018/11/29
  Time: 14:09
 /

require DIR . '/Mailer.php';


$config = [
    'smtp_host' => 'smtp.163.com',
    'username' => '[email protected]',
    'password' => '',
    'secure' => 'ssl',
    'port' => 465
];
$server = new Mailer($config);
$server->start();

发送

<?php
/**
  Created by PhpStorm.
  User: puresai
  Date: 2018/11/29
  Time: 14:14
 /

class Client
{
    private $client;


    public function __construct() {
        $this->client = new swoole_client(SWOOLE_SOCK_TCP);
    }


    public function send() {
        if( !$this->client->connect("127.0.0.1", 9502 , 1) ) {
            echo "Error: {$this->client->errMsg}[{$this->client->errCode}]
";
        }


        $action = 'sendMail';
        $time = time();
        $data = [
            'action' => $action,
            'to' => '[email protected]',
            'subject' => 'wow',
            'body' => 'hello, puresai!'
        ];
        $msg = json_encode($data);


        $this->client->send( $msg );
        $message = $this->client->recv();
        echo "Get Message From Server:{$message}
";
    }
}


$client = new Client();
$client->send();

测试通过!

注意:

此处我用了25端口,部署到Linux时上发送邮件发不出去,把PHPMailer的错误说明查了个遍,wrong,端口改为465,使用ssl发送,ok!

心累。


swoole发邮件
https://blog.puresai.com/2018/11/29/171/
作者
puresai
许可协议