Maison >développement back-end >tutoriel php >PHP 进展统一邮箱登陆的代理实现(swoole)

PHP 进展统一邮箱登陆的代理实现(swoole)

WBOY
WBOYoriginal
2016-06-13 12:27:421012parcourir

PHP 进行统一邮箱登陆的代理实现(swoole)

  在工作的过程中,经常会有很多应用有发邮件的需求,这个时候需要在每个应用中配置smtp服务器。一旦公司调整了smtp服务器的配置,比如修改了密码等,这个时候对于维护的人员来说要逐一修改应用中smtp的配置。这样的情况虽然不多见,但遇上了还是很头痛的一件事情。

 

  知道了问题,解决起来就有了方向。于是就有了自己开发一个简单的smtp代理的想法,这个代理主要的功能(参照问题)主要是:

    1.接受指定IP应用的smtp请求;

    2.应用不需要知道smtp的用户和密码;

    3.转发应用的smtp请求。

 

  开发的环境:Linux,php(swoole);

  代码如下:

<span style="color: #000000;">php</span><span style="color: #008000;">/*</span><span style="color: #008000;">* * * SMTP Proxy Server * @author Terry Zhang, 2015-11-13 * * @version 1.0 * * 注意:本程序只能运行在cli模式,且需要扩展Swoole 1.7.20+的支持。 * * Swoole的源代码及安装请参考 https://github.com/swoole/swoole-src/ * * 本程序的使用场景: *  * 在多个分散的系统中使用同一的邮件地址进行系统邮件发送时,一旦邮箱密码修改,则要修改每个系统的邮件配置参数。 * 同时,在每个系统中配置邮箱参数,使得邮箱的密码容易外泄。 *  * 通过本代理进行邮件发送的客户端,可以随便指定用户名和密码。 *  *  </span><span style="color: #008000;">*/</span><span style="color: #008000;">//</span><span style="color: #008000;">error_reporting(0);</span><span style="color: #008080;">defined</span>('DEBUG_ON') or <span style="color: #008080;">define</span>('DEBUG_ON', <span style="color: #0000ff;">false</span><span style="color: #000000;">);</span><span style="color: #008000;">//</span><span style="color: #008000;">主目录</span><span style="color: #008080;">defined</span>('BASE_PATH') or <span style="color: #008080;">define</span>('BASE_PATH',<span style="color: #000000;"> __DIR__);</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> CSmtpProxy{        </span><span style="color: #008000;">//</span><span style="color: #008000;">软件版本</span>    <span style="color: #0000ff;">const</span> VERSION = '1.0'<span style="color: #000000;">;            </span><span style="color: #0000ff;">const</span> EOF = "\r\n"<span style="color: #000000;">;            </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #800080;">$software</span> = "SMTP-Proxy-Server"<span style="color: #000000;">;        </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #800080;">$server_mode</span> =<span style="color: #000000;"> SWOOLE_PROCESS;            </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #800080;">$pid_file</span><span style="color: #000000;">;        </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #800080;">$log_file</span><span style="color: #000000;">;        </span><span style="color: #0000ff;">private</span> <span style="color: #800080;">$smtp_host</span> = 'localhost'<span style="color: #000000;">;        </span><span style="color: #0000ff;">private</span> <span style="color: #800080;">$smtp_port</span> = 25<span style="color: #000000;">;        </span><span style="color: #0000ff;">private</span> <span style="color: #800080;">$smtp_user</span> = ''<span style="color: #000000;">;        </span><span style="color: #0000ff;">private</span> <span style="color: #800080;">$smtp_pass</span> = ''<span style="color: #000000;">;        </span><span style="color: #0000ff;">private</span> <span style="color: #800080;">$smtp_from</span> = ''<span style="color: #000000;">;        </span><span style="color: #008000;">//</span><span style="color: #008000;">待写入文件的日志队列(缓冲区)</span>    <span style="color: #0000ff;">private</span> <span style="color: #800080;">$queue</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">();        </span><span style="color: #0000ff;">public</span> <span style="color: #800080;">$host</span> = '0.0.0.0'<span style="color: #000000;">;        </span><span style="color: #0000ff;">public</span> <span style="color: #800080;">$port</span> = 25<span style="color: #000000;">;        </span><span style="color: #0000ff;">public</span> <span style="color: #800080;">$setting</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">();        </span><span style="color: #008000;">//</span><span style="color: #008000;">最大连接数</span>    <span style="color: #0000ff;">public</span> <span style="color: #800080;">$max_connection</span> = 50<span style="color: #000000;">;        </span><span style="color: #008000;">/*</span><span style="color: #008000;">*     * @var swoole_server     </span><span style="color: #008000;">*/</span>    <span style="color: #0000ff;">protected</span> <span style="color: #800080;">$server</span><span style="color: #000000;">;        </span><span style="color: #0000ff;">protected</span> <span style="color: #800080;">$connection</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">();        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">function</span> setPidFile(<span style="color: #800080;">$pid_file</span><span style="color: #000000;">){        self</span>::<span style="color: #800080;">$pid_file</span> = <span style="color: #800080;">$pid_file</span><span style="color: #000000;">;    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">function</span> start(<span style="color: #800080;">$startFunc</span><span style="color: #000000;">){        </span><span style="color: #0000ff;">if</span>(!<span style="color: #008080;">extension_loaded</span>('swoole'<span style="color: #000000;">)){            </span><span style="color: #0000ff;">exit</span>("Require extension `swoole`.\n"<span style="color: #000000;">);        }        </span><span style="color: #800080;">$pid_file</span> = self::<span style="color: #800080;">$pid_file</span><span style="color: #000000;">;        </span><span style="color: #800080;">$server_pid</span> = 0<span style="color: #000000;">;        </span><span style="color: #0000ff;">if</span>(<span style="color: #008080;">is_file</span>(<span style="color: #800080;">$pid_file</span><span style="color: #000000;">)){            </span><span style="color: #800080;">$server_pid</span> = <span style="color: #008080;">file_get_contents</span>(<span style="color: #800080;">$pid_file</span><span style="color: #000000;">);        }        </span><span style="color: #0000ff;">global</span> <span style="color: #800080;">$argv</span><span style="color: #000000;">;        </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">empty</span>(<span style="color: #800080;">$argv</span>[1<span style="color: #000000;">])){            goto usage;        }</span><span style="color: #0000ff;">elseif</span>(<span style="color: #800080;">$argv</span>[1] == 'reload'<span style="color: #000000;">){            </span><span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">empty</span>(<span style="color: #800080;">$server_pid</span><span style="color: #000000;">)){                </span><span style="color: #0000ff;">exit</span>("SMTP Proxy Server is not running\n"<span style="color: #000000;">);            }            posix_kill(</span><span style="color: #800080;">$server_pid</span>,<span style="color: #000000;"> SIGUSR1);            </span><span style="color: #0000ff;">exit</span><span style="color: #000000;">;        }</span><span style="color: #0000ff;">elseif</span> (<span style="color: #800080;">$argv</span>[1] == 'stop'<span style="color: #000000;">){            </span><span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">empty</span>(<span style="color: #800080;">$server_pid</span><span style="color: #000000;">)){                </span><span style="color: #0000ff;">exit</span>("SMTP Proxy is not running\n"<span style="color: #000000;">);            }            posix_kill(</span><span style="color: #800080;">$server_pid</span>,<span style="color: #000000;"> SIGTERM);            </span><span style="color: #0000ff;">exit</span><span style="color: #000000;">;        }</span><span style="color: #0000ff;">elseif</span> (<span style="color: #800080;">$argv</span>[1] == 'start'<span style="color: #000000;">){            </span><span style="color: #008000;">//</span><span style="color: #008000;">已存在ServerPID,并且进程存在</span>            <span style="color: #0000ff;">if</span> (!<span style="color: #0000ff;">empty</span>(<span style="color: #800080;">$server_pid</span>) and posix_kill(<span style="color: #800080;">$server_pid</span>,(int) 0<span style="color: #000000;">)){                </span><span style="color: #0000ff;">exit</span>("SMTP Proxy is already running.\n"<span style="color: #000000;">);            }            </span><span style="color: #008000;">//</span><span style="color: #008000;">启动服务器</span>            <span style="color: #800080;">$startFunc</span><span style="color: #000000;">();        }</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{            usage</span>:            <span style="color: #0000ff;">exit</span>("Usage: php {<span style="color: #800080;">$argv</span>[0]} start|stop|reload\n"<span style="color: #000000;">);        }    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> __construct(<span style="color: #800080;">$host</span>,<span style="color: #800080;">$port</span><span style="color: #000000;">){            </span><span style="color: #800080;">$flag</span> =<span style="color: #000000;"> SWOOLE_SOCK_TCP;        </span><span style="color: #800080;">$this</span>->server = <span style="color: #0000ff;">new</span> swoole_server(<span style="color: #800080;">$host</span>,<span style="color: #800080;">$port</span>,self::<span style="color: #800080;">$server_mode</span>,<span style="color: #800080;">$flag</span><span style="color: #000000;">);        </span><span style="color: #800080;">$this</span>->host = <span style="color: #800080;">$host</span><span style="color: #000000;">;        </span><span style="color: #800080;">$this</span>->port = <span style="color: #800080;">$port</span><span style="color: #000000;">;        </span><span style="color: #800080;">$this</span>->setting = <span style="color: #0000ff;">array</span><span style="color: #000000;">(                </span>'backlog' => 128,                'dispatch_mode' => 2,<span style="color: #000000;">        );    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> daemonize(){        </span><span style="color: #800080;">$this</span>->setting['daemonize'] = 1<span style="color: #000000;">;    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> getConnectionInfo(<span style="color: #800080;">$fd</span><span style="color: #000000;">){        </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$this</span>->server->connection_info(<span style="color: #800080;">$fd</span><span style="color: #000000;">);    }        </span><span style="color: #008000;">/*</span><span style="color: #008000;">*     * 启动服务进程     * @param array $setting     * @throws Exception     </span><span style="color: #008000;">*/</span>    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> run(<span style="color: #800080;">$setting</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">()){        </span><span style="color: #800080;">$this</span>->setting = <span style="color: #008080;">array_merge</span>(<span style="color: #800080;">$this</span>->setting,<span style="color: #800080;">$setting</span><span style="color: #000000;">);        </span><span style="color: #008000;">//</span><span style="color: #008000;">不使用swoole的默认日志</span>        <span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$this</span>->setting['log_file'<span style="color: #000000;">])){            self</span>::<span style="color: #800080;">$log_file</span> = <span style="color: #800080;">$this</span>->setting['log_file'<span style="color: #000000;">];            </span><span style="color: #0000ff;">unset</span>(<span style="color: #800080;">$this</span>->setting['log_file'<span style="color: #000000;">]);        }        </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$this</span>->setting['max_connection'<span style="color: #000000;">])){            </span><span style="color: #800080;">$this</span>->max_connection = <span style="color: #800080;">$this</span>->setting['max_connection'<span style="color: #000000;">];            </span><span style="color: #0000ff;">unset</span>(<span style="color: #800080;">$this</span>->setting['max_connection'<span style="color: #000000;">]);        }        </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$this</span>->setting['smtp_host'<span style="color: #000000;">])){            </span><span style="color: #800080;">$this</span>->smtp_host = <span style="color: #800080;">$this</span>->setting['smtp_host'<span style="color: #000000;">];            </span><span style="color: #0000ff;">unset</span>(<span style="color: #800080;">$this</span>->setting['smtp_host'<span style="color: #000000;">]);        }        </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$this</span>->setting['smtp_port'<span style="color: #000000;">])){            </span><span style="color: #800080;">$this</span>->smtp_port = <span style="color: #800080;">$this</span>->setting['smtp_port'<span style="color: #000000;">];            </span><span style="color: #0000ff;">unset</span>(<span style="color: #800080;">$this</span>->setting['smtp_port'<span style="color: #000000;">]);        }        </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$this</span>->setting['smtp_user'<span style="color: #000000;">])){            </span><span style="color: #800080;">$this</span>->smtp_user = <span style="color: #800080;">$this</span>->setting['smtp_user'<span style="color: #000000;">];            </span><span style="color: #0000ff;">unset</span>(<span style="color: #800080;">$this</span>->setting['smtp_user'<span style="color: #000000;">]);        }        </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$this</span>->setting['smtp_pass'<span style="color: #000000;">])){            </span><span style="color: #800080;">$this</span>->smtp_pass = <span style="color: #800080;">$this</span>->setting['smtp_pass'<span style="color: #000000;">];            </span><span style="color: #0000ff;">unset</span>(<span style="color: #800080;">$this</span>->setting['smtp_pass'<span style="color: #000000;">]);        }        </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$this</span>->setting['smtp_from'<span style="color: #000000;">])){            </span><span style="color: #800080;">$this</span>->smtp_from = <span style="color: #800080;">$this</span>->setting['smtp_from'<span style="color: #000000;">];            </span><span style="color: #0000ff;">unset</span>(<span style="color: #800080;">$this</span>->setting['smtp_from'<span style="color: #000000;">]);        }            </span><span style="color: #800080;">$this</span>->server->set(<span style="color: #800080;">$this</span>-><span style="color: #000000;">setting);        </span><span style="color: #800080;">$version</span> = <span style="color: #008080;">explode</span>('.',<span style="color: #000000;"> SWOOLE_VERSION);        </span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$version</span>[0] == 1 && <span style="color: #800080;">$version</span>[1] $version[2] ){            <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> <span style="color: #0000ff;">Exception</span>('Swoole version require 1.7.20 +.'<span style="color: #000000;">);        }        </span><span style="color: #008000;">//</span><span style="color: #008000;">事件绑定</span>        <span style="color: #800080;">$this</span>->server->on('start',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onMasterStart'<span style="color: #000000;">));        </span><span style="color: #800080;">$this</span>->server->on('shutdown',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onMasterStop'<span style="color: #000000;">));        </span><span style="color: #800080;">$this</span>->server->on('ManagerStart',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onManagerStart'<span style="color: #000000;">));        </span><span style="color: #800080;">$this</span>->server->on('ManagerStop',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onManagerStop'<span style="color: #000000;">));        </span><span style="color: #800080;">$this</span>->server->on('WorkerStart',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onWorkerStart'<span style="color: #000000;">));        </span><span style="color: #800080;">$this</span>->server->on('WorkerStop',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onWorkerStop'<span style="color: #000000;">));        </span><span style="color: #800080;">$this</span>->server->on('WorkerError',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onWorkerError'<span style="color: #000000;">));        </span><span style="color: #800080;">$this</span>->server->on('Connect',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onConnect'<span style="color: #000000;">));        </span><span style="color: #800080;">$this</span>->server->on('Receive',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onReceive'<span style="color: #000000;">));        </span><span style="color: #800080;">$this</span>->server->on('Close',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onClose'<span style="color: #000000;">));                    </span><span style="color: #800080;">$this</span>->server-><span style="color: #000000;">start();    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> <span style="color: #008080;">log</span>(<span style="color: #800080;">$msg</span>,<span style="color: #800080;">$level</span> = 'debug',<span style="color: #800080;">$flush</span> = <span style="color: #0000ff;">false</span><span style="color: #000000;">){        </span><span style="color: #0000ff;">if</span><span style="color: #000000;">(DEBUG_ON){            </span><span style="color: #800080;">$log</span> = <span style="color: #008080;">date</span>('Y-m-d H:i:s').' ['.<span style="color: #800080;">$level</span>."]\t" .<span style="color: #800080;">$msg</span>."\n"<span style="color: #000000;">;            </span><span style="color: #0000ff;">if</span>(!<span style="color: #0000ff;">empty</span>(self::<span style="color: #800080;">$log_file</span><span style="color: #000000;">)){                </span><span style="color: #800080;">$debug_file</span> = <span style="color: #008080;">dirname</span>(self::<span style="color: #800080;">$log_file</span>).'/debug.log'<span style="color: #000000;">;                </span><span style="color: #008080;">file_put_contents</span>(<span style="color: #800080;">$debug_file</span>, <span style="color: #800080;">$log</span>,<span style="color: #000000;">FILE_APPEND);                </span><span style="color: #0000ff;">if</span>(<span style="color: #008080;">filesize</span>(<span style="color: #800080;">$debug_file</span>) > 10485760){<span style="color: #008000;">//</span><span style="color: #008000;">10M</span>                    <span style="color: #008080;">unlink</span>(<span style="color: #800080;">$debug_file</span><span style="color: #000000;">);                }            }            </span><span style="color: #0000ff;">echo</span> <span style="color: #800080;">$log</span><span style="color: #000000;">;        }        </span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$level</span> != 'debug'<span style="color: #000000;">){            </span><span style="color: #008000;">//</span><span style="color: #008000;">日志记录</span>            <span style="color: #800080;">$this</span>->queue[] = <span style="color: #008080;">date</span>('Y-m-d H:i:s')."\t[".<span style="color: #800080;">$level</span>."]\t".<span style="color: #800080;">$msg</span><span style="color: #000000;">;        }        </span><span style="color: #0000ff;">if</span>(<span style="color: #008080;">count</span>(<span style="color: #800080;">$this</span>->queue)>10 && !<span style="color: #0000ff;">empty</span>(self::<span style="color: #800080;">$log_file</span>) || <span style="color: #800080;">$flush</span><span style="color: #000000;">){            </span><span style="color: #0000ff;">if</span> (<span style="color: #008080;">filesize</span>(self::<span style="color: #800080;">$log_file</span>) > 209715200){ <span style="color: #008000;">//</span><span style="color: #008000;">200M</span>                <span style="color: #008080;">rename</span>(self::<span style="color: #800080;">$log_file</span>,self::<span style="color: #800080;">$log_file</span>.'.'.<span style="color: #008080;">date</span>('His'<span style="color: #000000;">));            }            </span><span style="color: #800080;">$logs</span> = ''<span style="color: #000000;">;            </span><span style="color: #0000ff;">foreach</span> (<span style="color: #800080;">$this</span>->queue <span style="color: #0000ff;">as</span> <span style="color: #800080;">$q</span><span style="color: #000000;">){                </span><span style="color: #800080;">$logs</span> .= <span style="color: #800080;">$q</span>."\n"<span style="color: #000000;">;            }            </span><span style="color: #008080;">file_put_contents</span>(self::<span style="color: #800080;">$log_file</span>, <span style="color: #800080;">$logs</span>,<span style="color: #000000;">FILE_APPEND);            </span><span style="color: #800080;">$this</span>->queue = <span style="color: #0000ff;">array</span><span style="color: #000000;">();        }    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> shutdown(){        </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$this</span>->server-><span style="color: #000000;">shutdown();    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> close(<span style="color: #800080;">$fd</span><span style="color: #000000;">){        </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$this</span>->server->close(<span style="color: #800080;">$fd</span><span style="color: #000000;">);    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> send(<span style="color: #800080;">$fd</span>,<span style="color: #800080;">$data</span><span style="color: #000000;">){        </span><span style="color: #800080;">$data</span> = <span style="color: #008080;">strtr</span>(<span style="color: #800080;">$data</span>,<span style="color: #0000ff;">array</span>("\n" => "", "\0" => "", "\r" => ""<span style="color: #000000;">));        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>("[P --> C]\t" . <span style="color: #800080;">$data</span><span style="color: #000000;">);        </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$this</span>->server->send(<span style="color: #800080;">$fd</span>,<span style="color: #800080;">$data</span>.self::<span style="color: #000000;">EOF);    }            </span><span style="color: #008000;">/*</span><span style="color: #008000;">+++++++++++++++++++++++++++++++++++++++++++++++++++++++++     + 事件回调    +++++++++++++++++++++++++++++++++++++++++++++++++++++++++</span><span style="color: #008000;">*/</span>        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onMasterStart(<span style="color: #800080;">$serv</span><span style="color: #000000;">){        </span><span style="color: #0000ff;">global</span> <span style="color: #800080;">$argv</span><span style="color: #000000;">;        swoole_set_process_name(</span>'php '.<span style="color: #800080;">$argv</span>[0].': master -host='.<span style="color: #800080;">$this</span>->host.' -port='.<span style="color: #800080;">$this</span>-><span style="color: #000000;">port);        </span><span style="color: #0000ff;">if</span>(!<span style="color: #0000ff;">empty</span>(<span style="color: #800080;">$this</span>->setting['pid_file'<span style="color: #000000;">])){            </span><span style="color: #008080;">file_put_contents</span>(self::<span style="color: #800080;">$pid_file</span>, <span style="color: #800080;">$serv</span>-><span style="color: #000000;">master_pid);        }        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>('Master started.'<span style="color: #000000;">);    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onMasterStop(<span style="color: #800080;">$serv</span><span style="color: #000000;">){        </span><span style="color: #0000ff;">if</span> (!<span style="color: #0000ff;">empty</span>(<span style="color: #800080;">$this</span>->setting['pid_file'<span style="color: #000000;">])){            </span><span style="color: #008080;">unlink</span>(self::<span style="color: #800080;">$pid_file</span><span style="color: #000000;">);        }        </span><span style="color: #800080;">$this</span>->shm-><span style="color: #000000;">delete();        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>('Master stop.'<span style="color: #000000;">);    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onManagerStart(<span style="color: #800080;">$serv</span><span style="color: #000000;">){        </span><span style="color: #0000ff;">global</span> <span style="color: #800080;">$argv</span><span style="color: #000000;">;        swoole_set_process_name(</span>'php '.<span style="color: #800080;">$argv</span>[0].': manager'<span style="color: #000000;">);        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>('Manager started.'<span style="color: #000000;">);    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onManagerStop(<span style="color: #800080;">$serv</span><span style="color: #000000;">){        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>('Manager stop.'<span style="color: #000000;">);    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onWorkerStart(<span style="color: #800080;">$serv</span>,<span style="color: #800080;">$worker_id</span><span style="color: #000000;">){        </span><span style="color: #0000ff;">global</span> <span style="color: #800080;">$argv</span><span style="color: #000000;">;        </span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$worker_id</span> >= <span style="color: #800080;">$serv</span>->setting['worker_num'<span style="color: #000000;">]) {            swoole_set_process_name(</span>"php {<span style="color: #800080;">$argv</span>[0]}: worker [task]"<span style="color: #000000;">);        } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {            swoole_set_process_name(</span>"php {<span style="color: #800080;">$argv</span>[0]}: worker [{<span style="color: #800080;">$worker_id</span>}]"<span style="color: #000000;">);        }        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>("Worker {<span style="color: #800080;">$worker_id</span>} started."<span style="color: #000000;">);    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onWorkerStop(<span style="color: #800080;">$serv</span>,<span style="color: #800080;">$worker_id</span><span style="color: #000000;">){        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>("Worker {<span style="color: #800080;">$worker_id</span>} stop."<span style="color: #000000;">);    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onWorkerError(<span style="color: #800080;">$serv</span>,<span style="color: #800080;">$worker_id</span>,<span style="color: #800080;">$worker_pid</span>,<span style="color: #800080;">$exit_code</span><span style="color: #000000;">){        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>("Worker {<span style="color: #800080;">$worker_id</span>} error:{<span style="color: #800080;">$exit_code</span>}."<span style="color: #000000;">);    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onConnect(<span style="color: #800080;">$serv</span>,<span style="color: #800080;">$fd</span>,<span style="color: #800080;">$from_id</span><span style="color: #000000;">){        </span><span style="color: #0000ff;">if</span>(<span style="color: #008080;">count</span>(<span style="color: #800080;">$this</span>->server->connections) $this-><span style="color: #000000;">max_connection){            </span><span style="color: #800080;">$info</span> = <span style="color: #800080;">$this</span>->getConnectionInfo(<span style="color: #800080;">$fd</span><span style="color: #000000;">);            </span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$this</span>->isIpAllow(<span style="color: #800080;">$info</span>['remote_ip'<span style="color: #000000;">])){                </span><span style="color: #008000;">//</span><span style="color: #008000;">建立服务器连接</span>                <span style="color: #800080;">$cli</span> = <span style="color: #0000ff;">new</span> Client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC); <span style="color: #008000;">//</span><span style="color: #008000;">异步非阻塞</span>                <span style="color: #800080;">$cli</span>->on('connect',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onServerConnect'<span style="color: #000000;">));                </span><span style="color: #800080;">$cli</span>->on('receive',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onServerReceive'<span style="color: #000000;">));                </span><span style="color: #800080;">$cli</span>->on('error',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onServerError'<span style="color: #000000;">));                </span><span style="color: #800080;">$cli</span>->on('close',<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>,'onServerClose'<span style="color: #000000;">));                </span><span style="color: #800080;">$cli</span>->fd = <span style="color: #800080;">$fd</span><span style="color: #000000;">;                </span><span style="color: #800080;">$ip</span> = <span style="color: #008080;">gethostbyname</span>(<span style="color: #800080;">$this</span>-><span style="color: #000000;">smtp_host);                </span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$cli</span>->connect(<span style="color: #800080;">$ip</span>,<span style="color: #800080;">$this</span>->smtp_port) !== <span style="color: #0000ff;">false</span><span style="color: #000000;">){                    </span><span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>] = <span style="color: #800080;">$cli</span><span style="color: #000000;">;                    }</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{                    </span><span style="color: #800080;">$this</span>->close(<span style="color: #800080;">$fd</span><span style="color: #000000;">);                    </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>('Cannot connect to SMTP server. Connection #'.<span style="color: #800080;">$fd</span>.' close.'<span style="color: #000000;">);                }                            }</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{                </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>('Blocked clinet connection, IP deny : '.<span style="color: #800080;">$info</span>['remote_ip'],'warn'<span style="color: #000000;">);                </span><span style="color: #800080;">$this</span>->server->close(<span style="color: #800080;">$fd</span><span style="color: #000000;">);                </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>('Connection #'.<span style="color: #800080;">$fd</span>.' close.'<span style="color: #000000;">);            }        }</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{            </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>('Blocked clinet connection, too many connections.','warn'<span style="color: #000000;">);            </span><span style="color: #800080;">$this</span>->server->close(<span style="color: #800080;">$fd</span><span style="color: #000000;">);                    }    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onReceive(<span style="color: #800080;">$serv</span>,<span style="color: #800080;">$fd</span>,<span style="color: #800080;">$from_id</span>,<span style="color: #800080;">$recv_data</span><span style="color: #000000;">){        </span><span style="color: #800080;">$info</span> = <span style="color: #800080;">$this</span>->getConnectionInfo(<span style="color: #800080;">$fd</span><span style="color: #000000;">);        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>("[P trim(<span style="color: #800080;">$recv_data</span><span style="color: #000000;">));        </span><span style="color: #008000;">//</span><span style="color: #008000;">禁止使用STARTTLS</span>        <span style="color: #0000ff;">if</span>(<span style="color: #008080;">strtoupper</span>(<span style="color: #008080;">trim</span>(<span style="color: #800080;">$recv_data</span>)) == 'STARTTLS'<span style="color: #000000;">){            </span><span style="color: #800080;">$this</span>->server->send(<span style="color: #800080;">$fd</span>,"502 Not implemented".self::<span style="color: #000000;">EOF);            </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>("[P --> C]\t502 Not implemented"<span style="color: #000000;">);        }</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{                        </span><span style="color: #008000;">//</span><span style="color: #008000;">重置登陆验证                    </span>            <span style="color: #0000ff;">if</span>(<span style="color: #008080;">preg_match</span>('/^AUTH\s+LOGIN(.*)/', <span style="color: #800080;">$recv_data</span>,<span style="color: #800080;">$m</span><span style="color: #000000;">)){                </span><span style="color: #800080;">$m</span>[1] = <span style="color: #008080;">trim</span>(<span style="color: #800080;">$m</span>[1<span style="color: #000000;">]);                </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">empty</span>(<span style="color: #800080;">$m</span>[1<span style="color: #000000;">])){                    </span><span style="color: #008000;">//</span><span style="color: #008000;">只发送AUTH LOGIN 接下来将发送用户名</span>                    <span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>]->user = <span style="color: #800080;">$this</span>-><span style="color: #000000;">smtp_user;                }</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{                    </span><span style="color: #800080;">$recv_data</span> = 'AUTH LOGIN '.<span style="color: #008080;">base64_encode</span>(<span style="color: #800080;">$this</span>->smtp_user).self::<span style="color: #000000;">EOF;                    </span><span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>]->pass = <span style="color: #800080;">$this</span>-><span style="color: #000000;">smtp_pass;                }            }</span><span style="color: #0000ff;">else</span><span style="color: #000000;">{                </span><span style="color: #0000ff;">if</span>(<span style="color: #008080;">preg_match</span>('/^HELO.*|^EHLO.*/', <span style="color: #800080;">$recv_data</span><span style="color: #000000;">)){                    </span><span style="color: #800080;">$recv_data</span> = 'HELO '.<span style="color: #800080;">$this</span>->smtp_host.self::<span style="color: #000000;">EOF;                }                </span><span style="color: #008000;">//</span><span style="color: #008000;">重置密码</span>                <span style="color: #0000ff;">if</span>(!<span style="color: #0000ff;">empty</span>(<span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>]-><span style="color: #000000;">pass)){                    </span><span style="color: #800080;">$recv_data</span> = <span style="color: #008080;">base64_encode</span>(<span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>]->pass).self::<span style="color: #000000;">EOF;                    </span><span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>]->pass = ''<span style="color: #000000;">;                }                </span><span style="color: #008000;">//</span><span style="color: #008000;">重置用户名</span>                <span style="color: #0000ff;">if</span>(!<span style="color: #0000ff;">empty</span>(<span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>]-><span style="color: #000000;">user)){                    </span><span style="color: #800080;">$recv_data</span> = <span style="color: #008080;">base64_encode</span>(<span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>]->user).self::<span style="color: #000000;">EOF;                    </span><span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>]->user = ''<span style="color: #000000;">;                    </span><span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>]->pass = <span style="color: #800080;">$this</span>-><span style="color: #000000;">smtp_pass;                }                                </span><span style="color: #008000;">//</span><span style="color: #008000;">重置mail from</span>                <span style="color: #0000ff;">if</span>(<span style="color: #008080;">preg_match</span>('/^MAIL\s+FROM:.*/', <span style="color: #800080;">$recv_data</span><span style="color: #000000;">)){                    </span><span style="color: #800080;">$recv_data</span> = 'MAIL FROM:$this->smtp_from.'>'.self::<span style="color: #000000;">EOF;                }            }                        </span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>]-><span style="color: #000000;">isConnected()){                </span><span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>]->send(<span style="color: #800080;">$recv_data</span><span style="color: #000000;">);                </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>("[P --> S]\t".<span style="color: #008080;">trim</span>(<span style="color: #800080;">$recv_data</span><span style="color: #000000;">));            }        }        }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onClose(<span style="color: #800080;">$serv</span>,<span style="color: #800080;">$fd</span>,<span style="color: #800080;">$from_id</span><span style="color: #000000;">){        </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span><span style="color: #000000;">])){            </span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>]-><span style="color: #000000;">isConnected()){                </span><span style="color: #800080;">$this</span>->connection[<span style="color: #800080;">$fd</span>]-><span style="color: #000000;">close();                </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>('Connection on SMTP server close.'<span style="color: #000000;">);            }        }        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>('Connection #'.<span style="color: #800080;">$fd</span>.' close. Flush the logs.','debug',<span style="color: #0000ff;">true</span><span style="color: #000000;">);    }        </span><span style="color: #008000;">/*</span><span style="color: #008000;">---------------------------------------------     *      * 服务器连接事件回调     *      ----------------------------------------------</span><span style="color: #008000;">*/</span>        <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onServerConnect(<span style="color: #800080;">$cli</span><span style="color: #000000;">){        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>('Connected to SMTP server.'<span style="color: #000000;">);    }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onServerReceive(<span style="color: #800080;">$cli</span>,<span style="color: #800080;">$data</span><span style="color: #000000;">){        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>("[P trim(<span style="color: #800080;">$data</span><span style="color: #000000;">));                </span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$this</span>->server->send(<span style="color: #800080;">$cli</span>->fd,<span style="color: #800080;">$data</span><span style="color: #000000;">)){            </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>("[P --> C]\t".<span style="color: #008080;">trim</span>(<span style="color: #800080;">$data</span><span style="color: #000000;">));        }            }        </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onServerError(<span style="color: #800080;">$cli</span><span style="color: #000000;">){        </span><span style="color: #800080;">$this</span>->server->close(<span style="color: #800080;">$cli</span>-><span style="color: #000000;">fd);        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>('Connection on SMTP server error: '.<span style="color: #800080;">$cli</span>->errCode.' '.socket_strerror(<span style="color: #800080;">$cli</span>->errCode),'warn'<span style="color: #000000;">);            }            </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> onServerClose(<span style="color: #800080;">$cli</span><span style="color: #000000;">){        </span><span style="color: #800080;">$this</span>-><span style="color: #008080;">log</span>('Connection on SMTP server close.'<span style="color: #000000;">);                </span><span style="color: #800080;">$this</span>->server->close(<span style="color: #800080;">$cli</span>-><span style="color: #000000;">fd);            }        </span><span style="color: #008000;">/*</span><span style="color: #008000;">*     * IP地址过滤     * @param unknown $ip     * @return boolean     </span><span style="color: #008000;">*/</span>    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> isIpAllow(<span style="color: #800080;">$ip</span><span style="color: #000000;">){        </span><span style="color: #800080;">$pass</span> = <span style="color: #0000ff;">false</span><span style="color: #000000;">;        </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$this</span>->setting['ip']['allow'<span style="color: #000000;">])){            </span><span style="color: #0000ff;">foreach</span> (<span style="color: #800080;">$this</span>->setting['ip']['allow'] <span style="color: #0000ff;">as</span> <span style="color: #800080;">$addr</span><span style="color: #000000;">){                </span><span style="color: #800080;">$pattern</span> = '/'.<span style="color: #008080;">str_replace</span>('*','\d+',<span style="color: #008080;">str_replace</span>('.', '\.', <span style="color: #800080;">$addr</span>)).'/'<span style="color: #000000;">;                </span><span style="color: #0000ff;">if</span>(<span style="color: #008080;">preg_match</span>(<span style="color: #800080;">$pattern</span>, <span style="color: #800080;">$ip</span>) && !<span style="color: #0000ff;">empty</span>(<span style="color: #800080;">$addr</span><span style="color: #000000;">)){                    </span><span style="color: #800080;">$pass</span> = <span style="color: #0000ff;">true</span><span style="color: #000000;">;                    </span><span style="color: #0000ff;">break</span><span style="color: #000000;">;                }            }        }                </span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$pass</span><span style="color: #000000;">){            </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$this</span>->setting['ip']['deny'<span style="color: #000000;">])){                </span><span style="color: #0000ff;">foreach</span> (<span style="color: #800080;">$this</span>->setting['ip']['deny'] <span style="color: #0000ff;">as</span> <span style="color: #800080;">$addr</span><span style="color: #000000;">){                    </span><span style="color: #800080;">$pattern</span> = '/'.<span style="color: #008080;">str_replace</span>('*','\d+',<span style="color: #008080;">str_replace</span>('.', '\.', <span style="color: #800080;">$addr</span>)).'/'<span style="color: #000000;">;                    </span><span style="color: #0000ff;">if</span>(<span style="color: #008080;">preg_match</span>(<span style="color: #800080;">$pattern</span>, <span style="color: #800080;">$ip</span>) && !<span style="color: #0000ff;">empty</span>(<span style="color: #800080;">$addr</span><span style="color: #000000;">)){                        </span><span style="color: #800080;">$pass</span> = <span style="color: #0000ff;">false</span><span style="color: #000000;">;                        </span><span style="color: #0000ff;">break</span><span style="color: #000000;">;                    }                }            }        }        </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$pass</span><span style="color: #000000;">;    }    }</span><span style="color: #0000ff;">class</span> Client <span style="color: #0000ff;">extends</span><span style="color: #000000;"> swoole_client{    </span><span style="color: #008000;">/*</span><span style="color: #008000;">*     * 记录当前连接     * @var unknown     </span><span style="color: #008000;">*/</span>    <span style="color: #0000ff;">public</span> <span style="color: #800080;">$fd</span><span style="color: #000000;"> ;        </span><span style="color: #0000ff;">public</span> <span style="color: #800080;">$user</span> = ''<span style="color: #000000;">;        </span><span style="color: #008000;">/*</span><span style="color: #008000;">*     * smtp登陆密码     * @var unknown     </span><span style="color: #008000;">*/</span>    <span style="color: #0000ff;">public</span> <span style="color: #800080;">$pass</span> = ''<span style="color: #000000;">;}</span>

 

 

  配置文件例子:

 

  

