|
|
<?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 那边专用 业务 ai 邮件 第二个版本
|
|
|
* 为定制逻辑
|
|
|
* @author:dc
|
|
|
* @time 2024/7/18 11:40
|
|
|
* Class MailList
|
|
|
* @package Controller\fob_ai
|
|
|
*/
|
|
|
class MailListV2Es2 extends Base {
|
|
|
|
|
|
/**
|
|
|
* @var Es
|
|
|
*/
|
|
|
public $es;
|
|
|
|
|
|
public function __construct()
|
|
|
{
|
|
|
$this->es = \es('email_lists');
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 当前邮箱下指定的文件夹
|
|
|
* @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;
|
|
|
// 项目id
|
|
|
$where['postid'] = intval(app()->request('postid'))?:-1;
|
|
|
$where['folder_as_int'] = 404; // 搜索那个文件夹
|
|
|
if($folder=='收件箱'){
|
|
|
$where['is_hots'] = 0;
|
|
|
$where['is_auto'] = 0;
|
|
|
$where['folder_as_int'] = folder2int($folder);
|
|
|
}elseif($folder=='发件箱'){
|
|
|
$where['is_hots'] = 0;
|
|
|
$where['folder_as_int'] = folder2int($folder);
|
|
|
}
|
|
|
else if($folder=='星标邮件'||$folder=='Starred'){
|
|
|
$where['flagged'] = 1; // 星标
|
|
|
$where['folder_as_int'] = [1,2,3,4,5]; // 所有
|
|
|
}elseif ($folder=='预热收件箱'){
|
|
|
$where['is_hots'] = 1;
|
|
|
$where['folder_as_int'] = folder2int('收件箱');
|
|
|
}elseif ($folder=='预热发件箱'){
|
|
|
$where['is_hots'] = 1;
|
|
|
$where['folder_as_int'] = folder2int('发件箱');
|
|
|
} elseif ($folder=='自动回复收件箱'){
|
|
|
$where['is_auto'] = 1;
|
|
|
$where['folder_as_int'] = folder2int('收件箱');
|
|
|
}elseif ($folder=='草稿箱' || $folder=='垃圾箱'){
|
|
|
$where['folder_as_int'] = folder2int($folder); // 所有
|
|
|
}
|
|
|
|
|
|
// 已读/未读
|
|
|
if(paramHas('seen')){
|
|
|
$seen = app()->request('seen',-1,'intval');
|
|
|
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(str_contains($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;
|
|
|
|
|
|
$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'][] = [
|
|
|
is_array($v)?'terms':'term' => [
|
|
|
$k=>$v
|
|
|
]
|
|
|
];
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if($assign = $this->assignSql($folder)){
|
|
|
$query['bool']['must'][] = $assign;
|
|
|
}
|
|
|
|
|
|
|
|
|
if(str_contains($folder, '收件箱') &&empty($where['is_hots']) &&empty($where['is_auto']) && empty($where['flagged'])){
|
|
|
$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'=>['constant_score'=>['filter'=>$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'] = '';
|
|
|
}
|
|
|
// 邮件箱
|
|
|
$v['folder_name'] = db()->cache(86400)->value(folderSql::first($v['folder_id'],'folder'));
|
|
|
|
|
|
// 暂时这样吧
|
|
|
$info = db()->first(\Model\listsSql::first('id = '.$v['id'],'`flagged`,`seen`,`deleted`'));
|
|
|
if($info){
|
|
|
$v['flagged'] = $info['flagged'];
|
|
|
$v['seen'] = $info['seen'];
|
|
|
$v['deleted'] = $info['deleted'];
|
|
|
}
|
|
|
|
|
|
// 手动触发同步es
|
|
|
redis()->rPush('sync_to_es',$v['id']);
|
|
|
|
|
|
return $v;
|
|
|
},$lists?:[]);
|
|
|
|
|
|
$lists = array_filter($lists,function ($v){
|
|
|
if($v['deleted']){
|
|
|
return false;
|
|
|
}
|
|
|
return true;
|
|
|
});
|
|
|
|
|
|
|
|
|
app()->_json(listsPage($lists,$total,$page,$limit));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private function assignSql($folder){
|
|
|
// 被分配的
|
|
|
$assign = app()->request('assign');
|
|
|
// 说明是子账号
|
|
|
if(!empty($assign['assign'])){
|
|
|
return [
|
|
|
'bool' => [
|
|
|
'should' =>[
|
|
|
[
|
|
|
'query_string'=>[
|
|
|
'query'=>(str_contains($folder, '发件箱')?'to':'from.email').':('.implode(' OR ',array_map(function($e){return '"'.$e.'"';},$assign['from'])).')'
|
|
|
]
|
|
|
],
|
|
|
[
|
|
|
'terms'=>[
|
|
|
'email_id'=>$assign['email_id']
|
|
|
]
|
|
|
]
|
|
|
]
|
|
|
]
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
return [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
...
|
...
|
|