1、实现SMTP协议的类dsmtp.cls.php:
// 通过socket实现SMTP协议的功能
// version: 1.1
// author : DCC
// create : 2014-01-17 23:38:24
// modify : 2014-01-18 16:59:04
// more : http://www.thinkful.cn/archives/389.html
class Dmail_smtp{
var $socket;
var $host;
var $user;
var $pwd;
var $port;
var $nickname;
var $weburl;
// 初始化
function__construct($host, $user, $pwd, $port= 25, $webname= ' 大超超在思考 ', $weburl= " www.thinkful.cn "){
$ this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$ this->host = $host;
$ this->user = $user;
$ this->pwd = $pwd;
$ this->port = $port;
$ this->nickname = $webname;
$ this->weburl = $weburl;
}
// 发邮件
function smtp($to, $ from, $subject, $body){
$conn = socket_connect($ this->socket, $ this->host, $ this->port);
if( $conn ){
// 接收连接成功的消息
$msg = " succeed connect to ".$ this->host. " : ".$ this->port. " \n ";
$msg .= $ this->_r();
// 开始认证过程
$ this->_w( " HELO ".$ this->weburl. " \r\n ");
$msg .= $ this->_r();
$ this->_w( " AUTH LOGIN ".base64_encode($ this->user). " \r\n ");
$msg .= $ this->_r();
$ this->_w(base64_encode($ this->pwd). " \r\n ");
$msg .= $ this->_r();
// 认证成功
if( stripos($msg, ' 235 Authentication successful ')!==FALSE ){
$ this->_w( " MAIL FROM:<{$from}>\r\n ");
$msg .= $ this->_r();
$ this->_w( " RCPT TO:<{$to}>\r\n ");
$msg .= $ this->_r();
$ this->_w( " DATA\r\n ");
$msg .= $ this->_r();
// 发送头和正文
$data = $ this->_genHeader($to, $ from, $subject)
. " \r\n ".$ this->_genBody($body);
$ this->_w($data);
$ this->_w( " \r\n.\r\n ");
$msg .= $ this->_r();
$ this->_w( " QUIT\r\n ");
$msg .= $ this->_r();
}
}
return $msg;
}
// 生成头部
private function _genHeader($to, $ from, $subject){
$header = " MIME-Version:1.0\r\n ";
$header .= " Content-Type: text/plain; charset=\"utf-8\"\r\n ";
$header .= " Subject: =?utf-8?B? ".base64_encode($subject). " ?=\r\n ";
$header .= " From: ".$ this->nickname. " < ".$ from. " >\r\n ";
$header .= " To: ".$to. " \r\n ";
$header .= " Date: ".date( " r "). " \r\n ";
list($msec, $sec) = explode( " ", microtime());
$header .= " Message-ID: <DCC_ ".date( " YmdHis "). " . ".($msec* 1000000). " . ".$ from. " >\r\n ";
return $header;
}
// 生成正文
private function _genBody($body){
$body = preg_replace( " /(^|(\r\n))(\.)/ ", " \1.\3 ", $body);
return $body;
}
// @发送控制流
// var: 控制代码
private function _w($s){
socket_write($ this->socket, $s);
}
// @读取返回的数据
private function _r(){
return socket_read($ this->socket, 1024);
}
}
2、实现POP3协议的类dpop3.cls.php:
<?php
// 通过socket实现pop3协议的功能
// version: 1.2
// author : DCC
// create : 2014-01-18 11:26:53
// modify : 2014-01-18 22:57:26
// more : http://www.thinkful.cn/archives/389.html
class Dmail_pop3{
var $socket;
var $host;
var $user;
var $pwd;
var $port;
var $content;
// 初始化
function __construct($host, $user, $pwd, $port= 110){
$ this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$ this->host = $host;
$ this->user = $user;
$ this->pwd = $pwd;
$ this->port = $port;
}
// 收邮件
function pop3(){
$conn = socket_connect($ this->socket, $ this->host, $ this->port);
if( $conn ){
// 接收连接成功的消息
$msg = " DCC: succeed connect to ".$ this->host. " : ".$ this->port. " \n ";
$msg .= $ this->_r();
// 开始认证过程
$ this->_w( " USER ".$ this->user. " \r\n ");
$msg .= $ this->_r();
$ this->_w( " PASS ".$ this->pwd. " \r\n ");
$msg .= $ this->_r();
// 认证成功
if( substr_count($msg, ' +OK ')>= 3 ){
// 向服务器发送请求邮箱信息
$ this->_w( " STAT\r\n ");
$mail_info = $ this->_r();
$msg .= $mail_info;
preg_match( ' /\+OK\s(\d+)\s(\d+)/ ', $mail_info, $m);
$mail_num = $m[ 1];
$mail_len = $m[ 2];
// 向服务器发送邮件i信息的请求
$ this->content = '';
for( $i= 1; $i<=$mail_num; $i++ ){
// 查看该邮件的信息
$ this->_w( " LIST {$i}\r\n ");
usleep( 160000); // waiting 0.16s
$mail_info = $ this->_r();
$msg .= $mail_info;
preg_match( ' /\+OK\s(\d+)\s(\d+)/ ', $mail_info, $m);
// 接收服务器返回的信息
$ this->_w( " RETR {$i}\r\n ");
$msg.= ' DCC: reading mail(id= '.$m[ 1]. ' )\'s content(length= '.$m[ 2]. ' byte): '. " \n ";
$data = '';
while( strlen($data)<$m[ 2] ){
$msg .= ' . ';
$data .= socket_read($ this->socket, 4096);
}
$ this->content .= $data;
$msg.= " \nDCC: mail(id= ".$m[ 1]. ' )\'s content(length= '.$m[ 2]. ' byte) read complete. '. " \n ";
}
}
}
return $msg;
}
// 返回收取邮件内容
function getContent(){
return $ this->content;
}
// @发送控制流
// var: 控制代码
private function _w($s){
socket_write($ this->socket, $s);
}
// @读取返回的数据
// var: 数据长度
private function _r($len= 1024){
return socket_read($ this->socket, $len);
}
}
3、界面——代码就不贴出来了,看基本调用方法:
// 调用SMTP时
require_once ' dsmtp.cls.php ';
$host = " smtp.qq.com ";
// 使用QQ邮箱和密码
$user = ' *******@qq.com ';
$pwd = ' ******* ';
$dmail = new Dmail_smtp($host, $user, $pwd);
$msg = $dmail->smtp($to, $ from, $subject, $body);
// ********************************
// ********************************
// 调用POP3时(后续处理复杂一点)
require_once ' dpop3.cls.php ';
$host = " pop.qq.com ";
$dmail = new Dmail_pop3($host, $user, $pwd);
$msg = $dmail->pop3();
$ret = $msg;
if( strpos($msg, ' read complete ')!==FALSE ){
$ct = $dmail->getContent();
$mail_list_arr = explode( ' X-QQ-SSF: ', $ct);
array_shift($mail_list_arr); // 去除第一个
$mail_list_arr = array_reverse($mail_list_arr);
foreach( $mail_list_arr as $v ){
// 中文标题的处理
if( preg_match( ' /Subject: =\?([^?]+)\?B\?([^?]+)\?=/i ', $v, $subject) ){
$tmp_s = base64_decode($subject[ 2]);
$tmp_s = $subject[ 1]== ' gbk '||$subject[ 1]== ' gb2312 '? iconv( ' gbk ', ' utf-8 ', $tmp_s) : $tmp_s;
}
// 英文标题
else if( preg_match( ' /Subject: (.*?)\r\n/i ', $v, $subject) ){
$tmp_s = $subject[ 1];
}
else{
$tmp_s = ' 邮件标题 ';
}
preg_match( ' /From: [^<]+<(.*?)>/i ', $v, $ from);
preg_match( ' /Date: (.*?)\r\n/i ', $v, $date);
$mail_list .= $tmp_s. ' |#DCC_LIST_INNER#| '
.$ from[ 1]. ' |#DCC_LIST_INNER#| '
.$date[ 1]. ' |#DCC_MAIL_LIST_SEP#| ';
}
$ret .= ' |#DCC_POP3_DATA_SEP#| '.$mail_list;
}
echo $ret;
die();