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->select('SENT');
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

<?php
class Sina_Mail_Net_Imap {
const MAX_READ_SIZE = 100000000;
const PATTERN_REQUEST_STRING_SEQUENCE = '/{\d+}/';
const PATTERN_RESPONSE_STRING_SEQUENCE = '/{(\d+)}$/';
const SEQUENCE_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_SEQUENCE = 256;
const PARAM_SEARCH = 512;
const PARAM_BODY = 1024;
const PARAM_PARTIAL = 2048;
const PARAM_EXCLUSIVE = 4096;
private static $statusKeywords = array(
'MESSAGES' => self::PARAM_NO,
'RECENT' => self::PARAM_NO,
'UIDNEXT' => self::PARAM_NO,
'UIDVALIDITY' => self::PARAM_NO,
'UNSEEN' => self::PARAM_NO,
);
private static $searchKeywords = array(
'ALL' => self::PARAM_NO,
'ANSWERED' => self::PARAM_NO,
'BCC' => 18, // self::PARAM_SINGLE | self::PARAM_STRING,
'BEFORE' => 66, // self::PARAM_SINGLE | self::PARAM_DATE,
'BODY' => 18, // self::PARAM_SINGLE | self::PARAM_STRING,
'CC' => 18, // self::PARAM_SINGLE | self::PARAM_STRING,
'DELETED' => self::PARAM_NO,
'DRAFT' => self::PARAM_NO,
'FLAGGED' => self::PARAM_NO,
'FROM' => 18, // self::PARAM_SINGLE | self::PARAM_STRING,
'HEADER' => 20, // self::PARAM_PAIR | self::PARAM_STRING,
'KEYWORD' => 130, // self::PARAM_SINGLE | self::PARAM_FLAG,
'LARGER' => 34, // self::PARAM_SINGLE | self::PARAM_NUMBER,
'NEW' => self::PARAM_NO,
'NOT' => 514, // self::PARAM_SINGLE | self::PARAM_SEARCH,
'OLD' => self::PARAM_NO,
'ON' => 66, // self::PARAM_SINGLE | self::PARAM_DATE,
'OR' => 516, // self::PARAM_PAIR | self::PARAM_SEARCH,
'RECENT' => self::PARAM_NO,
'SEEN' => self::PARAM_NO,
'SENTBEFORE' => 66, // self::PARAM_SINGLE | self::PARAM_DATE,
'SENTON' => 66, // self::PARAM_SINGLE | self::PARAM_DATE,
'SENTSINCE' => 66, // self::PARAM_SINGLE | self::PARAM_DATE,
'SINCE' => 66, // self::PARAM_SINGLE | self::PARAM_DATE,
'SMALLER' => 34, // self::PARAM_SINGLE | self::PARAM_NUMBER,
'SUBJECT' => 18, // self::PARAM_SINGLE | self::PARAM_STRING,
'TEXT' => 18, // self::PARAM_SINGLE | self::PARAM_STRING,
'TO' => 18, // self::PARAM_SINGLE | self::PARAM_STRING,
'UID' => 258, // self::PARAM_SINGLE | self::PARAM_SEQUENCE,
'UNANSWERED' => self::PARAM_NO,
'UNDELETED' => self::PARAM_NO,
'UNDRAFT' => self::PARAM_NO,
'UNFLAGGED' => self::PARAM_NO,
'UNKEYWORD' => 130, // self::PARAM_SINGLE | self::PARAM_FLAG,
'UNSEEN' => self::PARAM_NO,
);
private static $fetchKeywords = array(
'ALL' => 4097, // self::PARAM_NO | self::PARAM_EXCLUSIVE,
'FAST' => 4097, // self::PARAM_NO | self::PARAM_EXCLUSIVE,
'FULL' => 4097, // self::PARAM_NO | self::PARAM_EXCLUSIVE,
'BODY' => 3075, // self::PARAM_NO | self::PARAM_SINGLE | self::PARAM_BODY | self::PARAM_PARTIAL,
'BODY.PEEK' => 3074, // self::PARAM_SINGLE | self::PARAM_BODY | self::PARAM_PARTIAL,
'BODYSTRUCTURE' => self::PARAM_NO,
'ENVELOPE' => self::PARAM_NO,
'FLAGS' => self::PARAM_NO,
'INTERNALDATE' => self::PARAM_NO,
'RFC822' => self::PARAM_NO,
'RFC822.HEADER' => self::PARAM_NO,
'RFC822.SIZE' => self::PARAM_NO,
'RFC822.TEXT' => self::PARAM_NO,
'UID' => self::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 $lastSend = '';
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->getResponse();
} public function capability() {
$res = $this->request('capability');
if (isset($res[0][0]) && $res[0][0] == '*' &&
isset($res[0][1]) && strcasecmp($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 (isset($this->capabilities['ID'])) {
$this->request('id', array($data));
}
}
public function login($username, $password) {
try {
$this->request('login', array($username, $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 (isset($r[0]) && $r[0] == '*' &&
isset($r[1]) && strcasecmp($r[1], 'list') == 0 &&
isset($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, self::$statusKeywords);
$res = $this->request('status', array($folder, $args));
$status = array();
if (!empty($res)) {
foreach ($res as &$r) {
if (isset($r[0]) && $r[0] == '*' &&
isset($r[1]) && strcasecmp($r[1], 'status') == 0 &&
isset($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 select($folder) {
$res = $this->request('select', array($folder));
$status = array();
if (!empty($res)) {
foreach ($res as $r) {
if (isset($r[0]) && $r[0] == '*') {
if (isset($r[1]) && isset($r[2])) {
if (strcasecmp($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];
}
} elseif (ctype_digit($r[1])) {
$status[$r[2]] = $r[1];
} else {
$status[$r[1]] = $r[2];
}
}
}
}
}
$this->currentFolder = $folder;
return $status;
}
public function search($data) {
$args = $this->formatArgsForCommand($data, self::$searchKeywords, true);
$res = $this->request('search', $args);
$ls = array();
foreach ($res as &$r) {
if (isset($r[0]) && $r[0] == '*' &&
isset($r[1]) && strcasecmp($r[1], 'search') == 0) {
for ($i = 2, $n = count($r); $i < $n; ++$i) {
$ls[] = $r[$i];
}
}
}
return $ls;
}
public function fetch($seq, $data) {
$seqStr = $this->formatSequence($seq);
$args = $this->formatArgsForCommand($data, self::$fetchKeywords);
$res = $this->request('fetch', array($seqStr, $args));
// var_dump($res);
$ls = array();
foreach ($res as &$r) {
if (isset($r[0]) && $r[0] == '*' &&
isset($r[1]) && is_numeric($r[1]) &&
isset($r[2]) && strcasecmp($r[2], 'fetch') == 0 &&
isset($r[3]) && is_array($r[3])) {
$a = array();
for ($i = 0, $n = count($r[3]); $i < $n; $i += 2) {
$key = $r[3][$i];
if (((strcasecmp($key, 'BODY') == 0 && isset($args['BODY']) && is_array($args['BODY'])) ||
(strcasecmp($key, 'BODY.PEEK') == 0 && isset($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++;
} else {
$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; // 格式化参数列表
$strSeqList = array();
if (is_array($args)) {
$argStr = $this->formatRequestArray($args, $strSeqList);
} else {
$argStr = $this->formatRequestString($args, $strSeqList);
}
//$argStr = $this->makeRequest($args, $strSeqList);
$subReqs = array();
if (isset($argStr[0])) {
$req .= ' ' . $argStr;
// 如果参数中包括需要序列化的数据,根据序列化标识{length}将命令拆分成多条
if (!empty($strSeqList) && preg_match_all(self::PATTERN_REQUEST_STRING_SEQUENCE, $req, $matches, PREG_OFFSET_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($strSeqList) + 1) {
$subReqs = null;
}
}
} if (empty($subReqs)) {
// 处理单条命令
$this->sock->writeLine($req);
$this->lastSend = $req;
$res = $this->getResponse($tag);
} else {
// 处理多条命令
$this->lastSend = '';
foreach ($subReqs as $id => $req) {
$this->sock->writeLine($req);
$this->lastSend .= $req;
$res = $this->getResponse($tag);
if (isset($res[0][0]) && $res[0][0] == '+') {
$this->sock->write($strSeqList[$id]);
$this->lastSend .= "\r\n" . $strSeqList[$id];
} else {
// 如果服务器端返回其他相应,则定制后续执行
break;
}
}
}
return $res;
} private function formatRequestString($s, &$strSeqList) {
$s = trim($s);
$needQuote = false;
if (!isset($s[0])) {
$needQuote = true;
} elseif ($this->currentCommand == 'ID') {
$needQuote = true;
} else {
// 参数包含多行时,需要进行序列化
if (strpos($s, "\r") !== false || strpos($s, "\n") !== false) {
$strSeqList[] = $s;
$s = sprintf('{%d}', strlen($s));
} else {
// 参数包含双引号或空格时,需要将使用双引号括起来
if (strpos($s, '"') !== false) {
$s = addcslashes($s, '"');
$needQuote = true;
}
if (strpos($s, ' ') !== false) {
$needQuote = true;
}
}
}
if ($needQuote) {
return sprintf('"%s"', $s);
} else {
return $s;
}
}
private function formatRequestArray($arr, &$strSeqList, $level = -1) {
$a = array();
foreach ($arr as $k => $v) {
$isBody = false;
$supportPartial = false;
$partialStr = '';
if ($this->currentCommand == 'FETCH') {
// 识别是否body命令,是否可以包含<partial>
$kw = strtoupper($k);
if (isset(self::$fetchKeywords[$kw]) && (self::$fetchKeywords[$kw] & self::PARAM_BODY) > 0) {
$isBody = true;
}
if (isset(self::$fetchKeywords[$kw]) && (self::$fetchKeywords[$kw] & self::PARAM_PARTIAL) > 0) {
$supportPartial = true;
}
}
if (is_array($v)) {
if ($supportPartial && isset($v[self::PARTIAL_PARAM_NAME]) && is_array($v[self::PARTIAL_PARAM_NAME])) {
// 处理包含<partial>的命令
foreach ($v[self::PARTIAL_PARAM_NAME] as $spos => $mlen) {
$partialStr = sprintf('<%d.%d>', $spos, $mlen);
}
unset($v[self::PARTIAL_PARAM_NAME]);
}
$s = $this->formatRequestArray($v, $strSeqList, $level + 1);
} else {
$s = $this->formatRequestString($v, $strSeqList);
}
if (!is_numeric($k)) {
// 字典方式需要包含键名
$k = $this->formatRequestString($k, $strSeqList);
if ($isBody) {
$s = $k . $s;
} else {
$s = $k . ' ' . $s;
}
// 包含<partial>
if ($supportPartial) {
$s .= $partialStr;
}
}
$a[] = $s;
}
if ($level < 0) {
return implode(' ', $a);
} elseif (($level % 2) == 0) {
return sprintf('(%s)', implode(' ', $a));
} else {
return sprintf('[%s]', implode(' ', $a));
}
}
private function formatSequence($seq) {
$n = count($seq);
if ($n == 0) {
return '1:*';
} elseif ($n == 1) {
if (isset($seq[0])) {
return strval($seq[0]);
} else {
foreach ($seq as $k => $v) {
return $k . ':' . $v;
}
}
} else {
return implode(',', $seq);
}
}
private function formatArgsForCommand(&$data, &$fields, $asList = false) {
$args = array();
foreach ($data as $k => $v) {
if (is_numeric($k)) {
// 无值参数
$name = strtoupper($v);
if (isset($fields[$name])) {
// 对于排他性属性,直接返回
if (($fields[$name] & self::PARAM_EXCLUSIVE) > 0) {
return $name;
} elseif (($fields[$name] & self::PARAM_NO) > 0) {
$args[] = $name;
}
}
} elseif ($k == self::SEQUENCE_PARAM_NAME) {
// 序列
$args[] = $this->formatSequence($v);
} else {
$name = strtoupper($k);
if (isset($fields[$name])) {
$paramType = $fields[$name];
// 格式化参数类型
if (($paramType & self::PARAM_DATE) > 0) {
$v = date('j-M-Y', $v);
} elseif (($paramType & self::PARAM_SEQUENCE) > 0) {
$v = $this->formatSequence($v);
} // 根据参数定义拼组参数列表
if (($paramType & self::PARAM_SINGLE) > 0) {
// 单值参数
if ($asList) {
$args[] = $name;
$args[] = $v;
} else {
$args[$name] = $v;
}
} elseif (($paramType & self::PARAM_PAIR) > 0) {
// 键值对参数
if (is_array($v)) {
foreach ($v as $x => $y) {
$pk = $x;
$pv = $y;
break;
}
} else {
$pk = $v;
$pv = '';
}
if ($asList) {
$args[] = $name;
$args[] = $pk;
$args[] = $pv;
} else {
$args[$name] = array($pk => $pv);
}
} elseif (($paramType & self::PARAM_LIST) > 0) {
// 列表参数
if ($asList) {
$args[] = $name;
foreach ($v as $i) {
$args[] = $i;
}
} else {
$args[$name] = $v;
}
} elseif (($paramType & self::PARAM_NO) > 0) {
// 无值参数
$args[] = $name;
}
}
}
}
return $args;
}
private function getResponse($tag = null) {
$r = array();
$readMore = true;
while ($readMore) {
$ln = trim($this->sock->readLine());
if (!isset($ln[0])) {
// connection closed or read empty string, throw exception to avoid dead loop and reconnect
throw new Exception('read response failed');
} $matches = null;
$strSeqKey = null;
$strSeq = null;
if (preg_match(self::PATTERN_RESPONSE_STRING_SEQUENCE, $ln, $matches)) {
$strSeqKey = $matches[0];
$this->readSequence($ln, $strSeq, $matches[1]);
}
$this->lastRecv = $ln; // 区分处理不同种响应
switch ($ln[0]) {
case '*':
$r[] = $this->parseLine($ln, $strSeqKey, $strSeq);
if (!$tag) {
$readMore = false;
}
break;
case $this->tagName:
$r[] = $this->parseLine($ln);
if ($tag) {
$readMore = false;
} else { }
break;
case '+':
$r[] = $this->parseLine($ln);
$readMore = false;
break;
default:
$r[] = $ln;
break;
}
} //var_dump($this->lastSend, $this->lastRecv); // 无响应数据
if (empty($r)) {
throw new Exception('no response');
} $last = $r[count($r) - 1];
if (isset($last[0]) && $last[0] == '+') {
// 继续发送请求数据
} else {
if ($tag) {
if (!isset($last[0]) || strcasecmp($last[0], $tag) != 0) {
throw new Exception('tag no match');
}
} else {
if (!isset($last[0]) || strcasecmp($last[0], '*') != 0) {
throw new Exception('untag no match');
}
}
if (isset($last[1])) {
// 处理响应出错的情况
if (strcasecmp($last[1], 'bad') == 0) {
throw new Exception(implode(' ', $last));
} elseif (strcasecmp($last[1], 'no') == 0) {
throw new Exception(implode(' ', $last));
}
}
//$this->currentCommand = null;
} return $r;
} private function readSequence(&$ln, &$strSeq, $seqLength) {
// 对于字符串序列,读取完整内容后再拼接响应
$readLen = 0;
$st = microtime(true);
// 网络请求多次读取字符串序列内容,直到读好为止
while ($readLen < $seqLength) {
$sb = $this->sock->read($seqLength - $readLen);
if (isset($sb[0])) {
$strSeq .= $sb;
$readLen = strlen($strSeq);
}
if ((microtime(true) - $st) > $this->timeout) {
throw new Exception('read sequence timeout');
}
}
// 读取字符串序列后的剩余命令
$leftLn = rtrim($this->sock->readLine());
$ln = $ln . $leftLn;
} private function parseLine($ln, $strSeqKey = null, $strSeq = null) {
$r = array();
$p =& $r;
$stack = array();
$token = '';
$escape = false;
$inQuote = false;
for ($i = 0, $n = strlen($ln); $i < $n; ++$i) {
$ch = $ln[$i];
if ($ch == '"') {
// 处理双引号括起的字符串
if (!$inQuote) {
$inQuote = true;
} else {
$inQuote = false;
}
} elseif ($inQuote) {
// 对于括起的字符串,处理双引号转义
if ($ch == '\\') {
if (!$escape && isset($ln[$i + 1]) && $ln[$i + 1] == '"') {
$token .= '"';
$i++;
} else {
$token .= $ch;
$escape = !$escape;
}
} else {
$token .= $ch;
}
} elseif ($ch == ' ' ||
$ch == '(' || $ch == ')' ||
$ch == '[' || $ch == ']') {
// 处理子列表
if (isset($token[0])) {
// 将字符串序列标识:{length},替换为真实字符串
if ($strSeqKey && $token == $strSeqKey) {
$p[] = $strSeq;
} else {
$p[] = $token;
}
$token = '';
}
if ($ch == '(' || $ch == '[') {
$p[] = array();
$stack[] =& $p;
$p =& $p[count($p) - 1];
} elseif ($ch == ')' || $ch == ']') {
$p =& $stack[count($stack) - 1];
array_pop($stack);
}
} else {
// 处理字符串字面量
$token .= $ch;
}
}
if (isset($token[0])) {
// 将字符串序列标识:{length},替换为真实字符串
if ($strSeqKey && $token == $strSeqKey) {
$p[] = $strSeq;
} else {
$p[] = $token;
}
}
return $r;
}
} // end of php

socket.php

<?php
class Socket{
const DEFAULT_READ_SIZE = 8192;
const CRTL = "\r\n";
private $uri = null;
private $timeout = null;
private $sock = null;
private $connected = false;
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->close();
} $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_set_timeout($this->sock, $this->timeout);
$this->connected = true;
} public function read($size){
assert($this->connected); $buf = fread($this->sock, $size);
if ($buf === false) {
$this->handleReadError();
} return $buf;
} public function readLine(){
assert($this->connected);
$buf = '';
while (true) {
$s = fgets($this->sock, self::DEFAULT_READ_SIZE);
if ($s === false) {
$this->checkReadTimeout();
break;
}
$n = strlen($s);
if (!$n) {
break;
}
$buf .= $s;
if ($s[$n - 1] == "\n") {
break;
}
} return $buf;
} public function readAll(){
assert($this->connected);
$buf = '';
while (true) {
$s = fread($this->sock, self::DEFAULT_READ_SIZE);
if ($s === false) {
$this->handleReadError();
} if (!isset($s[0])) {
break;
} $buf .= $s;
} return $buf;
} public function write($s){
assert($this->connected);
$n = strlen($s);
$w = 0;
while ($w < $n) {
$buf = substr($s, $w, self::DEFAULT_READ_SIZE);
$r = fwrite($this->sock, $buf);
if (!$r) {
$this->close();
}
$w += $r;
}
}
public function writeLine($s){
$this->write($s . self::CRTL);
}
public function close() {
if ($this->connected) {
fclose($this->sock);
$this->connected = false;
}
}
private function formatTimeout($timeout, $default = null){
$t = intval($timeout);
if ($t <= 0) {
if (!$default) {
$t = ini_get('default_socket_timeout');
} else {
$t = $default;
}
}
return $t;
} private function checkReadTimeout(){
$meta = stream_get_meta_data($this->sock);
if (isset($meta['timed_out'])) {
$this->close();
}
} private function handleReadError(){
$this->checkReadTimeout();
$this->close();
}
}

[PHP] PHP调用IMAP协议读取邮件类库的更多相关文章

  1. [日常] imap协议读取邮件

    telnet imap.sina.net 143 A01 LOGIN shihan@appdev.sinanet.com 密码 A02 list "" * //列出邮件夹 * LI ...

  2. 基于Lumisoft.NET组件,使用IMAP协议收取邮件

    在早期一直使用Lumisoft.NET组件来进行邮件的处理查找,对于邮件的处理非常方便,之前在随笔<基于Lumisoft.NET组件的POP3邮件接收和删除操作>中也介绍过基于POP3和S ...

  3. 使用 EWS(Exchange Web Service)协议读取邮件、发送邮件

    问题: 公司之前可以通过POP3协议收发邮件,因而在SoapUI中用JavaMail可以读取邮件,后来配置了Office 365,POP3协议端口不再开放,邮件全部读取失败,报login timeou ...

  4. Android javaMail使用imap协议接收邮件

    在这里说明一下,pop3和imap协议都是接收邮件的,但是他们还是有很多不同的. IMAP和POP有什么区别? POP允许电子邮件客户端下载服务器上的邮件,但是您在电子邮件客户端的操作(如:移动邮件. ...

  5. 使用imap协议接收邮件

    之前一直使用PHPMail类进行发送邮件,这个是一个非常强大的类,但是其实底层就是使用mail()函数来进行发送的. 但是现在公司有个需求是  写个程序需要实时的接收邮件,主要是判断邮件发出去了,并且 ...

  6. C# Po3协议读取邮件内容遇到的问题

    背景:最近在做一个小工具,读取PO3协议邮件服务器的指定人员的邮件,东西做出来了,弄了一个While死循环,20秒执行一次, 结果运行了3天,周一来IT人员找上门来了,你的电脑什么情况,怎么一个小时下 ...

  7. MailKit使用IMAP读取邮件找不到附件Attachments为空的解决方法

    今天发现有些邮件无法读取Attachments,邮件明明有附件,但使用Mailkit读取时,Attachments为空,我用的IMAP协议读取收件箱里的邮件,处理完后移动已删除: foreach (v ...

  8. Android pop3与imap方式接收邮件(javamail)

    需要下载3个jar包:mail.jar/    activation.jar/    additionnal.jar 1.pop3 /** * 以pop3方式读取邮件,此方法不能读取邮件是否为已读,已 ...

  9. mail客户端POP和IMAP协议

    POP-邮局协议 mail客户端如果使用POP协议,那么线上服务器的邮件将会自动下载到客户端. IMAP-因特网消息访问协议 mail客户端如果使用IMAP协议,邮件服务器上的邮件将不会自动下载到客户 ...

随机推荐

  1. Python xlwt 写Excel相关操作记录

    1.安装xlwt pip install xlwt 2.写Excel必要的几步 import xlwt book = xlwt.Workbook() #创建一个workbook,无编码设置编码book ...

  2. 前端常用的css代码

    1.垂直居中对齐 .vc{ position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); } .vc{ position: ...

  3. 【转】SQL中GROUP BY语句与HAVING语句的使用

    一.GROUP BY GROUP BY语句用来与聚合函数(aggregate functions such as COUNT, SUM, AVG, MIN, or MAX.)联合使用来得到一个或多个列 ...

  4. 基于socketserver实现并发的socket编程

    目录 一.基于TCP协议 1.1 server类 1.2 request类 1.3 继承关系 1.4 服务端 1.5 客户端 1.6 客户端1 二.基于UDP协议 2.1 服务端 2.2 客户端 2. ...

  5. EJB组件开发实记(1)

    安装JBoss或者Wildfly jdk1.4以上. Eclipes安装插件 JBoss Tools: eclipes Jee photon 在eclipes 内部点击 >>Windows ...

  6. MongoDB for OPS 04:备份恢复

    写在前面的话 和 MySQL 一样,mongodb 也是需要将数据进行备份的,毕竟天有不测风云,谁也不知道哪天机器就炸了. 备份恢复 mongodb 提供了两种备份恢复手段:mongoexport / ...

  7. 使用pytorch时所遇到的问题总结

    使用pytorch时所遇到的问题总结 1.ubuntu vscode切换虚拟环境 在ubuntu系统上,配置工作区文件夹所使用的虚拟环境.之前笔者误以为只需要在vscode内置的终端上将虚拟环境切换过 ...

  8. SpringCloud的入门学习之Eureka(Eureka的单节点)

    SpringCloud--->Spring生态体系的微服务架构:https://spring.io/ 官网贴图,如下所示,介绍了微服务的架构体系(话说,英语好读官网,可能很爽吧,没体验过). 1 ...

  9. go-goroutine 和 channel

    goroutine 和 channel goroutine-看一个需求 需求:要求统计 1-9000000000 的数字中,哪些是素数? 分析思路: 1) 传统的方法,就是使用一个循环,循环的判断各个 ...

  10. Python爬取知乎上搞笑视频,一顿爆笑送给大家

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:Huangwei AI 来源:Python与机器学习之路 PS:如有需 ...