<?php namespace Controller\fob_ai; use Controller\Base; use Lib\Es\Es; use Lib\Mail\MailFun; use Lib\Verify; use Model\folderSql; use function Swoole\Coroutine\Http\request; /** * 黑格 fob 那边专用 业务 * 为定制逻辑 * @author:dc * @time 2024/7/18 11:40 * Class MailList * @package Controller\fob_ai */ class MailListV2Es extends Base { /** * @var Es */ public $es; public function __construct() { $this->es = \es(); } /** * 当前邮箱下指定的文件夹 * @param string $folder * @return array * @throws \Lib\Err * @author:dc * @time 2024/7/19 11:37 */ private function getFolderId(string $folder,$emails=[]){ if(!$emails){ $emails = $this->getEmails('id'); } $k = md5(json_encode($emails)); // 查询 文件夹 static $folderList; if(empty($folderList[$k])){ $folderList[$k] = db()->all(folderSql::all($emails)); } $folder_id = []; // 文件夹id if($folderList[$k]){ foreach ($folderList[$k] as $item){ if(folderAlias($item['folder']) == $folder){ $folder_id[] = $item['id']; } } } if(!$folder_id){ app()->e('folder_not_fount'); } return $folder_id; } /** * 处理like条件 * @param $str * @return string * @author:dc * @time 2024/9/4 11:14 */ private function getLikeStr($str){ if(str_starts_with($str, '^')){ return addslashes(mb_substr($str,1,99)).'%%'; } return '%%'.addslashes($str).'%%'; } /** * 邮件列表 * 接收参数 * page 分页 * limit 每页数量 * mail_id 指定邮件id * attachment 是否附件 * emails 邮箱 * folder 文件夹 * from_not_in 不在这些发件箱的邮件 * @throws \Lib\Err * @author:dc * @time 2024/7/18 11:40 */ public function lists(){ // 分页 页数 $page = app()->request('page',1,'intval') ? : 1; $limit = app()->request('limit',20,'intval') ? : 1; // 指定id $ids = app()->requestArr('mail_id'); foreach ($ids as $i=>$d){ if(!is_numeric($d)){ unset($ids[$i]); } } // 目录 $folder = app()->request('folder','收件箱'); // 只允许查询这里文件夹 if(!in_array($folder,['收件箱','发件箱','垃圾箱','星标邮件','预热收件箱','预热发件箱','自动回复收件箱','Starred','草稿箱'])){ app()->e('folder_not_fount'); } $where['is_hots'] = 0; if($folder=='星标邮件'||$folder=='Starred'){ $folder = '收件箱'; $where['flagged'] = 1; // 星标 unset($where['is_hots']); }elseif ($folder=='预热收件箱'){ $folder = '收件箱'; $where['is_hots'] = 1; }elseif ($folder=='预热发件箱'){ $folder = '发件箱'; $where['is_hots'] = 1; } elseif ($folder=='自动回复收件箱'){ $is_auto_inbox = 1; $folder = '收件箱'; $where['is_hots'] = 0; }elseif ($folder=='草稿箱'){ $folder = '草稿箱'; $where['is_hots'] = 0; } $seen = app()->request('seen',-1,'intval'); // 已读/未读 if(paramHas('seen')){ if(in_array($seen,[0,1])){ $where['seen'] = $seen; } } // 搜索标题 $keyword = app()->request('keyword'); if($keyword){ $where['subject'] = $keyword; } // 联系人 $address = app()->request('address'); if($address){ if(is_array($address)){ // 发贱人 if(Verify::sEmail($address['from']??'')){ if($folder=='发件箱'){ $where['to'] = $address['from']; }else{ $where['from.email'] = $address['from']; } } } } if($ids) $where['uuid'] = $ids; if(app()->request('attachment',0,'bool_Val')){ // 附件 $where['is_file'] = 1; //附件 } // 软删 $where['deleted'] = 0; /************ 2024-09-02 *************/ if($folder=='收件箱' && empty($where['flagged']) && !$ids) { if(!empty($is_auto_inbox)){ // 是否是自动收件箱 $where['is_auto'] = 1; }else{ $where['is_auto'] = 0; } } /************ 2024-09-02 *************/ $query = [ 'bool'=>[ 'must' => [] ] ]; foreach ($where as $k=>$v){ if($k=='subject'){ if($v){ $query['bool']['must'][] = [ 'query_string' => [ 'query'=>'"'.addcslashes($v,'"').'"', "default_field"=> "subject" ] ]; } }elseif (in_array($k,['from.email','to'])){ $query['bool']['must'][] = [ 'match_phrase' => [ $k=>$v ] ]; }else{ $query['bool']['must'][] = [ 'term' => [ $k=>$v ] ]; } } // 星标就不加文件夹赛选 if(empty($where['flagged'])){ $query['bool']['must'][] = $this->assignSql($folder); }else{ $query['bool']['must'][] = $this->assignSql('收件箱'); } if($folder=='收件箱'&&empty($is_auto_inbox)){ $from_not_in_like = app()->request('from_not_in_like'); if ($from_not_in_like) { $from_not_in_like = is_array($from_not_in_like) ? $from_not_in_like : [$from_not_in_like]; $notinquery = []; foreach ($from_not_in_like as $k => $sub) { if($sub){ $notinquery[] = ['match_phrase'=>['from.email'=>$sub]]; } } if($notinquery){ $query['bool']['must_not'] = $notinquery; } } } $result = $this->es->search(['query'=>$query],($page-1) * $limit,$limit,['udate'=>"desc"]); $total = $result['hits']['total']['value']??0; $lists = $result['hits']['hits']??[]; // map $lists = array_map(function ($v){ $v = $v['_source']; $v['id'] = $v['uuid']; $v['from_name'] = $v['from']['name']??''; $v['from'] = $v['from']['email']??''; $v['uuid'] = md5($v['email_id'].'-'.$v['folder_id'].'-'.$v['uid']); if(!empty($v['description'])){ $v['description'] = @html_entity_decode($v['description'], ENT_COMPAT, 'UTF-8'); } $v['to_name'] = @json_decode($v['to_name'],true); $v['to_name'] = $v['to_name']?:[]; if($v['to_name']){ if(!empty($v['to_name'][0]['email'])){ $v['to'] = $v['to_name'][0]['email']; } $v['to_name'] = MailFun::mb_coding($v['to_name'][0]['name']??''); } if(is_array($v['to_name'])){ $v['to_name'] = ''; } return $v; },$lists?:[]); app()->_json(listsPage($lists,$total,$page,$limit)); } private function assignSql($folder){ // 被分配的 $assign = app()->request('assign'); $query = []; $fids = []; if(!empty($assign['email_id'])){ // 此处请求中的 $email = array_values(array_intersect($assign['email_id'],$this->getEmails('id'))); if($email){ $fids = $this->getFolderId($folder,$email); // 有目录id和from if($fids && !empty($assign['from'])){ if($folder=='发件箱'){ $query = [ 'bool' => [ 'must' => [ ['terms'=>['folder_id'=>$fids]], ['query_string'=>[ 'query'=> implode(' OR ',$assign['from']), 'default_field'=>'to' ]] ] ] ]; }else{ $query = [ 'bool' => [ 'must' => [ ['terms'=>['folder_id'=>$fids]], ['query_string'=>[ 'query'=>'from.email:('.implode(' OR ',array_map(function($e){ return '"'.$e.'"'; },$assign['from'])).')'] ], ] ] ]; } } } // 返回 不在assign中的目录 $afids = array_values(array_diff($this->getFolderId($folder),$fids)); if($query && $afids){ return [ 'bool' => [ 'should' =>[ ["bool" =>['must' => [$query]]], ["bool" =>['must' => [['terms'=>['folder_id'=>$afids]]]]] ] ] ]; }else if($afids){ return ['terms'=>['folder_id'=>$afids]]; }else if($query&&!$afids){ return $query; } return ['term'=>['folder_id'=> -1]]; } return ['terms'=>['folder_id'=> $this->getFolderId($folder)]]; } private function assignSql3($folder){ // 被分配的 $assign = app()->request('assign'); if(!empty($assign['email_id'])){ // 此处请求中的 $email = array_diff($this->getEmails('id'),$assign['email_id']); if($email){ $fids = $this->getFolderId($folder,$email); // 有目录id和from if($fids){ return ['terms'=>['folder_id'=>$fids]]; } } return ['term'=>['folder_id'=>-1]]; } return ['terms'=>['folder_id'=> $this->getFolderId($folder)]]; } public function count(){ if(!$this->getEmails('id')){ app()->e('email_request_required'); } $body = []; $body['query'] = [ 'bool'=>[ 'must'=>[ ['term'=>['deleted'=>0]] ] ] ]; // 时间 必须是数组 $udate = app()->request('udate'); if($udate && is_array($udate) && count($udate) == 2){ $udate = array_values($udate); $udate = array_map(function ($v){ if(is_numeric($v)) return $v; return strtotime($v); },$udate); // 时间范围搜索 $body['query']['bool']['must'][] = [ 'range' => [ 'udate' => [ 'gte' => $udate[0], // 大于等于开始日期 'lte' => $udate[1] // 小于等于结束日期 ] ] ]; } // show_count_filed $show_count_filed = app()->requestArr('show_count_filed',['inbox', 'send', 'unseen', 'flagged', 'junk', 'hot_inbox', 'hot_send']); // 发件箱 if(in_array('hot_send',$show_count_filed)){ // 预热发件箱 $fCount = $this->countHot($body,'发件箱'); } // 预热收件箱 if(in_array('hot_inbox',$show_count_filed)) { $sCount = $this->countHot($body,'收件箱'); } if(in_array('send',$show_count_filed)) { $faCount = $this->countMail($body,'发件箱'); } // 垃圾箱 if(in_array('junk',$show_count_filed)) { $lajiCount = $this->countMail($body,'垃圾箱'); } // 收件箱 if(in_array('inbox',$show_count_filed) || in_array('replied',$show_count_filed)) { $repliedCount = $shouCount = $this->countMail($body,'收件箱'); } // 未读 if(in_array('unseen',$show_count_filed)) { $seenCount = $this->countMail($body,'收件箱', 0); } // 星标 if(in_array('flagged',$show_count_filed)) { $flaggedCount = $this->countFlagged($body); } $data = []; if(isset($shouCount)) $data['inbox'] = $shouCount; if(isset($repliedCount)) $data['replied'] = $repliedCount; if(isset($faCount)) $data['send'] = $faCount; if(isset($seenCount)) $data['unseen'] = $seenCount; if(isset($flaggedCount)) $data['flagged'] = $flaggedCount; if(isset($lajiCount)) $data['junk'] = $lajiCount; if(isset($sCount)) $data['hot_inbox'] = $sCount; if(isset($fCount)) $data['hot_send'] = $fCount; app()->_json($data); } /** * 统计预热邮件 * @param $body * @param $folder * @author:dc * @time 2025/3/6 15:24 */ private function countHot($body,$folder){ $body['query']['bool']['must'][] = ['term'=>['is_hots'=>1]]; $body['query']['bool']['must'][] = $this->assignSql3($folder); return $this->es->count($body); } private function countMail($body,$folder,$seen=null){ if($folder == '收件箱'){ $body['query']['bool']['must'][] = ['term'=>['is_auto'=>0]]; $from_not_in_like = app()->request('from_not_in_like'); if ($from_not_in_like) { $from_not_in_like = is_array($from_not_in_like) ? $from_not_in_like : [$from_not_in_like]; $notinquery = []; foreach ($from_not_in_like as $k => $sub) { if($sub){ $notinquery[] = ['match_phrase'=>['from.email'=>$sub]]; } } if($notinquery){ $body['query']['bool']['must_not'] = $notinquery; } } } if($seen!==null){ $body['query']['bool']['must'][] = ['term'=>['seen'=>$seen]]; } $body['query']['bool']['must'][] = ['term'=>['is_hots'=>0]]; $body['query']['bool']['must'][] = $this->assignSql($folder); return $this->es->count($body); } /** * 统计星标 * @param $body * @return int|mixed * @author:dc * @time 2025/3/6 16:01 */ private function countFlagged($body){ $body['query']['bool']['must'][] = ['term'=>['flagged'=>1]]; $body['query']['bool']['must'][] = $this->assignSql('收件箱'); return $this->es->count($body); } }