| 
...
 | 
...
 | 
@@ -3,6 +3,8 @@ | 
| 
 | 
 | 
 namespace Lib\Mail;
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 use Lib\DbPool;
 | 
| 
 | 
 | 
 use Model\folderSql;
 | 
| 
 | 
 | 
 use Model\listsSql;
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 /**
 | 
| 
 | 
 | 
  * 操作邮件
 | 
| 
...
 | 
...
 | 
@@ -59,11 +61,14 @@ class Mail { | 
| 
 | 
 | 
             $pid = 0;
 | 
| 
 | 
 | 
             foreach ($folder['id'] as $k=>$item){
 | 
| 
 | 
 | 
                 // 插入到数据库
 | 
| 
 | 
 | 
                 $pid = Folder::_insert(
 | 
| 
 | 
 | 
                     $this->client->getId(),
 | 
| 
 | 
 | 
                     $folder['name'][$k],
 | 
| 
 | 
 | 
                     $item,
 | 
| 
 | 
 | 
                     $pid
 | 
| 
 | 
 | 
                 $pid = $db->insert(
 | 
| 
 | 
 | 
                     folderSql::$table,
 | 
| 
 | 
 | 
                     [
 | 
| 
 | 
 | 
                         'email_id' => $this->client->getId(),
 | 
| 
 | 
 | 
                         'folder' => $folder['name'][$k],
 | 
| 
 | 
 | 
                         'origin_folder' => $item,
 | 
| 
 | 
 | 
                         'pid' => $pid
 | 
| 
 | 
 | 
                     ]
 | 
| 
 | 
 | 
                 );
 | 
| 
 | 
 | 
             }
 | 
| 
 | 
 | 
         }
 | 
| 
...
 | 
...
 | 
@@ -74,32 +79,35 @@ class Mail { | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
     /**
 | 
| 
 | 
 | 
      * 同步邮件
 | 
| 
 | 
 | 
      * @param $email
 | 
| 
 | 
 | 
      * @param $email_id
 | 
| 
 | 
 | 
      * @param $folder_id
 | 
| 
 | 
 | 
      * @param string $folder
 | 
| 
 | 
 | 
      * @param null|DbPool $db
 | 
| 
 | 
 | 
      * @return bool
 | 
| 
 | 
 | 
      * @throws \Exception
 | 
| 
 | 
 | 
      * @author:dc
 | 
| 
 | 
 | 
      * @time 2023/2/6 15:04
 | 
| 
 | 
 | 
      * @time 2023/2/18 9:54
 | 
| 
 | 
 | 
      */
 | 