<span style="color: #008000;">/*</span><span style="color: #008000;">* *  运行配置</span><span style="color: #008000;">*/</span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">array</span><span style="color: #000000;">(        </span>'worker_num' => 12,        'log_file' => BASE_PATH.'/logs/proxyserver.log',        'pid_file' => BASE_PATH.'/logs/proxyserver.pid',        'heartbeat_idle_time' => 300,        'heartbeat_check_interval' => 60,        'max_connection' => 50,   <br>     //配置真实的smtp信息         'smtp_host' => '',        'smtp_port' => 25,        'smtp_user' => '',        'smtp_pass' => '',        'smtp_from' => '',        'ip' => <span style="color: #0000ff;">array</span><span style="color: #000000;">(            </span>'allow' => <span style="color: #0000ff;">array</span>('192.168.0.*'),            'deny' => <span style="color: #0000ff;">array</span>('192.168.10.*','192.168.100.*'),<span style="color: #000000;">        ));</span>

  运行例子:

  

defined('BASE_PATH') or define('BASE_PATH', __DIR__);defined('DEBUG_ON') or define('DEBUG_ON', true);//服务器配置require BASE_PATH.'/CSmtpProxy.php';$settings = require BASE_PATH.'/conf/config.php';CSmtpProxy::setPidFile($settings['pid_file']);CSmtpProxy::start(function(){	global $settings;	$serv = new CSmtpProxy('0.0.0.0', 25);	$serv->daemonize();	$serv->run($settings);});

  应用配置:

  smtp host: 192.168.0.*  //指定smtpproxy 运行的服务器IP。

     port: 25

     user: xxxx  //随意填写

     pass:  xxxx  //随意填写

     from: [email protected] // 根据情况填写

 

——————————————————————————————————————————————————————

 

  存在的问题:

    1、不支持ssl模式;

    2、应用的from还是要填写正确,否则发出的邮件发件人会显示错误。

 

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn