作者 邓超

预热 逻辑

  1 +<?php
  2 +
  3 +include_once "../vendor/autoload.php";
  4 +
  5 +/**
  6 + * 只有黑格 在使用此业务
  7 + * 预热 邮件 数据处理
  8 + * 主要功能:
  9 + * 在 https://fob.ai.cc/api/mail/preheat 拉取 预热邮件
  10 + * 在 https://oa.shopk.com/api/mail/preheat 拉取 预热邮件
  11 + * 在 lists表中找到这些邮箱发出的邮件
  12 + * 然后在 hot_mail表中记录起来
  13 + * @author:dc
  14 + * @time 2024/7/18 13:50
  15 + * Class HotMail
  16 + */
  17 +class HotMail {
  18 +
  19 + public function __construct(){$this->start();}
  20 +
  21 + /**
  22 + * shopk那边的预热邮箱
  23 + * @var array
  24 + */
  25 + private $shopkHotEmail = [];
  26 +
  27 + /**
  28 + * @author:dc
  29 + * @time 2024/7/18 14:04
  30 + */
  31 + private function start(){
  32 + _echo('启动预热邮件处理 '.getmypid());
  33 +
  34 + $this->shopkHotEmail = $this->getHotEmail();
  35 + if($this->shopkHotEmail){
  36 + array_map([$this,'moveMail'],$this->getFobHotEmail());
  37 + }
  38 +
  39 + }
  40 +
  41 + /**
  42 + * 邮件检查及移动
  43 + * @param string $email 检查的邮箱
  44 + * @author:dc
  45 + * @time 2024/7/18 14:06
  46 + */
  47 + private function moveMail(string $email){
  48 + // 读取邮箱在表里的id
  49 + $email_id = db()->value(sprintf("select `id` from `%s` where `email` = '%s' limit 1",\Model\emailSql::$table, $email));
  50 +
  51 + if($email_id){
  52 + $this->findFolder($email_id,'收件箱','s');
  53 + $this->findFolder($email_id,'发件箱','f');
  54 + }
  55 +
  56 + return true;
  57 + }
  58 +
  59 + /**
  60 + * 查找文件夹
  61 + * @param int $email_id 邮箱id
  62 + * @param string $folder 那个文件夹
  63 + * @author:dc
  64 + * @time 2024/7/18 15:10
  65 + */
  66 + private function findFolder(int $email_id, string $folder,string $type){
  67 + // 查询 文件夹
  68 + $folders = db()->all(\Model\folderSql::all($email_id,['id','folder']));
  69 +
  70 + foreach ($folders as $f){
  71 + if(folderAlias($f['folder']) == $folder){
  72 + // 最后记录的id
  73 + $last_id = db()->value('select max(`lists_id`) from `fob_hot_mail` where `email_id` = '.$email_id.' limit 1');
  74 + $this->findList(new Data($email_id,$f['id'],$type,$last_id));
  75 + }
  76 + }
  77 + return true;
  78 + }
  79 +
  80 + /**
  81 + * 查找 邮件
  82 + * @author:dc
  83 + * @time 2024/7/18 15:11
  84 + */
  85 + private function findList(Data $data, int $p = 1){
  86 + $lists = db()->all(
  87 + sprintf(
  88 + "select `id`,`folder_id`,`email_id`,`from` from `lists` where `id` > %d and `email_id` = %d and `folder_id` = %d and (select count(*) from `fob_hot_mail` where `lists`.`id` = `fob_hot_mail`.`lists_id`) > 0 limit 1000 offset ".(($p-1)*1000),
  89 + $data->last_id,
  90 + $data->email_id,
  91 + $data->folder_id
  92 + )
  93 + );
  94 + if($lists){
  95 + // 处理数据
  96 + foreach ($lists as $list){
  97 + $list['folder'] = $data->type;
  98 + $this->insertData($list);
  99 + }
  100 + $lists = null;
  101 + $list = null;
  102 + // 再次查找
  103 + $this->findList($data,$p + 1);
  104 + }
  105 + return true;
  106 + }
  107 +
  108 + /**
  109 + * 插入数据
  110 + * @param array $data
  111 + * @author:dc
  112 + * @time 2024/7/18 15:25
  113 + */
  114 + private function insertData(array $data){
  115 + // 是预热 邮箱发来的邮件
  116 + if(in_array($data['from'],$this->shopkHotEmail)){
  117 + // 不存在 数据
  118 + if(db()->count("select count(*) from `fob_hot_mail` where `lists_id` = ".$data['id']) == 0){
  119 + db()->insert('fob_hot_mail',[
  120 + 'lists_id' => $data['id'],
  121 + 'email_id' => $data['email_id'],
  122 + 'folder_id' => $data['folder_id'],
  123 + 'folder' => $data['folder']
  124 + ],false);
  125 + }
  126 + }
  127 + return true;
  128 + }
  129 +
  130 +
  131 + /**
  132 + * 获取预热邮箱
  133 + * shopk的
  134 + * @return array
  135 + * @author:dc
  136 + * @time 2024/7/18 13:58
  137 + */
  138 + private function getHotEmail():array {
  139 + $data = @file_get_contents('https://oa.shopk.com/api/mail/preheat');
  140 +
  141 + if($data){
  142 + $data = @json_decode($data,1);
  143 + if($data && isset($data['data']) && is_array($data['data'])){
  144 + return $data['data'];
  145 + }
  146 + }
  147 + logs('shopk 获取预热邮箱错误:'.print_r($data,1),'get_hot_oa_email.error.log')->write();
  148 + return [];
  149 + }
  150 +
  151 + /**
  152 + * fob黑格的预热邮箱
  153 + * @author:dc
  154 + * @time 2024/7/18 14:21
  155 + */
  156 + private function getFobHotEmail(){
  157 + $data = @file_get_contents('https://fob.ai.cc/api/mail/preheat/'.md5('aicc.'.date('ymdh')));
  158 + print_r($data);
  159 + if($data){
  160 + $data = @json_decode($data,1);
  161 + if($data && isset($data['data']) && is_array($data['data'])){
  162 + return $data['data'];
  163 + }
  164 + }
  165 + logs('fob 获取预热邮箱错误:'.print_r($data,1),'get_hot_fob_email.error.log')->write();
  166 + }
  167 +
  168 +
  169 +
  170 +}
  171 +
  172 +
  173 +class Data {
  174 +
  175 + public int $email_id = 0;
  176 + public int $folder_id = 0;
  177 + public string $type = '';
  178 + public int $last_id = 0;
  179 +
  180 + public function __construct(int $email_id,int $folder_id, string $type,int $last_id)
  181 + {
  182 + $this->email_id = $email_id;
  183 + $this->folder_id = $folder_id;
  184 + $this->type = $type;
  185 + $this->last_id = $last_id;
  186 + }
  187 +
  188 +}
  189 +
  190 +
  191 +new HotMail();
  1 +<?php
  2 +
  3 +namespace Controller\fob_ai;
  4 +
  5 +
  6 +
  7 +use Controller\Base;
  8 +use Model\folderSql;
  9 +
  10 +/**
  11 + * 黑格 fob 那边专用 业务
  12 + * 为定制逻辑
  13 + * @author:dc
  14 + * @time 2024/7/18 11:40
  15 + * Class MailList
  16 + * @package Controller\fob_ai
  17 + */
  18 +class MailList extends Base {
  19 +
  20 +
  21 + /**
  22 + * 邮件列表
  23 + * @throws \Lib\Err
  24 + * @author:dc
  25 + * @time 2024/7/18 11:40
  26 + */
  27 + public function lists(){
  28 +
  29 + // 分页 页数
  30 + $page = app()->request('page',1,'intval');
  31 + $page = $page ? $page : 1;
  32 +
  33 + $limit = app()->request('limit',20,'intval');
  34 + $limit = $limit ? $limit : 1;
  35 +
  36 + // 指定id
  37 + $ids = app()->request('mail_id');
  38 + $ids = is_array($ids) ? $ids : [$ids];
  39 + foreach ($ids as $i=>$d){
  40 + if(!is_numeric($d)){
  41 + unset($ids[$i]);
  42 + }
  43 + }
  44 +
  45 + // 附件
  46 + $attachment = app()->request('attachment',0,'bool_Val');
  47 +
  48 + $deleted = 0;
  49 +
  50 + $where = ['email_id'=>$this->getEmails('id')];
  51 +
  52 + // 目录
  53 + $folder = app()->request('folder','收件箱');
  54 + // 只允许查询这里文件夹
  55 + if(in_array($folder,['收件箱','发件箱','垃圾箱','星标邮件','预热收件箱','预热发件箱']))
  56 + // 查询 文件夹
  57 + $folderList = db()->all(folderSql::all($where['email_id']));
  58 + $folder_id = [];
  59 + // 文件夹id
  60 + if($folderList){
  61 + foreach ($folderList as $item){
  62 + if(
  63 + // 数组文件夹
  64 + (is_array($folder) && in_array($item['folder'],$folder))
  65 + || $item['folder'] == $folder
  66 + ){
  67 + $folder_id[] = $item['id'];
  68 + }
  69 + }
  70 + }
  71 + if(!$folder_id){
  72 + app()->e('folder_not_fount');
  73 + }
  74 +
  75 + //目录
  76 + $where['folder_id'] = $folder_id;
  77 + if($ids) $where['id'] = $ids;
  78 +
  79 + if(paramHas('attachment')){
  80 + $where['is_file'] = $attachment ? 1 : 0; //附件
  81 + }
  82 +
  83 +
  84 + // 软删
  85 + $where['deleted'] = $deleted;
  86 + // 已读/未读
  87 + if(paramHas('seen')){
  88 + if(in_array($seen,[0,1])){
  89 + $where['seen'] = $seen;
  90 + }
  91 + }
  92 +
  93 + $where['_'] = [];
  94 + // 搜索关键字
  95 + $keyword = app()->request('keyword','',['htmlspecialchars','addslashes']);
  96 + if($keyword){
  97 + $where['_'][] = '`subject` like "%'.$keyword.'%"';
  98 + }
  99 +
  100 + // 那个发的
  101 + $address = app()->request('address');
  102 + if($address){
  103 + if(is_array($address)){
  104 + // 发贱人
  105 + if(Verify::sEmail($address['from']??'')){
  106 + $where['from'] = $address['from'];
  107 + }
  108 + // 收件人
  109 + if(Verify::sEmail($address['to']??'')){
  110 + $where['_'][] = '`to_name` like "%'.$address.'%"';
  111 + }
  112 +
  113 + }else if(Verify::sEmail($address)){
  114 + // 收件人/发件人
  115 + $where['_'][] = '(`from` = "'.$address.'" or `to_name` like "%'.$address.'%")';
  116 + }
  117 + }
  118 + // from 搜索收件人
  119 + if(app()->requestHas('from')){
  120 + // 如果是发件箱
  121 + if($folder == '发件箱'){
  122 + $where['to'] = app()->request('from');
  123 + if(!$where['to']){
  124 + // 不让查询数据
  125 + $where['id'] = 0;
  126 + }
  127 + }else{
  128 + $where['from'] = app()->request('from');
  129 + if(!$where['from']){
  130 + // 不让查询数据
  131 + $where['id'] = 0;
  132 + }
  133 + }
  134 +
  135 +
  136 + }
  137 +
  138 +
  139 + // 回复
  140 + if (paramHas('answered')){
  141 + $where['answered'] = app()->request('answered',0,'bool_Val')?1:0;
  142 + }
  143 +
  144 + // 这个主要是来筛选 是否是自己发送的
  145 + $fromto = app()->request('formorto');
  146 + if($fromto=='from'){
  147 + $where['from'] = $this->getEmails('email');
  148 + }elseif ($fromto=='to'){
  149 + $where['from.notin'] = $this->getEmails('email');
  150 + }
  151 +
  152 + /**
  153 + * 不查询哪些发件人的邮件
  154 + */
  155 + $form_not_in = app()->request('from_not_in');
  156 + if($form_not_in){
  157 + $form_not_in = is_array($form_not_in) ? $form_not_in : [$form_not_in];
  158 + $form_not_in = array_filter($form_not_in,function ($v){
  159 + if(is_string($v) && Verify::sEmail($v)){
  160 + return true;
  161 + }
  162 + return false;
  163 + });
  164 + if($form_not_in){
  165 + if(isset($where['from.notin'])){
  166 + $where['from.notin'] = array_merge($where['from.notin'],$form_not_in);
  167 + }else{
  168 + $where['from.notin'] = $form_not_in;
  169 + }
  170 +
  171 + }
  172 + }
  173 + if(!empty($where['from.notin'])){
  174 + $where['from.notin'] = array_unique($where['from.notin']);
  175 + }
  176 +
  177 +
  178 +
  179 + $lists = db()->all(
  180 + listsSql::lists(
  181 + dbWhere($where),
  182 + $page,
  183 + $limit
  184 + )
  185 + );
  186 +
  187 + // map
  188 + $lists = array_map(function ($v){
  189 + $v['uuid'] = get_email_uuid($v['subject'],$v['udate'],$v['from'],$v['to'],$v['size']);
  190 + if(!empty($v['description'])){
  191 + $v['description'] = @html_entity_decode($v['description'], ENT_COMPAT, 'UTF-8');
  192 + }
  193 + $v['to_name'] = @json_decode($v['to_name'],true);
  194 + $v['to_name'] = $v['to_name']?:[];
  195 + if($v['to_name']){
  196 + if(!empty($v['to_name'][0]['email'])){
  197 + $v['to'] = $v['to_name'][0]['email'];
  198 + }
  199 + $v['to_name'] = $v['to_name'][0]['name']??'';
  200 + }
  201 + if(is_array($v['to_name'])){
  202 + $v['to_name'] = '';
  203 + }
  204 + return $v;
  205 + },$lists);
  206 +
  207 + // 总数
  208 + $total = db()->count(
  209 + listsSql::listCount(dbWhere($where))
  210 + );
  211 +
  212 + app()->_json(listsPage($lists,$total,$page,$limit));
  213 +
  214 + }
  215 +
  216 +
  217 +
  218 +}
  219 +
  220 +
  221 +
  222 +
  223 +
  224 +
  225 +
  226 +
  227 +
  228 +
  229 +
  230 +
  231 +
  232 +
