作者 邓超

优化 同步

... ... @@ -733,7 +733,7 @@ class Imap {
}elseif($header2Body=='body'){
$filed = 'RFC822.TEXT';
}else{
$filed = 'UID FLAGS INTERNALDATE';
$filed = $header2Body;
}
// 读取数据
... ...
... ... @@ -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;
}
... ...
... ... @@ -60,6 +60,19 @@ class listsSql {
}
/**
* 获取已有的uid
* @param int $email_id
* @param int $folder_id
* @param array $uids
* @return string
* @author:dc
* @time 2023/4/23 16:54
*/
public static function getUids(int $email_id, int $folder_id, array $uids){
return "select `uid` from `".static::$table."` where ".dbWhere(['email_id'=>$email_id,'folder_id'=>$folder_id,'uid'=>$uids]);
}
/**
* 获取已存在的id
* @param $email_id
* @param $folder_id
... ...