作者 邓超

mail del

  1 +<?php
  2 +
  3 +
  4 +/**
  5 + * 循环本地,验证远程是否存在 不存在则删除本地
  6 + */
  7 +//error_reporting();
  8 +
  9 +use Swoole\Process;
  10 +
  11 +
  12 +
  13 +function start(){
  14 +
  15 +// 删除停止运行的值
  16 +// redis()->delete(SYNC_RUNNING_REDIS_KEY,'email_sync_stop_num');
  17 +
  18 + // 进程管理器
  19 + $pm = new Process\Manager();
  20 +
  21 + // 启动业务进程
  22 + $pm->addBatch(1,function (Process\Pool $pool, int $worker_id){
  23 +
  24 + swoole_set_process_name('php-email-sync-list-check-'.$worker_id);
  25 +
  26 + include_once __DIR__."/../vendor/autoload.php";
  27 + _echo("业务进程({$worker_id})启动成功");
  28 +
  29 + $run_timer = time();
  30 +
  31 + $id = 0;
  32 + // 循环阻塞
  33 + while (true){
  34 +
  35 + // 运行超过1天的 停止
  36 + if($run_timer < (time()-21600)){
  37 + break;
  38 + }
  39 +
  40 + $id = db()->value(\Model\listsSql::first('`id` > '.$id,'`id`'));
  41 +
  42 + if($id){
  43 + // 占用当前的id,占用2小时
  44 + if(redis()->add('just_sync_delete_'.$id,time(),3600)){
  45 + // 启动一个协程
  46 + go(function () use ($id){
  47 + // 开始同步
  48 + try {
  49 + sync($id);
  50 + }catch (\Throwable $e){
  51 + echo $e->getMessage();
  52 + }
  53 + \Lib\Log::getInstance()->write();
  54 + });
  55 + }
  56 + }else{
  57 + co::sleep(1);
  58 + }
  59 + //每次都暂停1秒,防止同一时间启动太多的任务
  60 + co::sleep(0.5);
  61 + }
  62 +
  63 + },true);
  64 +
  65 +
  66 + // 启动管理器
  67 + $pm->start();
  68 +
  69 +}
  70 +
  71 +/**
  72 + * 开始同步, 这里是主要的业务代码
  73 + * @param $email_id
  74 + * @param $worker_id
  75 + * @return int
  76 + * @author:dc
  77 + * @time 2023/3/10 10:19
  78 + */
  79 +function sync($email_id){
  80 +
  81 + $email = db()->first(\Model\emailSql::first($email_id));
  82 + if(!$email || $email['pwd_error']){
  83 + return 0;
  84 + }
  85 +
  86 + // 读取到邮箱中的文件夹
  87 + $folders = db()->all(\Model\folderSql::all($email['id']));
  88 + if(!$folders){
  89 + return 3;
  90 + }
  91 +
  92 +
  93 + $mailServer = new Lib\Mail\Mail($email['email'],base64_decode($email['password']),$email['imap']);
  94 +
  95 + // 登录服务器
  96 + if($mailServer->login()!==1){
  97 + return 2;
  98 + }
  99 +
  100 + $call = function ($email_id,$folder_id,$origin_folder) use ($mailServer){
  101 + // gmail 邮箱 这个是不可选的
  102 + if($origin_folder == '[Gmail]'){
  103 + return;
  104 + }
  105 + // 同步父文件夹
  106 + $mailServer->client->selectFolder($origin_folder);
  107 + $page = 0;
  108 + $db = db();
  109 + while (1){
  110 + $ids = $db->all("select `id`,`uid` from ".\Model\listsSql::$table." limit 100 offset ".($page*100));
  111 + $page++;
  112 + if($ids){
  113 + $ids = array_column($ids,'id','uid');
  114 + $result = $mailServer->client->fetch(array_keys($ids),'UID',true);
  115 + foreach ($ids as $uid=>$id){
  116 + if(!isset($result[$uid])){
  117 + _echo('删除 e '.$email_id.' f '.$folder_id.' u '.$uid.' id '.$id);
  118 + // 删除 如果远程没有,就删除本地
  119 + $db->delete(\Model\listsSql::$table,['id'=>$id]);
  120 + }
  121 + }
  122 + }
  123 + // 结束了
  124 + if(count($ids) < 100){
  125 + break;
  126 + }
  127 +
  128 + }
  129 +
  130 +
  131 + };
  132 +
  133 +// $folders = list_to_tree($folders);
  134 + foreach ($folders as $folder){
  135 + try {
  136 +
  137 + if(empty($folder['_child'])){
  138 + $call($email_id,$folder['id'],$folder['origin_folder']);
  139 + }else{
  140 + foreach ($folder['_child'] as $item){
  141 + // 同步子文件夹
  142 + $call($email_id,$item['id'],$item['origin_folder']);
  143 + }
  144 + }
  145 +
  146 + }catch (\Throwable $e){
  147 + logs(
  148 + $e->getMessage().$e->getTraceAsString(),
  149 + LOG_PATH.'/imap/'.$email['email'].'.error.log'
  150 + );
  151 + }
  152 + }
  153 +
  154 +
  155 + $email = null;
  156 + $mailServer = null;
  157 +}
  158 +
  159 +
  160 +if(!function_exists("imap_8bit")){
  161 + echo '请安装imap扩展';
  162 + exit(0);
  163 +}
  164 +
  165 +
  166 +
  167 +start();
  168 +
  169 +
  170 +
  171 +
  172 +
  173 +
  174 +
  175 +
  176 +