首页 > 作文

[PHP] PHP调用IMAP协议读取邮件类库

更新时间:2023-04-07 16:27:50 阅读: 评论:0

socket.php 为连接socket的类库

imap.php 基于socket的imap协议封装

test.php 进行测试

require_once 'socket.php';require_once 'imap.php';$imap=new sina_mail_net_imap("imap.sina.net:143",30,30);$imap->capability();$imap->id(array(    'name'          => 'sinamail othermail client',    'version'       => '1',    'os'            => 'sinamail othermail',    'os-version'    => '1.0',));$imap->login("xxxx@xxxxx","xxxx");$folders=$imap->getlist('', '*');var_dump($folders);$status = $imap->lect('nt');var_dump($status);$ls = $imap->fetch(array(), array('uid', 'internaldate', 'rfc822.size'));foreach($ls as $k=>$i){    $info=$imap->fetch(array($k), array('rfc822'));}

imap.php

<?phpclass sina_mail_net_imap {const max_read_size = 100000000;const pattern_request_string_quence   = '/{\d+}/';const pattern_respon_string_quence  = '/{(\d+)}$/';const quence_param_name   = '[]';const partial_param_name    = '<>';const param_no          = 1;const param_single      = 2;const param_pair        = 4;const param_list        = 8;const param_string      = 16;const param_number      = 32;const param_date        = 64;const param_画画大全图片flag        = 128;const param_quence    = 256;const param_arch      = 512;const param_body        = 1024;const param_partial     = 2048;const param_exclusive   = 4096;private static $statuskeywords = array('messages'      => lf::param_no,'recent'        => lf::param_no,'uidnext'       => lf::param_no,'uidvalidity'   => lf::param_no,'unen'        => lf::param_no,);private static $archkeywords = array('all'           => lf::param_no,'answered'      => lf::param_no,'bcc'           => 18, // lf::param_single | lf::param_string,'before'        => 66, // lf::param_single | lf::param_date,'body'          => 18, // lf::param_single | lf::param_string,'cc'            => 18, // lf::param_single | lf::param_string,'deleted'       => lf::param_no,'draft'         => lf::param_no,'flagged'       => lf::param_no,'from'          => 18, // lf::param_single | lf::param_string,'header'        => 20, // lf::param_pair | lf::param_string,'keyword'       => 130, // lf::param_single | lf::param_flag,'larger'        => 34, // lf::param_single | lf::param_number,'new'           => lf::param_no,'not'           => 514, // lf::param_single | lf::param_arch,'old'           => lf::param_no,'on'            => 66, // lf::param_single | lf::param_date,'or'            => 516, // lf::param_pair | lf::param_arch,'recent'        => lf::param_no,'en'          => lf::param_no,'ntbefore'    => 66, // lf::param_single | lf::param_date,'nton'        => 66, // lf::param_single | lf::param_date,'ntsince'     => 66, // lf::param_single | lf::param_date,'since'         => 66, // lf::param_single | lf::param_date,'smaller'       => 34, // lf::param_single | lf::param_number,'subject'       => 18, // lf::param_single | lf::param_string,'text'          => 18, // lf::param_single | lf::param_string,'to'            => 18, // lf::param_single | lf::param_string,'uid'           => 258, // lf::param_single | lf::pa感谢朋友的话ram_quence,'unanswered'    => lf::param_no,'undeleted'     => lf::param_no,'undraft'       => lf::param_no,'unflagged'     => lf::param_no,'unkeyword'     => 130, // lf::param_single | lf::param_flag,'unen'        => lf::param_no,);private static $fetchkeywords = array('all'           => 4097, // lf::param_no | lf::param_exclusive,'fast'          => 4097, // lf::param_no | lf::param_exclusive,'full'          => 4097, // lf::param_no | lf::param_exclusive,'body'          => 3075, // lf::param_no | lf::param_single | lf::param_body | lf::param_partial,'body.peek'     => 3074, // lf::param_single | lf::param_body | lf::param_partial,'bodystructure' => lf::param_no,'envelope'      => lf::param_no,'flags'         => lf::param_no,'internaldate'  => lf::param_no,'rfc822'        => lf::param_no,'rfc822.header' => lf::param_no,'rfc822.size'   => lf::param_no,'rfc822.text'   => lf::param_no,'uid'           => lf::param_no,);private $sock = null;private $timeout = 120;private $ts = 0;private $tagname = 'a';private $tagid = 0;private $capabilities = array();private $folders = array();private $currentfolder = null;private $currentcommand = null;private $lastnd = '';private $lastrecv = '';public function __construct($uri, $timeout = null, $conntimeout = null) {$this->sock = new socket($uri, $timeout);        //        $t = intval($timeout);//        if ($t > 0) {//            $this->timeout = $t;//        }$this->connect($conntimeout);        }public function __destruct() {}public function connect($timeout) {        $this->sock->connect($timeout);        $this->getrespon();}public function capability() {$res = $this->request('capability');if (ist($res[0][0]) && $res[0][0] == '*' &&ist($res[0][1]) && strcacmp($res[0][1], 'capability') == 0) {for ($i = 2, $n = count($res[0]); $i < $n; ++$i) {$this->capabilities[strtoupper($res[0][$i])] = true;}}        }public function id($data) {if (ist($this->capabilities['id'])) {            $this->request('id', array($data));            }        }public function login($urname, $password) {try {$this->request('login', array($urname, $password));} catch (exception $ex) {throw new exception($ex->getmessage(), $ex->getcode());}}public function logout() {$this->request('logout');        }public function getlist($reference = '', $wildcard = '') {$res = $this->request('list', array($reference, $wildcard));foreach ($res as &$r) {if (ist($r[0]) && $r[0] == '*' && ist($r[1]) && strcacmp($r[1], 'list') == 0 && ist($r[4])) {$this->folders[$r[4]] = array('id'    => $r[4],'name'  => mb_convert_encoding($r[4], 'utf-8', 'utf7-imap'),'path'  => $r[3],'attr'  => $r[2],);}}return $this->folders;}public function status($folder, $data) {$args = $this->formatargsforcommand($data, lf::$statuskeywords);$res = $this->request('status', array($folder, $args));$status = array();if (!empty($res)) {            foreach ($res as &$r) {if (ist($r[0]) && $r[0] == '*' && ist($r[1]) && strcacmp($r[1], 'status') == 0 && ist($r[3]) && is_array($r[3])) {for ($i = 0, $n = count($r[3]); $i < $n; $i += 2) {$status[$r[3][$i]] = $r[3][$i + 1];}}}}return $status;}public function lect($folder) {$res = $this->request('lect', array($folder));$status = array();if (!empty($res)) {foreach ($res as $r) {if (ist($r[0]) && $r[0] == '*') {if (ist($r[1]) && ist($r[2])) {if (strcacmp($r[1], 'ok') == 0 && is_array($r[2])) {for ($i = 0, $n = count($i); $i < $n; $i += 2) {$status[$r[2][$i]] = $r[2][$i + 1];}} elif (ctype_digit($r[1])) {$status[$r[2]] = $r[1];} el {$status[$r[1]] = $r[2];}    }}}}$this->currentfolder = $folder;return $status;}public function arch($data) {     $args = $this->formatargsforcommand($data, lf::$archkeywords, true);                $res = $this->request('arch', $args);$ls = array();foreach ($res as &$r) {if (ist($r[0]) && $r[0] == '*' && ist($r[1]) && strcacmp($r[1], 'arch') == 0) {for ($i = 2, $n = count($r); $i < $n; ++$i) {$ls[] = $r[$i];}}}return $ls;}public function fetch($q, $data) {                        $qstr = $this->formatquence($q);        $args = $this->formatargsforcommand($data, lf::$fetchkeywords);                                $res = $this->request('fetch', array($qstr, $args));//        var_dump($res);$ls = array();foreach ($res as &$r) {if (ist($r[0]) && $r[0] == '*' &&ist($r[1]) && is_numeric($r[1]) && ist($r[2]) && strcacmp($r[2], 'fetch') == 0 &&ist($r[3]) && is_array($r[3])) {$a = array();for ($i = 0, $n = count($r[3]); $i < $n; $i += 2) {$key = $r[3][$i];if (((strcacmp($key, 'body') == 0 && ist($args['body']) && is_array($args['body'])) || (strcacmp($key, 'body.peek') == 0 && ist($args['body.peek']) && is_array($args['body.peek']))) && is_array($r[3][$i + 1])) {$key = trim($this->formatrequestarray(array($key => $r[3][$i + 1]), $placeholder, 0), '()');$i++;} el {$key = $r[3][$i];}$a[$key] = $r[3][$i + 1];}if (!empty($a)) {$ls[$r[1]] = $a;}}}return $ls;}private function nexttag() {$this->tagid++;return sprintf('%s%d', $this->tagname, $this->tagid);}private function request($cmd, $args = array()) {                $this->currentcommand = strtoupper(trim($cmd));$tag = $this->nexttag();$req = $tag . ' ' . $this->currentcommand;// 格式化参数列表$strqlist = array();if (is_array($args)) {$argstr = $this->formatrequestarray($args, $strqlist);                } el {                $argstr = $this->formatrequeststring($args, $strqlist);}//$argstr = $this->makerequest($args, $strqlist);$subreqs = array();if (ist($argstr[0])) {$req .= ' ' . $argstr;// 如果参数中包括需要序列化的数据,根据序列化标识{length}将命令拆分成多条if (!empty($strqlist) && preg_match_all(lf::pattern_request_string_quence, $req, $matches, preg_offt_capture)) {$p = 0;foreach ($matches[0] as $m) {$e = $m[1] + strlen($m[0]);$subreqs[] = substr($req, $p, $e - $p);                    $p = $e;}$subreqs[] = substr($req, $p);// 校验序列化标识与需要序列化的参数列表数量是否一致if (count($subreqs) != count($strqlist) + 1) {$subreqs = null;}}}if (empty($subreqs)) {// 处理单条命令$this->sock->writeline($req);$this->lastnd = $req;        $res = $this->getrespon($tag);} el {            // 处理多条命令$this->lastnd = '';foreach ($subreqs as $id => $req) {$this->sock->writeline($req);                          $this->lastnd .= $req;$res = $this->getrespon($tag);                if (ist($res[0][0]) && $res[0][0] == '+') {$this->sock->write($strqlist[$id]);                $this->lastnd .= "\r\n" . $strqlist[$id];} el {// 如果服务器端返回其他相应,则定制后续执行break;}}                }return $res;}private function formatrequeststring($s, &$strqlist) {$s = trim($s);$needquote = fal;if (!ist($s[0])) {$needquote = true;} elif ($this->currentcommand == 'id') {    $needquote = true;} el {// 参数包含多行时,需要进行序列化if (strpos($s, "\r") !== fal || strpos($s, "\n") !== fal) {                $strqlist[] = $s;$s = sprintf('{%d}', strlen($s));} el {// 参数包含双引号或空格时,需要将使用双引号括起来if (strpos($s, '"') !== fal) {$s = addcslashes($s, '"');$needquote = true;}if (strpos($s, ' ') !== fal) {$needquote = true;}}}if ($needquote) {return sprintf('"%s"', $s);} el {return $s;}}private function formatrequestarray($arr, &$strqlist, $level = -1) {$a = array();foreach ($arr as $k => $v) {$isbody = fal;$supportpartial = fal;$partialstr = '';if ($this->currentcommand == 'fetch') {// 识别是否body命令,是否可以包含<partial>$kw = strtoupper($k);            if (ist(lf::$fetchkeywords[$kw]) && (lf::$fetchkeywords[$kw] & lf::param_body) > 0) {$isbody = true;}if (ist(lf::$fetchkeywords[$kw]) && (lf::$fetchkeywords[$kw] & lf::param_partial) > 0) {$supportpartial = true;}}                        if (is_array($v)) {                        if ($supportpartial && ist($v[lf::partial_param_name]) && is_array($v[lf::partial_param_name])) {                    // 处理包含<partial>的命令foreach ($v[lf::partial_param_name] as $spos => $mlen) {$partialstr =  sprintf('<%d.%d>', $spos, $mlen);}                    unt($v[lf::partial_param_name]);}$s = $this->formatrequestarray($v, $strqlist, $level + 1);} el {$s = $this->formatrequeststring($v, $strqlist);}            if (!is_numeric($k)) {// 字典方式需要包含键名$k = $this->formatrequeststring($k, $strqlist);if ($isbody) {$s = $k . $s;                    } el {$s = $k . ' ' . $s;}// 包含<partial>if ($supportpartial) {$s .= $partialstr;}}$a[] = $s;}if ($level < 0) {return implode(' ', $a);} elif (($level % 2) == 0) {return sprintf('(%s)', implode(' ', $a));} el {return sprintf('[%s]', implode(' ', $a));}}private function formatquence($q) {$n = count($q);if ($n == 0) {return '1:*';            } elif ($n == 1) {if (ist($q[0])) {return strval($q[0]);} el {foreach ($q as $k => $v) {return $k . ':'goodbay . $v;}}} el {return implode(',', $q);}}private function formatargsforcommand(&$data, &$fields, $aslist = fal) {$args = array();foreach ($data as $k => $v) {            if (is_numeric($k)) {// 无值参数$name = strtoupper($v);if (ist($fields[$name])) {// 对于排他性属性,直接返回if (($fields[$name] & lf::param_exclusive) > 0) {return $name;} elif (($fields[$name] & lf::param_no) > 0) {                $args[] = $name;}}} elif ($k == lf::quence_param_name) {// 序列$args[] = $this->formatquence($v);                } el {$name = strtoupper($k);if (ist($fields[$name])) {$paramtype = $fields[$name];                    // 格式化参数类型if (($paramtype & lf::param_date) > 0) {$v = date('j-m-y', $v);} elif (($paramtype & lf::param_quence) > 0) {$v = $this->formatquence($v);}                        // 根据参数定义拼组参数列表if (($paramtype & lf::param_single) > 0) {// 单值参数if ($aslist) {$args[] = $name;$args[] = $v;} el {$args[$name] = $v;}} elif (($paramtype & lf::param_pair) > 0) {// 键值对参数if (is_array($v)) {foreach ($v as $x => $y) {$pk = $x;$pv = $y;break;}} el {$pk = $v;$pv = '';}if ($aslist) {$args[] = $name;$args[] = $pk;$args[] = $pv;} el {$args[$name] = array($pk => $pv);}} elif (($paramtype & lf::param_list) > 0) {// 列表参数if ($aslist) {$args[] = $name;foreach ($v as $i) {$args[] = $i;}} el {$args[$name] = $v;}} elif (($paramtype & lf::param_no) > 0) {// 无值参数$args[] = $name;}}}}return $args;}private function getrespon($tag = null) {$r = array();$readmore = true;  while ($readmore) {$ln = trim($this->sock->readline());            if (!ist($ln[0])) {// connection clod or read empty string, throw exception to avoid dead loop and reconnectthrow new exception('read respon failed');}$matches = null;$strqkey = null;$strq = null;if (preg_match(lf::pattern_respon_string_quence, $ln, $matches)) {$strqkey = $matches[0];$this->readquence($ln, $strq, $matches[1]);}$this->lastrecv = $ln;// 区分处理不同种响应switch ($ln[0]) {ca '*':$r[] = $this->parline($ln, $strqkey, $strq);                                        if (!$tag) {$readmore = fal;}break;ca $this->tagname:$r[] = $this->parline($ln);if ($tag) {$readmore = fal;} el {}break;ca '+':$r[] = $this->parline($ln);$readmore = fal;break;default:$r[] = $ln;break;}                        }        //var_dump($this->lastnd, $this->lastrecv);// 无响应数据if (empty($r)) {throw new exception('no respon');}$last = $r[count($r) - 1];if (ist($last[0]) && $last[0] == '+') {// 继续发送请求数据} el {if ($tag) {if (!ist($last[0]) || strcacmp($last[0], $tag) != 0) {                    throw new exception('tag no match');}           } el {if (!ist($last[0]) || strcacmp($last[0], '*') != 0) {                    throw new exception('untag no match');}}if记叙文阅读 (ist($last[1])) {// 处理响应出错的情况if (strcacmp($last[1], 'bad') == 0) {        throw new exception(implode(' ', $last));} elif (strcacmp($last[1], 'no') == 0) {throw new exception(implode(' ', $last));}}//$this->currentcommand = null;}return $r;}private function readquence(&$ln, &$strq, $qlength) {// 对于字符串序列,读取完整内容后再拼接响应        $readlen = 0;$st = microtime(true);// 网络请求多次读取字符串序列内容,直到读好为止while ($readlen < $qlength) {$sb = $this->sock->read($qlength - $readlen);if (ist($sb[0])) {$strq .= $sb;$readlen = strlen($strq);}                    if ((microtime(true) - $st) > $this->timeout) {throw new exception('read quence timeout');}}// 读取字符串序列后的剩余命令$leftln = rtrim($this->sock->readline());$ln = $ln . $leftln;}private function parline($ln, $strqkey = null, $strq = null) {$r = array();$p =& $r;$stack = array();$token = '';$escape = fal;$inquote = fal;for ($i = 0, $n = strlen($ln); $i < $n; ++$i) {$ch = $ln[$i];if ($ch == '"') {// 处理双引号括起的字符串if (!$inquote) {$inquote = true;} el {$inquote = fal;}} elif ($inquote) {// 对于括起的字符串,处理双引号转义if ($ch == '\\') {if (!$escape && ist($ln[$i + 1]) && $ln[$i + 1] == '"') {               $token .= '"';$i++;} el {$token .= $ch;$escape = !$escape;}                    } el {$token .= $ch;}} elif ($ch == ' ' || $ch == '(' || $ch == ')' || $ch == '[' || $ch == ']') {// 处理子列表if (ist($token[0])) {// 将字符串序列标识:{length},替换为真实字符串if ($strqkey && $token == $strqkey) {$p[] = $strq;} el {$p[] = $token;}$token = '';}                if ($ch == '(' || $ch == '[') {                    $p[] = array();$stack[] =& $p;$p =& $p[count($p) - 1];                                        } elif ($ch == ')' || $ch == ']') {        $p =& $stack[count($stack) - 青春永不言败1];array_pop($stack);}} el {                // 处理字符串字面量$token .= $ch;}            }if (ist($token[0])) {// 将字符串序列标识:{length},替换为真实字符串if ($strqkey && $token == $strqkey) {$p[] = $strq;} el {$p[] = $token;}}return $r;}}// end of php

socket.php

<?phpclass socket{const default_read_size = 8192;const crtl = "\r\n";private $uri = null;private $timeout = null;private $sock = null;private $connected = fal;public function __construct($uri, $timeout = null){$this->uri = $uri;$this->timeout = $this->formattimeout($timeout);}public function connect($timeout = null, $retrytimes = null){if ($this->connected) {$this->clo();}$conntimeout = $this->formattimeout($timeout, $this->timeout);$retrytimes = intval($retrytimes);if ($retrytimes < 1) {$retrytimes = 1;}for ($i = 0; $i < $retrytimes; ++$i) {$this->sock = stream_socket_client($this->uri, $errno, $error, $conntimeout);if ($this->sock) {break;}}if (!$this->sock) {}stream_t_timeout($this->sock, $this->timeout);$this->connected = true;}public function read($size){asrt($this->connected);$buf = fread($this->sock, $size);if ($buf === fal) {$this->handlereaderror();}return $buf;}public function readline(){asrt($this->connected);$buf = '';while (true) {$s = fgets($this->sock, lf::default_read_size);if ($s === fal) {$this->checkreadtimeout();break;}$n = strlen($s);if (!$n) {break;}$buf .= $s;if ($s[$n - 1] == "\n") {break;}}return $buf;}public function readall(){asrt($this->connected);$buf = '';while (true) {$s = fread($this->sock, lf::default_read_size);if ($s === fal) {$this->handlereaderror();}if (!ist($s[0])) {break;}$buf .= $s;}return $buf;}public function write($s){asrt($this->connected);$n = strlen($s);$w = 0;while ($w < $n) {$buf = substr($s, $w, lf::default_read_size);$r = fwrite($this->sock, $buf);if (!$r) {$this->clo();}$w += $r;}}public function writeline($s){$this->write($s . lf::crtl);}public function clo() {if ($this->connected) {fclo($this->sock);$this->connected = fal;}}private function formattimeout($timeout, $default = null){$t = intval($timeout);if ($t <= 0) {if (!$default) {$t = ini_get('default_socket_timeout');} el {$t = $default;}}return $t;}private function checkreadtimeout(){$meta = stream_get_meta_data($this->sock);if (ist($meta['timed_out'])) {$this->clo();}}private function handlereaderror(){$this->checkreadtimeout();$this->clo();}}

本文发布于:2023-04-07 16:27:48,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/921b48b522e2f5b38dc67badad84e47e.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:[PHP] PHP调用IMAP协议读取邮件类库.doc

本文 PDF 下载地址:[PHP] PHP调用IMAP协议读取邮件类库.pdf

标签:字符串   参数   序列   命令
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图