| 
...
 | 
...
 | 
@@ -194,153 +194,139 @@ class Mail { | 
| 
 | 
 | 
             false
 | 
| 
 | 
 | 
         );
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         // 最后拉取的msgno
 | 
| 
 | 
 | 
         $lastMsgno   =   $db->value(listsSql::lastMsgno($email_id,$folder_id));
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         $nu = 20;
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         if(!$lastMsgno){
 | 
| 
 | 
 | 
             $msgno = range(1,$nu);
 | 
| 
 | 
 | 
         }else{
 | 
| 
 | 
 | 
             $msgno = range($lastMsgno,$lastMsgno+$nu);
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
             if($lastMsgno > $status['EXISTS']){
 | 
| 
 | 
 | 
                 $msgno = range($status['EXISTS'] > $nu ? $status['EXISTS'] - $nu : 1,$status['EXISTS']);
 | 
| 
 | 
 | 
             }
 | 
| 
 | 
 | 
             // 一样就不拉新的
 | 
| 
 | 
 | 
             if($lastMsgno == $status['EXISTS']){
 | 
| 
 | 
 | 
                 return true;
 | 
| 
 | 
 | 
             }
 | 
| 
 | 
 | 
         if(!$status['EXISTS']){
 | 
| 
 | 
 | 
             return true;
 | 
| 
 | 
 | 
         }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         //
 | 
| 
 | 
 | 
         $nu = 100;
 | 
| 
 | 
 | 
         $msgno = 1;
 | 
| 
 | 
 | 
         while (true){
 | 
| 
 | 
 | 
             // 是否结束了
 | 
| 
 | 
 | 
             if($status['EXISTS'] < $msgno){
 | 
| 
 | 
 | 
                 break;
 | 
| 
 | 
 | 
             }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         // 循环
 | 
| 
 | 
 | 
         $results = $this->client->fetchHeader($msgno);
 | 
| 
 | 
 | 
         if($results && is_array($results)){
 | 
| 
 | 
 | 
             // 表示已存在新邮件
 | 
| 
 | 
 | 
             if($folder == 'INBOX') redis()->incr('have_new_mail_'.$email_id,120);
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
             // 批量插入
 | 
| 
 | 
 | 
             foreach ($results as $key=>$result){
 | 
| 
 | 
 | 
                 $header = $result['HEADER.FIELDS'];
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                 foreach ($result['FLAGS'] as $k=>$FLAG){
 | 
| 
 | 
 | 
                     $result['FLAGS'][$k] = strtolower(str_replace('\\','',$FLAG));
 | 
| 
 | 
 | 
                 }
 | 
| 
 | 
 | 
                 try {
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
             $uids = $this->client->fetch(range($msgno,($msgno-1)+$nu),'UID');
 | 
| 
 | 
 | 
             if(!$uids){
 | 
| 
 | 
 | 
                 break;
 | 
| 
 | 
 | 
             }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 //                    if(empty($header['Subject'])){
 | 
| 
 | 
 | 
 //                        logs($result);
 | 
| 
 | 
 | 
 //                    }
 | 
| 
 | 
 | 
             $uids = array_column($uids,'UID');
 | 
| 
 | 
 | 
             $existsUids = $db->value(listsSql::getUids($email_id,$folder_id,$uids));
 | 
| 
 | 
 | 
             // 获取不存在数据库的uid
 | 
| 
 | 
 | 
             $uids = array_diff($uids,$existsUids);
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
             $msgno += $nu;
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
             // 开始同步
 | 
| 
 | 
 | 
             if($uids){
 | 
| 
 | 
 | 
                 $results = $this->client->fetchHeader($uids,true);
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                 if($results && is_array($results)){
 | 
| 
 | 
 | 
                     // 表示已存在新邮件
 | 
| 
 | 
 | 
                     if($folder == 'INBOX') redis()->incr('have_new_mail_'.$email_id,120);
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                     // 批量插入
 | 
| 
 | 
 | 
                     foreach ($results as $key=>$result){
 | 
| 
 | 
 | 
                         $header = $result['HEADER.FIELDS'];
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                         foreach ($result['FLAGS'] as $k=>$FLAG){
 | 
| 
 | 
 | 
                             $result['FLAGS'][$k] = strtolower(str_replace('\\','',$FLAG));
 | 
| 
 | 
 | 
                         }
 | 
| 
 | 
 | 
                         try {
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                             // 没有收件人
 | 
| 
 | 
 | 
                             if(!empty($header['To'])){
 | 
| 
 | 
 | 
                                 $header['To'] = MailFun::toOrFrom($header['To']);
 | 
| 
 | 
 | 
                             }else{
 | 
| 
 | 
 | 
                                 $header['To'] = [];
 | 
| 
 | 
 | 
                             }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                             $header['From'] = MailFun::toOrFrom($header['From']);
 | 
| 
 | 
 | 
                             // 抄送 ,密送
 | 
| 
 | 
 | 
                             $cc = [];
 | 
| 
 | 
 | 
                             $bcc = [];
 | 
| 
 | 
 | 
                             if($header['Cc']??''){
 | 
| 
 | 
 | 
                                 $cc = MailFun::toOrFrom($header['Cc']);
 | 
| 
 | 
 | 
                             }
 | 
| 
 | 
 | 
                             if($header['Bcc']??''){
 | 
| 
 | 
 | 
                                 $bcc = MailFun::toOrFrom($header['Bcc']);
 | 
| 
 | 
 | 
                             }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                             $data   =   [
 | 
| 
 | 
 | 
                                 'msgno'   =>  $key,
 | 
| 
 | 
 | 
                                 'uid'   =>  $result['UID'],
 | 
| 
 | 
 | 
                                 'subject'   =>  $header['Subject']??'',
 | 
| 
 | 
 | 
                                 'cc'    =>  $cc,
 | 
| 
 | 
 | 
                                 'bcc'    =>  $bcc,
 | 
| 
 | 
 | 
                                 'from'   =>  $header['From'][0]['email']??'',
 | 
| 
 | 
 | 
                                 'from_name'   =>  $header['From'][0]['name']??'',
 | 
| 
 | 
 | 
                                 'to'   =>  $header['To']?implode(',',array_column($header['To'],'email')):'',
 | 
| 
 | 
 | 
                                 'to_name'   =>  json_encode($header['To']),
 | 
| 
 | 
 | 
                                 'date'   =>  strtotime(is_array($header['Date']??'') ? $header['Date'][0] : $header['Date']??''),
 | 
| 
 | 
 | 
                                 'message_id'   =>  $header['Message-ID']??'',
 | 
| 
 | 
 | 
                                 'udate'   =>  strtotime($result['INTERNALDATE']),
 | 
| 
 | 
 | 
                                 'size'   =>  $result['RFC822.SIZE']??0,
 | 
| 
 | 
 | 
                                 'recent'   =>  in_array('recent',$result['FLAGS']) ? 1 : 0,
 | 
| 
 | 
 | 
                                 'seen'   =>  in_array('seen',$result['FLAGS']) ? 1 : 0,
 | 
| 
 | 
 | 
                                 'draft'   =>  in_array('draft',$result['FLAGS']) ? 1 : 0,
 | 
| 
 | 
 | 
                                 'flagged'   =>  in_array('flagged',$result['FLAGS']) ? 1 : 0,
 | 
| 
 | 
 | 
                                 'answered'   =>  in_array('answered',$result['FLAGS']) ? 1 : 0,
 | 
| 
 | 
 | 
                                 'folder_id'   =>  $folder_id,
 | 
| 
 | 
 | 
                                 'email_id'    =>  $email_id,
 | 
| 
 | 
 | 
                                 'uuid'  =>  md5($email_id.$folder_id.$result['UID']),
 | 
| 
 | 
 | 
                                 'is_file'  =>  MailFun::isFile($result['BODYSTRUCTURE']??'') ? 1: 0 //是否附件
 | 
| 
 | 
 | 
                             ];
 | 
| 
 | 
 | 
                             $data['date'] = $data['date'] ? : 0;
 | 
| 
 | 
 | 
                         }catch (\Throwable $e){
 | 
| 
 | 
 | 
                             logs(
 | 
| 
 | 
 | 
                                 '邮件解析失败:'.PHP_EOL.$e->getMessage().PHP_EOL.print_r($result,true),
 | 
| 
 | 
 | 
                                 LOG_PATH.'/imap/mail/'.$email_id.'/'.$result['UID'].'.log'
 | 
| 
 | 
 | 
                             );
 | 
| 
 | 
 | 
                             unset($results[$key]);
 | 
| 
 | 
 | 
                             continue;
 | 
| 
 | 
 | 
                         }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                         // 插入数据库
 | 
| 
 | 
 | 
                         try {
 | 
| 
 | 
 | 
                             $id = $db->insert(listsSql::$table,$data);
 | 
| 
 | 
 | 
                             if($id){
 | 
| 
 | 
 | 
                                 // 同步body内容
 | 
| 
 | 
 | 
                                 redis()->rPush('sync_email_body', [
 | 
| 
 | 
 | 
                                     'lists_id'  =>  $id,
 | 
| 
 | 
 | 
                                     'email_id'  =>  $email_id,
 | 
| 
 | 
 | 
                                     'folder_id'  =>  $folder_id,
 | 
| 
 | 
 | 
                                     'folder'  =>  $folder,
 | 
| 
 | 
 | 
                                     'uid'  =>  $data['uid'],
 | 
| 
 | 
 | 
                                 ]);
 | 
| 
 | 
 | 
                             }
 | 
| 
 | 
 | 
                         }catch (\Throwable $e){
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                         }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                     // 没有收件人
 | 
| 
 | 
 | 
                     if(!empty($header['To'])){
 | 
| 
 | 
 | 
                         $header['To'] = MailFun::toOrFrom($header['To']);
 | 
| 
 | 
 | 
                     }else{
 | 
| 
 | 
 | 
                         $header['To'] = [];
 | 
| 
 | 
 | 
                     }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                     $header['From'] = MailFun::toOrFrom($header['From']);
 | 
| 
 | 
 | 
                     // 抄送 ,密送
 | 
| 
 | 
 | 
                     $cc = [];
 | 
| 
 | 
 | 
                     $bcc = [];
 | 
| 
 | 
 | 
                     if($header['Cc']??''){
 | 
| 
 | 
 | 
                         $cc = MailFun::toOrFrom($header['Cc']);
 | 
| 
 | 
 | 
                     // 结束操作了
 | 
| 
 | 
 | 
                     if(redis()->get(SYNC_RUNNING_REDIS_KEY) == 'stop'){
 | 
| 
 | 
 | 
                         break;
 | 
| 
 | 
 | 
                     }
 | 
| 
 | 
 | 
                     if($header['Bcc']??''){
 | 
| 
 | 
 | 
                         $bcc = MailFun::toOrFrom($header['Bcc']);
 | 
| 
 | 
 | 
                     }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                     $data   =   [
 | 
| 
 | 
 | 
                         'msgno'   =>  $key,
 | 
| 
 | 
 | 
                         'uid'   =>  $result['UID'],
 | 
| 
 | 
 | 
                         'subject'   =>  $header['Subject']??'',
 | 
| 
 | 
 | 
                         'cc'    =>  $cc,
 | 
| 
 | 
 | 
                         'bcc'    =>  $bcc,
 | 
| 
 | 
 | 
                         'from'   =>  $header['From'][0]['email']??'',
 | 
| 
 | 
 | 
                         'from_name'   =>  $header['From'][0]['name']??'',
 | 
| 
 | 
 | 
                         'to'   =>  $header['To']?implode(',',array_column($header['To'],'email')):'',
 | 
| 
 | 
 | 
                         'to_name'   =>  json_encode($header['To']),
 | 
| 
 | 
 | 
                         'date'   =>  strtotime(is_array($header['Date']??'') ? $header['Date'][0] : $header['Date']??''),
 | 
| 
 | 
 | 
                         'message_id'   =>  $header['Message-ID']??'',
 | 
| 
 | 
 | 
                         'udate'   =>  strtotime($result['INTERNALDATE']),
 | 
| 
 | 
 | 
                         'size'   =>  $result['RFC822.SIZE']??0,
 | 
| 
 | 
 | 
                         'recent'   =>  in_array('recent',$result['FLAGS']) ? 1 : 0,
 | 
| 
 | 
 | 
                         'seen'   =>  in_array('seen',$result['FLAGS']) ? 1 : 0,
 | 
| 
 | 
 | 
                         'draft'   =>  in_array('draft',$result['FLAGS']) ? 1 : 0,
 | 
| 
 | 
 | 
                         'flagged'   =>  in_array('flagged',$result['FLAGS']) ? 1 : 0,
 | 
| 
 | 
 | 
                         'answered'   =>  in_array('answered',$result['FLAGS']) ? 1 : 0,
 | 
| 
 | 
 | 
                         'folder_id'   =>  $folder_id,
 | 
| 
 | 
 | 
                         'email_id'    =>  $email_id,
 | 
| 
 | 
 | 
                         'uuid'  =>  md5($email_id.$folder_id.$result['UID']),
 | 
| 
 | 
 | 
                         'is_file'  =>  MailFun::isFile($result['BODYSTRUCTURE']??'') ? 1: 0 //是否附件
 | 
| 
 | 
 | 
                     ];
 | 
| 
 | 
 | 
                     $data['date'] = $data['date'] ? : 0;
 | 
| 
 | 
 | 
                 }catch (\Throwable $e){
 | 
| 
 | 
 | 
                     logs(
 | 
| 
 | 
 | 
                         '邮件解析失败:'.PHP_EOL.$e->getMessage().PHP_EOL.print_r($result,true),
 | 
| 
 | 
 | 
                         LOG_PATH.'/imap/mail/'.$email_id.'/'.$result['UID'].'.log'
 | 
| 
 | 
 | 
                     );
 | 
| 
 | 
 | 
                     unset($results[$key]);
 | 
| 
 | 
 | 
                     continue;
 | 
| 
 | 
 | 
                 }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                 $results[$key]  =   $data;
 | 
| 
 | 
 | 
             }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
             // 保存数据,这里其实不用再次写循环的。我想写一个
 | 
| 
 | 
 | 
             $uuids = $db->all(listsSql::hasUuid(array_column($results,'uuid')));
 | 
| 
 | 
 | 
             $uuids = $uuids ? array_column($uuids,null,'uuid') : [];
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 //            $db->transaction();
 | 
| 
 | 
 | 
             foreach ($results as $insert){
 | 
| 
 | 
 | 
                 if(empty($uuids[$insert['uuid']])){
 | 
| 
 | 
 | 
                     // 新增
 | 
| 
 | 
 | 
                     try {
 | 
| 
 | 
 | 
                         $id = $db->insert(listsSql::$table,$insert);
 | 
| 
 | 
 | 
                         // 同步body内容
 | 
| 
 | 
 | 
                         redis()->rPush('sync_email_body', [
 | 
| 
 | 
 | 
                             'lists_id'  =>  $id,
 | 
| 
 | 
 | 
                             'email_id'  =>  $email_id,
 | 
| 
 | 
 | 
                             'folder_id'  =>  $folder_id,
 | 
| 
 | 
 | 
                             'folder'  =>  $folder,
 | 
| 
 | 
 | 
                             'uid'  =>  $insert['uid'],
 | 
| 
 | 
 | 
                         ]);
 | 
| 
 | 
 | 
                     }catch (\Throwable $e){
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                     }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                 }else{
 | 
| 
 | 
 | 
                     // 修改
 | 
| 
 | 
 | 
                     $db->update(
 | 
| 
 | 
 | 
                         listsSql::$table,
 | 
| 
 | 
 | 
                         $insert,
 | 
| 
 | 
 | 
                         dbWhere(['id'=>$uuids[$insert['uuid']]['id']])
 | 
| 
 | 
 | 
                     );
 | 
| 
 | 
 | 
                 }
 | 
| 
 | 
 | 
             }
 | 
| 
 | 
 | 
 //            $db->commit();
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
             // 更新数量
 | 
| 
 | 
 | 
             $db->update(
 | 
| 
 | 
 | 
                 folderSql::$table,
 | 
| 
 | 
 | 
                 ['last_sync_time' => time()],
 | 
| 
 | 
 | 
                 dbWhere(['id'=>$folder_id]),
 | 
| 
 | 
 | 
                 false
 | 
| 
 | 
 | 
             );
 | 
| 
 | 
 | 
             // 结束操作了
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
             if(redis()->get(SYNC_RUNNING_REDIS_KEY) != 'stop'){
 | 
| 
 | 
 | 
                 // 再次调用
 | 
| 
 | 
 | 
                 $this->syncMail($email_id,$folder_id,$folder,$db);
 | 
| 
 | 
 | 
             }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         // 更新数量
 | 
| 
 | 
 | 
         $db->update(
 | 
| 
 | 
 | 
             folderSql::$table,
 | 
| 
 | 
 | 
             ['last_sync_time' => time()],
 | 
| 
 | 
 | 
             dbWhere(['id'=>$folder_id]),
 | 
| 
 | 
 | 
             false
 | 
| 
 | 
 | 
         );
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         return true;
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
     }
 | 
...
 | 
...
 | 
 |