| 
 | 
 | 
     public static function syncMail($email,$email_id,$folder_id,$folder='INBOX'):bool {
 | 
| 
 | 
 | 
     public function syncMail($email_id,$folder_id,$folder='INBOX',$db = null):bool {
 | 
| 
 | 
 | 
         $db = $db ? $db : db();
 | 
| 
 | 
 | 
         // 选择文件夹
 | 
| 
 | 
 | 
         try {
 | 
| 
 | 
 | 
             $status =   static::$client[$email]->selectFolder($folder);
 | 
| 
 | 
 | 
         }catch (\Throwable $e){
 | 
| 
 | 
 | 
             Log::error($email.' 选择文件夹错误:'.$e->getMessage());
 | 
| 
 | 
 | 
             return false;
 | 
| 
 | 
 | 
         }
 | 
| 
 | 
 | 
         $status =   $this->client->selectFolder($folder);
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         // 是否有邮件
 | 
| 
 | 
 | 
         if (!isset($status['EXISTS']) || !$status['EXISTS']){
 | 
| 
 | 
 | 
             return true;
 | 
| 
 | 
 | 
         }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         // 更新数量
 | 
| 
 | 
 | 
         Folder::_updateNum($folder_id,$status['EXISTS'], $status['UNSEEN']??null);
 | 
| 
 | 
 | 
         $db->update(
 | 
| 
 | 
 | 
             folderSql::$table,
 | 
| 
 | 
 | 
             ['exsts'=>$status['EXISTS'],'unseen'=>$status['UNSEEN']??0],
 | 
| 
 | 
 | 
             dbWhere(['id'=>$folder_id])
 | 
| 
 | 
 | 
         );
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         // 最后拉取的时间,如果是第一次
 | 
| 
 | 
 | 
         $lastMsgno   =   EList::_lastMsgno($email_id, $folder_id);
 | 
| 
 | 
 | 
         // 最后拉取的msgno
 | 
| 
 | 
 | 
         $lastMsgno   =   $db->value(listsSql::lastMsgno($email_id,$folder_id));
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         $nu = 20;
 | 
| 
 | 
 | 
 
 | 
| 
...
 | 
...
 | 
@@ -118,29 +126,19 @@ class Mail { | 
| 
 | 
 | 
         }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         SYNCEMAILLIST:
 | 
| 
 | 
 | 
         // 是否有id
 | 
| 
 | 
 | 
         $dataids = EList::_getIdsByMsgno($email_id,$folder_id,$msgno);
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         // 循环
 | 
| 
 | 
 | 
         $results = static::$client[$email]->fetchHeader($msgno);
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         $results = $this->client->fetchHeader($msgno);
 | 
| 
 | 
 | 
         if($results){
 | 
| 
 | 
 | 
             DB::beginTransaction();
 | 
| 
 | 
 | 
             // 批量插入
 | 
| 
 | 
 | 
             foreach ($results as $key=>$result){
 | 
| 
 | 
 | 
                 if($key == $status['EXISTS']){
 | 
| 
 | 
 | 
                     $end = true;
 | 
| 
 | 
 | 
                 }
 | 
| 
 | 
 | 
                 $header = &$result['HEADER.FIELDS'];
 | 
| 
 | 
 | 
                 $header = $result['HEADER.FIELDS'];
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                 foreach ($result['FLAGS'] as $k=>$FLAG){
 | 
| 
 | 
 | 
                     $result['FLAGS'][$k] = strtolower(str_replace('\\','',$FLAG));
 | 
| 
 | 
 | 
                 }
 | 
| 
 | 
 | 
                 try {
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                     $file_header = &$result['BODYSTRUCTURE'];
 | 
| 
 | 
 | 
                     $file_header = $result['BODYSTRUCTURE'];
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                     // 没有收件人
 | 
| 
 | 
 | 
                     if(!empty($header['To'])){
 | 
| 
...
 | 
...
 | 
@@ -149,11 +147,9 @@ class Mail { | 
| 
 | 
 | 
                         $header['To'] = [];
 | 
| 
 | 
 | 
                     }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                     $header['From'] = MailFun::toOrFrom($header['From']);
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                     $data   =   [
 | 
| 
 | 
 | 
                         'id'    =>  $dataids[$key]??0,
 | 
| 
 | 
 | 
                         'msgno'   =>  $key,
 | 
| 
 | 
 | 
                         'uid'   =>  $result['UID'],
 | 
| 
 | 
 | 
                         'subject'   =>  $header['Subject'],
 | 
| 
...
 | 
...
 | 
@@ -166,7 +162,7 @@ class Mail { | 
| 
 | 
 | 
                         'date'   =>  isset($header['Date'])&&$header['Date'] ? strtotime(is_array($header['Date']) ? $header['Date'][0] : $header['Date']) : strtotime($result['INTERNALDATE']),
 | 
| 
 | 
 | 
                         'message_id'   =>  $header['Message-ID']??'',
 | 
| 
 | 
 | 
                         'udate'   =>  strtotime($result['INTERNALDATE']),
 | 
| 
 | 
 | 
 //                      'size'   =>  $result['RFC822.SIZE'],
 | 
| 
 | 
 | 
                         'size'   =>  $result['RFC822.SIZE']??0,
 | 
| 
 | 
 | 
                         'recent'   =>  in_array('recent',$result['FLAGS']),
 | 
| 
 | 
 | 
                         'seen'   =>  in_array('seen',$result['FLAGS']),
 | 
| 
 | 
 | 
                         'draft'   =>  in_array('draft',$result['FLAGS']),
 | 
| 
...
 | 
...
 | 
@@ -174,29 +170,50 @@ class Mail { | 
| 
 | 
 | 
                         'answered'   =>  in_array('answered',$result['FLAGS']),
 | 
| 
 | 
 | 
                         'folder_id'   =>  $folder_id,
 | 
| 
 | 
 | 
                         'email_id'    =>  $email_id,
 | 
| 
 | 
 | 
                         'uuid'  =>  $email_id.$folder_id.$result['UID'],
 | 
| 
 | 
 | 
                         'uuid'  =>  md5($email_id.$folder_id.$result['UID']),
 | 
| 
 | 
 | 
                         'is_file'  =>  MailFun::isFile($file_header[$key]['BODYSTRUCTURE']??[]) //是否附件
 | 
| 
 | 
 | 
                     ];
 | 
| 
 | 
 | 
                 }catch (\Throwable $e){
 | 
| 
 | 
 | 
                     Log::error('邮件解析失败:'.$e->getMessage().print_r($result,true));
 | 
| 
 | 
 | 
                     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;
 | 
| 
 | 
 | 
             }
 | 
| 
 | 
 | 
             EList::_insertAll(array_values($results));
 | 
| 
 | 
 | 
             // 提交
 | 
| 
 | 
 | 
             DB::commit();
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
             // 保存数据,这里其实不用再次写循环的。我想写一个
 | 
| 
 | 
 | 
             $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']])){
 | 
| 
 | 
 | 
                     // 新增
 | 
| 
 | 
 | 
                     $db->insert(listsSql::$table,$insert);
 | 
| 
 | 
 | 
                 }else{
 | 
| 
 | 
 | 
                     // 修改
 | 
| 
 | 
 | 
                     $db->update(
 | 
| 
 | 
 | 
                         listsSql::$table,
 | 
| 
 | 
 | 
                         $insert,
 | 
| 
 | 
 | 
                         dbWhere(['id'=>$uuids[$insert['uuid']]['id']])
 | 
| 
 | 
 | 
                     );
 | 
| 
 | 
 | 
                 }
 | 
| 
 | 
 | 
             }
 | 
| 
 | 
 | 
             $db->commit();
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
             // 结束操作了
 | 
| 
 | 
 | 
         }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         // 再次调用
 | 
| 
 | 
 | 
         Mail::syncMail($email,$email_id,$folder_id,$folder);
 | 
| 
 | 
 | 
         $this->syncMail($email_id,$folder_id,$folder,$db);
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         return true;
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
     }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
...
 | 
...
 | 
 |