@@ -62,7 +62,7 @@ function logs($message,$filename=null){ @@ -62,7 +62,7 @@ function logs($message,$filename=null){
62 } 62 }
63 // $a = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT,4); 63 // $a = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT,4);
64 // $message .= print_r($a,1); 64 // $message .= print_r($a,1);
65 - \Lib\Log::append($message, $filename); 65 + return \Lib\Log::append($message, $filename);
66 66
67 } 67 }
68 68
@@ -16,12 +16,12 @@ class Log { @@ -16,12 +16,12 @@ class Log {
16 /** 16 /**
17 * @var array 17 * @var array
18 */ 18 */
19 - public array $filename = []; 19 + protected array $filename = [];
20 20
21 /** 21 /**
22 * @var array 22 * @var array
23 */ 23 */
24 - public array $message = []; 24 + protected array $message = [];
25 25
26 /** 26 /**
27 * @var self 27 * @var self
@@ -39,8 +39,10 @@ class Log { @@ -39,8 +39,10 @@ class Log {
39 /** 39 /**
40 * 追加日志内容 40 * 追加日志内容
41 * @param string $message 41 * @param string $message
  42 + * @param null $filename
  43 + * @return Log
42 * @author:dc 44 * @author:dc
43 - * @time 2023/3/14 10:45 45 + * @time 2024/7/18 14:12
44 */ 46 */
45 public static function append(string $message, $filename = null){ 47 public static function append(string $message, $filename = null){
46 48
@@ -49,7 +51,7 @@ class Log { @@ -49,7 +51,7 @@ class Log {
49 } 51 }
50 52
51 self::getInstance()->message[$filename ? md5($filename) : 'default'][] = date('Y-m-d H:i:s ').$message; 53 self::getInstance()->message[$filename ? md5($filename) : 'default'][] = date('Y-m-d H:i:s ').$message;
52 - 54 + return self::getInstance();
53 } 55 }
54 56
55 57
@@ -84,7 +86,7 @@ class Log { @@ -84,7 +86,7 @@ class Log {
84 /** 86 /**
85 * @return array 87 * @return array
86 */ 88 */
87 - public function getFilename($key=null): string 89 + protected function getFilename($key=null): string
88 { 90 {
89 return $this->filename[$key]??LOG_PATH.'/'.date('Y-m-d').'.error.log'; 91 return $this->filename[$key]??LOG_PATH.'/'.date('Y-m-d').'.error.log';
90 } 92 }