作者 邓超

1

<?php
var_dump(str_starts_with('a_sdf','_'));
//use Model\listsSql;
//include_once __DIR__."/../vendor/autoload.php";
//
//print_r(redis()->incr('asdfasdfasdfasdf',600));
//$ids = db()->all('select `id` from `'.\Model\emailSql::$table.'` limit 1000 offset 0');
//print_r($ids);
... ...
... ... @@ -52,6 +52,8 @@ function start(){
if(!$id){
co::sleep(1);
}else{
// 占用当前的id,占用2小时
redis()->add('just_sync_'.$id,time(),7200);
// 启动一个协程
go(function () use (&$start_num,$worker_id,$id){
$start_num++;
... ... @@ -71,10 +73,19 @@ function start(){
}
// 协程完成后执行的函数
co::defer(function () use (&$start_num,$worker_id){
co::defer(function () use (&$start_num,$worker_id,$id){
// _echo('正常关闭进程('.$worker_id.')下的协程('.co::getCid().')');
$start_num--;
// 消除占用
redis()->delete('just_sync_'.$id);
// 写入日志
\Lib\Log::getInstance()->write();
// 关闭数据库链接
db()->close();
// 关闭redis链接
redis()->close();
});
});
... ...
... ... @@ -2,6 +2,8 @@
error_reporting(E_ERROR | E_NOTICE | E_WARNING);
ini_set('display_errors',0);
// 开启4个进程
define('WORKER_NUM',10);
// 开启最大1000个协程
... ...
... ... @@ -55,6 +55,9 @@ abstract class Base {
if(empty($data)){
app()->e('email_request_required');
}
if($data['pwd_error']){
app()->e('imap_password_error',403);
}
}
if($filed == '*'){
... ...
... ... @@ -3,6 +3,7 @@
namespace Controller;
use Lib\Err;
use Lib\Mail\Mail;
use Lib\Mail\MailFun;
use Model\folderSql;
... ... @@ -23,16 +24,38 @@ class Folder extends Base {
* @time 2023/2/18 10:58
*/
public function lists(){
try {
$emails = $this->getEmails();
}catch (Err $e){
$emails = [$this->getEmail()];
}
$emails = array_column($emails,'email','id');
// 查询
$folders = db()->all(
\Model\folderSql::all(
$this->getEmail('id'),
'`id`,`folder`,`pid`,`exsts`,`unseen`'
array_keys($emails),
'`id`,`folder`,`pid`,`exsts`,`unseen`,`email_id`'
)
);
// 转tree
$folders = list_to_tree($folders);
$data = [];
foreach ($folders as $k=>$folder){
if (empty($data[$emails[$folder['email_id']]])){
$data[$emails[$folder['email_id']]] = [];
}
$data[$emails[$folder['email_id']]][$k] = $folder;
unset($data[$emails[$folder['email_id']]][$k]['email_id']);
}
$folders = $data;$data = null;
foreach ($folders as $f=>$folder){
// 转tree
$folders[$f] = list_to_tree($folder);
}
return $folders;
}
... ...
... ... @@ -28,30 +28,42 @@ class Home extends Base {
$page = app()->request('page',1,'intval');
$page = $page ? $page : 1;
$size = app()->request('size',20,'intval');
$size = $size ? $size : 1;
$limit = app()->request('limit',20,'intval');
$limit = $limit ? $limit : 1;
// 指定id
$ids = app()->request('mail_id');
$ids = is_array($ids) ? $ids : [$ids];
foreach ($ids as $i=>$d){
if(!is_numeric($d)){
unset($ids[$i]);
}
}
// 邮件文件夹的id
$folder_id = app()->request('folder_id');
$folder_id = (int) app()->request('folder_id');
// 附件
$attachment = app()->request('attachment');
$where = ['email_id'=>$this->getEmails('id')];
if($folder_id) $where['folder_id'] = $folder_id;
if($ids) $where['id'] = $ids;
if($attachment) $where['is_file'] = 1; //附件
$lists = db()->all(
listsSql::lists(
$this->getEmails('id'),
dbWhere($where),
$page,
$size,
(int) $folder_id
$limit
)
);
// 总数
$total = db()->count(
listsSql::listCount(
$this->getEmails('id'),
(int) $folder_id
)
listsSql::listCount(dbWhere($where))
);
app()->_json(listsPage($lists,$total,$page,$size));
app()->_json(listsPage($lists,$total,$page,$limit));
}
... ... @@ -112,18 +124,18 @@ class Home extends Base {
*/
public function sync(){
$where['email'] = web_request_emails();
$emails = web_request_emails();
if(empty($where)){
if(empty($emails)){
app()->e('sync_request_param_error');
}else{
// 查询id
$datas = db()->all(emailSql::getValues($where,'`id`,`email`,`pwd_error`'));
foreach ($datas as &$v){
$datas = db()->all(emailSql::getValues(['email'=>$emails],'`id`,`email`,`pwd_error`'));
foreach ($datas as $k=>$v){
if(!$v['pwd_error']){
redis()->rPush('sync_email_lists', $v['id']);
}
unset($v['id']);
$datas[$k]['have_new'] = redis()->getDel('have_new_mail_'.$v['id']);
}
// 返回成功的参数值
app()->_json($datas);
... ...
... ... @@ -68,6 +68,7 @@ class Login {
$ret = db()->update(emailSql::$table,$data,dbWhere(['id'=>$id]));
}else{
// 新增
$data['email'] = $formData['email'];
$ret = db()->insert(emailSql::$table,$data);
if($ret){
... ... @@ -81,9 +82,7 @@ class Login {
if($ret){
app()->_json([
'token' => $data['token']
]);
app()->_json(db()->first(emailSql::first($formData['email'],'`id`,`email`,`last_sync_time`')));
}
app()->e('login_error');
... ...
... ... @@ -181,7 +181,7 @@ function web_request_emails():array {
$emails = app()->request('emails');
$emails = is_array($emails) ? $emails : [$emails];
foreach ($emails as $k=>$email){
if(!\Lib\Verify::sEmail($email)){
if(!$email || !\Lib\Verify::sEmail($email)){
unset($emails[$k]);
}
}
... ... @@ -203,7 +203,7 @@ function web_request_emails():array {
function web_request_email():string {
$email = app()->request('email');
if(!\Lib\Verify::sEmail($email)){
if(!$email || !\Lib\Verify::sEmail($email)){
app()->e('email_request_required');
}
... ...
... ... @@ -17,9 +17,10 @@ return [
'server_error' => '服务器异常',
'login_error' => '登录失败',
'login_error_imap' => '登录失败,请检查密码/是否开启imap服务',
'login_error_imap' => '登录失败,请检查密码是否正确或者是否开启imap/smtp服务',
'token_verify_error' => '令牌验证失败',
'token_verify_notfound' => '令牌验证失败.',
'imap_password_error' => '密码错误请重新登录.',
'param_request_error' => '参数异常',
'folder_create_name_error' => '文件夹名称只能输入中文英文数字',
... ...
... ... @@ -276,10 +276,14 @@ class DbPool {
* 结束
*/
public function __destruct(){
$this->client = null;
$this->close();
}
public function close(){
$this->client = null;
}
}
... ...
... ... @@ -178,6 +178,9 @@ class Mail {
// 循环
$results = $this->client->fetchHeader($msgno);
if($results){
// 表示已存在新邮件
redis()->incr('have_new_mail_'.$email_id,120);
// 批量插入
foreach ($results as $key=>$result){
$header = $result['HEADER.FIELDS'];
... ...
... ... @@ -138,22 +138,38 @@ class RedisPool {
/**
* 自增
* @param $key
* @param null $ttl
* @return int
* @author:dc
* @time 2023/2/17 15:29
*/
public function incr($key){
public function incr($key, $ttl = null){
if($ttl){
return $this->client->eval(
"local x = redis.call('incr',KEYS[1]);redis.call('expire',KEYS[1],ARGV[1]);return x",
[$key, $ttl],
1
);
}
return $this->client->incr($key);
}
/**
* 自减
* @param $key
* @param null $ttl
* @return int
* @author:dc
* @time 2023/2/17 15:29
* @time 2023/3/16 11:19
*/
public function decr($key){
public function decr($key,$ttl = null){
if($ttl){
return $this->client->eval(
"local x = redis.call('decr',KEYS[1]);redis.call('expire',KEYS[1],ARGV[1]);return x",
[$key, $ttl],
1
);
}
return $this->client->decr($key);
}
... ... @@ -169,6 +185,20 @@ class RedisPool {
return $this->client->del($key);
}
/**
* 获取值并删除
* @param $key
* @return mixed
* @author:dc
* @time 2023/3/16 11:36
*/
public function getDel($key){
return $this->client->eval(
"local x = redis.call('get',KEYS[1]);if x then redis.call('del',KEYS[1]) end return x",
[$key],
1
);
}
/**
... ... @@ -196,14 +226,7 @@ class RedisPool {
public function __destruct()
{
// TODO: Implement __destruct() method.
try {
if($this->client->ping()){
$this->client->close();
}
}catch (\RedisException $e){}
$this->client = null;
$this->close();
}
... ... @@ -228,7 +251,21 @@ class RedisPool {
}
/**
* 关闭
* @author:dc
* @time 2023/3/16 13:42
*/
public function close(){
// TODO: Implement __destruct() method.
try {
if($this->client->ping()){
$this->client->close();
}
}catch (\RedisException $e){}
$this->client = null;
}
... ...
... ... @@ -35,7 +35,7 @@ class Verify {
* @author:dc
* @time 2023/3/10 16:04
*/
public static function sEmail($email){
public static function sEmail(string $email){
return preg_match('/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/',$email);
}
... ... @@ -57,7 +57,7 @@ class Verify {
* @author:dc
* @time 2023/3/13 10:59
*/
public static function sDomain($domain){
public static function sDomain(string $domain){
return preg_match('/[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?/',$domain);
}
... ... @@ -68,7 +68,7 @@ class Verify {
* @author:dc
* @time 2023/3/13 11:00
*/
public static function sUrl($url){
public static function sUrl(string $url){
return preg_match('/[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$/',$url);
}
... ...
... ... @@ -15,13 +15,13 @@ class folderSql {
/**
* 所有文件夹
* @param int $email_id
* @param int|array $email_id
* @return string
* @author:dc
* @time 2023/2/18 9:22
*/
public static function all(int $email_id, $field = '`id`,`folder`,`pid`,`origin_folder`,`last_sync_time`'):string {
return "select {$field} from `".static::$table."` where `email_id` = {$email_id} order by `id` asc";
public static function all(int|array $email_id, $field = '`id`,`folder`,`pid`,`origin_folder`,`last_sync_time`'):string {
return "select {$field} from `".static::$table."` where ".dbWhere(['email_id'=>$email_id])." order by `id` asc";
}
... ...
... ... @@ -20,37 +20,31 @@ class listsSql {
/**
* 查询列表
* @param int|array $email_id
* @param string $where
* @param int $p
* @param int $size
* @param int $folder_id
* @return string
* @author:dc
* @time 2023/3/10 15:24
* @time 2023/3/16 18:11
*/
public static function lists(int|array $email_id, int $p, int $size, int $folder_id = 0){
public static function lists(string $where, int $p, int $size){
$where = ['email_id'=>$email_id];
if($folder_id) $where['folder_id'] = $folder_id;
$filed = '`id`,`uid`,`msgno`,`subject`,`from`,`from_name`,`to`,`date`,`size`,`recent`,`flagged`,`answered`,`deleted`,`seen`,`draft`,`udate`,`folder_id`,`is_file`,`cc`,`bcc`,`description`';
$filed = '`id`,`uid`,`msgno`,`subject`,`from`,`to`,`date`,`size`,`recent`,`flagged`,`answered`,`deleted`,`seen`,`draft`,`udate`,`folder_id`,`is_file`,`cc`,`bcc`';
return "select {$filed} from `".static::$table."` where ".dbWhere($where)." order by `udate` desc limit {$size} offset ".(($p-1)*30);
return "select {$filed} from `".static::$table."` where ".$where." order by `udate` desc limit {$size} offset ".(($p-1)*30);
}
/**
* 统计列表
* @param int|array $email_id
* @param int $folder_id
* @param string $where
* @return string
* @author:dc
* @time 2023/3/10 15:26
* @time 2023/3/16 18:10
*/
public static function listCount(int|array $email_id, int $folder_id = 0){
$where = ['email_id'=>$email_id];
if($folder_id) $where['folder_id'] = $folder_id;
return "select count(*) from `".static::$table."` where ".dbWhere($where);
public static function listCount(string $where){
return "select count(*) from `".static::$table."` where ".$where;
}
/**
... ...