作者 邓超

1

@@ -115,20 +115,14 @@ function sync($email_id,$worker_id){ @@ -115,20 +115,14 @@ function sync($email_id,$worker_id){
115 return 1; 115 return 1;
116 } 116 }
117 117
118 - $mailServer = new Lib\Mail\Mail(); 118 + $mailServer = new Lib\Mail\Mail($email['email'],base64_decode($email['password']),$email['imap']);
119 119
120 - try {  
121 // 登录服务器 120 // 登录服务器
122 - $mailServer->login($email['email'],base64_decode($email['password']),$email['imap']);  
123 - }catch (Throwable $e){  
124 - if($e->getCode() == 403){  
125 - // 登录失败了 ,  
126 - db()->update(\Model\emailSql::$table,['pwd_error'=>1],dbWhere(['id'=>$email_id]));  
127 - }  
128 - 121 + if(!$mailServer->login()){
129 return 2; 122 return 2;
130 } 123 }
131 124
  125 +
132 // 同步文件夹 126 // 同步文件夹
133 $mailServer->syncFolder($email_id,db()); 127 $mailServer->syncFolder($email_id,db());
134 128
@@ -239,21 +239,13 @@ function sync($worker_id=0){ @@ -239,21 +239,13 @@ function sync($worker_id=0){
239 return 1; 239 return 1;
240 } 240 }
241 241
242 - $mailServer = new Lib\Mail\Mail(); 242 + $mailServer = new Lib\Mail\Mail($email['email'],base64_decode($email['password']),$email['imap']);
243 243
244 - try {  
245 // 登录服务器 244 // 登录服务器
246 - $mailServer->login($email['email'],base64_decode($email['password']),$email['imap']);  
247 - }catch (Throwable $e){  
248 - if($e->getCode() == 403){  
249 - // 登录失败了 ,  
250 - db()->update(\Model\emailSql::$table,['pwd_error'=>1],dbWhere(['id'=>$id]));  
251 - }  
252 - 245 + if(!$mailServer->login()){
253 return 2; 246 return 2;
254 } 247 }
255 248
256 -  
257 // 文件夹间隔1天同步一次 249 // 文件夹间隔1天同步一次
258 if(empty($email['last_sync_time']) || time() > $email['last_sync_time']+86400){ 250 if(empty($email['last_sync_time']) || time() > $email['last_sync_time']+86400){
259 // 同步文件夹 251 // 同步文件夹
@@ -7,6 +7,8 @@ @@ -7,6 +7,8 @@
7 "php": "^8.0.2", 7 "php": "^8.0.2",
8 "ext-pdo": "*", 8 "ext-pdo": "*",
9 "ext-redis": "*", 9 "ext-redis": "*",
  10 + "ext-mbstring": "*",
  11 + "ext-json": "*",
10 "phpmailer/phpmailer": "^6.7" 12 "phpmailer/phpmailer": "^6.7"
11 }, 13 },
12 "require-dev": { 14 "require-dev": {
@@ -37,7 +37,4 @@ define('APP_DEBUG',true); @@ -37,7 +37,4 @@ define('APP_DEBUG',true);
37 37
38 38
39 39
40 -// 创建 必须 目录  
41 -if(!is_dir(LOG_PATH)){  
42 - mkdir(LOG_PATH,0777,true);  
43 -} 40 +
@@ -46,15 +46,17 @@ class Folder extends Base { @@ -46,15 +46,17 @@ class Folder extends Base {
46 * @time 2023/2/18 17:56 46 * @time 2023/2/18 17:56
47 */ 47 */
48 public function create(){ 48 public function create(){
  49 + $email = $this->getEmail('id');
  50 +
49 $formData = app()->request(['pid','folder']); 51 $formData = app()->request(['pid','folder']);
50 // 验证目录 可以输入中文英文数字 52 // 验证目录 可以输入中文英文数字
51 - if(empty($formData['folder']) || !preg_match("/^[\u4E00-\u9FA5A-Za-z0-9_]+$/",$formData['folder'])){ 53 + if(empty($formData['folder'])){
52 app()->e('folder_create_name_error'); 54 app()->e('folder_create_name_error');
53 } 55 }
54 // 不为空上级 56 // 不为空上级
55 if(!empty($formData['pid'])){ 57 if(!empty($formData['pid'])){
56 $parent = db()->first(folderSql::first(['id'=>$formData['pid']])); 58 $parent = db()->first(folderSql::first(['id'=>$formData['pid']]));
57 - if(!$parent || $parent['email_id'] != $this->login_email['id']){ 59 + if(!$parent || $parent['email_id'] != $email['id']){
58 app()->e('folder_parent_not_fount'); 60 app()->e('folder_parent_not_fount');
59 } 61 }
60 if($parent['pid']){ 62 if($parent['pid']){
@@ -63,11 +65,13 @@ class Folder extends Base { @@ -63,11 +65,13 @@ class Folder extends Base {
63 65
64 } 66 }
65 67
  68 + $formData['folder'] = str_replace(["'",'"','/','\\','&','*','(',')'],'',$formData['folder']);
  69 +
66 // 判断文件夹是否存在 70 // 判断文件夹是否存在
67 $has = db()->count(folderSql::has( 71 $has = db()->count(folderSql::has(
68 [ 72 [
69 - 'email_id' => $this->login_email['id'],  
70 - 'origin_folder' => $formData['folder'] 73 + 'email_id' => $email['id'],
  74 + 'origin_folder' => MailFun::folderEncoding($formData['folder'])
71 ] 75 ]
72 )); 76 ));
73 77
@@ -76,8 +80,19 @@ class Folder extends Base { @@ -76,8 +80,19 @@ class Folder extends Base {
76 } 80 }
77 81
78 // 远程创建 82 // 远程创建
79 - $mail = new Mail();  
80 - $mail->login($this->login_email['email'],$this->login_email['password'],$this->login_email['imap']); 83 + $mail = new Mail(
  84 + $email['email'],
  85 + $email['password'],
  86 + $email['imap']
  87 + );
  88 +
  89 + if(!$mail->login()){
  90 + app()->e('login_error_imap');
  91 + }
  92 +
  93 +
  94 +
  95 +
81 $folder = $mail->client->folderCreate($formData['folder']); 96 $folder = $mail->client->folderCreate($formData['folder']);
82 97
83 98
@@ -44,13 +44,13 @@ class Login { @@ -44,13 +44,13 @@ class Login {
44 } 44 }
45 45
46 // 进行远程登录,验证 46 // 进行远程登录,验证
47 - try{  
48 - (new Mail())->login($formData['email'],$formData['password'],$formData['imap']);  
49 - }catch (\Exception $e){  
50 - if($e->getCode()==403){ 47 + $login = (new Mail($formData['email'],$formData['password'],$formData['imap']))->login(false);
  48 + if( $login === 0){
51 app()->e('login_error_imap'); 49 app()->e('login_error_imap');
  50 + }elseif ($login === -1){
  51 + app()->e('server_error');
52 } 52 }
53 - } 53 +
54 54
55 // 是否存在 55 // 是否存在
56 $id = db()->value(emailSql::hasEmail($formData['email'])); 56 $id = db()->value(emailSql::hasEmail($formData['email']));
@@ -50,16 +50,7 @@ function db():\Lib\DbPool{ @@ -50,16 +50,7 @@ function db():\Lib\DbPool{
50 */ 50 */
51 function logs($message,$filename=null){ 51 function logs($message,$filename=null){
52 52
53 - $filename = $filename ? $filename : LOG_PATH.'/error.log';  
54 - if(!is_dir(dirname($filename))){  
55 - @mkdir(dirname($filename),0755,true);  
56 - }  
57 -  
58 - @file_put_contents(  
59 - $filename,  
60 - date('Y-m-d H:i:s ').print_r($message,true).PHP_EOL,  
61 - FILE_APPEND  
62 - ); 53 + \Lib\Log::append($message, $filename);
63 54
64 } 55 }
65 56
@@ -299,19 +299,12 @@ class App { @@ -299,19 +299,12 @@ class App {
299 */ 299 */
300 public static function end() 300 public static function end()
301 { 301 {
302 - // 这里可以做其他事  
303 - $app = self::instance();  
304 -  
305 - /**  
306 - * 这里写  
307 - */  
308 302
309 - // end code 303 + $app = self::instance();
310 304
311 // 记录日志 305 // 记录日志
312 - $filename = LOG_PATH.'/'.$app->nowDate().'.log';  
313 if($last_error = error_get_last()){ 306 if($last_error = error_get_last()){
314 - logs(print_r($last_error,true), $filename); 307 + logs(print_r($last_error,true));
315 308
316 $data['error_message'] = $last_error['message']; 309 $data['error_message'] = $last_error['message'];
317 $data['status'] = 502; 310 $data['status'] = 502;
@@ -321,15 +314,15 @@ class App { @@ -321,15 +314,15 @@ class App {
321 }else{ 314 }else{
322 if($app->getError()){ 315 if($app->getError()){
323 logs( 316 logs(
324 - is_string($app->getError()) ? $app->getError() : implode(PHP_EOL,$app->getError()),  
325 - $filename 317 + is_string($app->getError()) ? $app->getError() : implode(PHP_EOL,$app->getError())
326 ); 318 );
327 } 319 }
328 320
329 self::echo($app->data); 321 self::echo($app->data);
330 } 322 }
331 323
332 - 324 + // 日志记录
  325 + Log::getInstance()->write();
333 326
334 // header("Content-Type:text/event-stream;Charset=UTF-8;"); 327 // header("Content-Type:text/event-stream;Charset=UTF-8;");
335 328
@@ -67,11 +67,14 @@ class DbPool { @@ -67,11 +67,14 @@ class DbPool {
67 } 67 }
68 $query = $this->client->prepare($sql); 68 $query = $this->client->prepare($sql);
69 69
  70 + if(APP_DEBUG){
70 // todo:: 记录日志,生产请注释 71 // todo:: 记录日志,生产请注释
71 logs( 72 logs(
72 $params ? [$sql,$params] : $sql, 73 $params ? [$sql,$params] : $sql,
73 LOG_PATH.'/sql.log' 74 LOG_PATH.'/sql.log'
74 ); 75 );
  76 + }
  77 +
75 78
76 if($query->execute($params)){ 79 if($query->execute($params)){
77 return $query; 80 return $query;
  1 +<?php
  2 +
  3 +namespace Lib;
  4 +
  5 +
  6 +/**
  7 + * 日志文件
  8 + * @author:dc
  9 + * @time 2023/3/14 10:26
  10 + * Class Log
  11 + * @package Lib
  12 + */
  13 +class Log {
  14 +
  15 +
  16 + /**
  17 + * @var array
  18 + */
  19 + public array $filename = [];
  20 +
  21 + /**
  22 + * @var array
  23 + */
  24 + public array $message = [];
  25 +
  26 + /**
  27 + * @var self
  28 + */
  29 + private static self $instance;
  30 +
  31 + /**
  32 + * Log constructor.
  33 + */
  34 + public function __construct()
  35 + {
  36 + $this->filename['default'] = LOG_PATH.'/'.app()->nowDate().'.error.log';
  37 + }
  38 +
  39 + /**
  40 + * 追加日志内容
  41 + * @param string $message
  42 + * @author:dc
  43 + * @time 2023/3/14 10:45
  44 + */
  45 + public static function append(string $message, $filename = null){
  46 +
  47 + if($filename){
  48 + self::getInstance()->setFilename($filename);
  49 + }
  50 +
  51 + self::getInstance()->message[md5($filename)][] = $message;
  52 +
  53 + }
  54 +
  55 +
  56 + /**
  57 + * @return Log
  58 + */
  59 + public static function getInstance(): Log
  60 + {
  61 + if (empty(static::$instance)){
  62 + static::$instance = new Log();
  63 + }
  64 +
  65 + return self::$instance;
  66 + }
  67 +
  68 + /**
  69 + * 设置日志文件
  70 + * @param $filename
  71 + * @author:dc
  72 + * @time 2023/3/14 11:11
  73 + */
  74 + private function setFilename($filename){
  75 +
  76 + // 创建目录
  77 + if(!is_dir(dirname($filename))){
  78 + @mkdir(dirname($filename),0755,true);
  79 + }
  80 +
  81 + $this->filename[md5($filename)] = $filename;
  82 +
  83 +
  84 + }
  85 +
  86 + /**
  87 + * 写入日志
  88 + * @author:dc
  89 + * @time 2023/3/14 10:45
  90 + */
  91 + public function write(){
  92 +
  93 + foreach ($this->filename as $key=>$fn){
  94 + if(!empty($this->message[$key])){
  95 +
  96 + array_unshift($this->message[$key],app()->nowDateTime());
  97 + $this->message[$key][] = PHP_EOL;
  98 +
  99 + @file_put_contents(
  100 + $fn,
  101 + implode(PHP_EOL."\t",$this->message[$key]),
  102 + FILE_APPEND
  103 + );
  104 + $this->message[$key] = [];
  105 + }
  106 +
  107 + }
  108 +
  109 + }
  110 +
  111 +}
@@ -437,10 +437,10 @@ class Imap { @@ -437,10 +437,10 @@ class Imap {
437 */ 437 */
438 public function folderCreate(string $folder):string { 438 public function folderCreate(string $folder):string {
439 // 需要转码 439 // 需要转码
440 - $folder = mb_convert_encoding($folder,'UTF7-IMAP','UTF-8'); 440 + $folder = MailFun::folderEncoding($folder);
441 // A003 CREATE owatagusiam 顶级 441 // A003 CREATE owatagusiam 顶级
442 // A003 CREATE owatagusiam/owatagusiam2 有上下级关系的文件夹 442 // A003 CREATE owatagusiam/owatagusiam2 有上下级关系的文件夹
443 - $res = $this->request('CREATE '.$folder); 443 + $res = $this->request("CREATE \"{$folder}\"");
444 444
445 if ($res[0] == 'ok'){ 445 if ($res[0] == 'ok'){
446 return $folder; 446 return $folder;
@@ -21,23 +21,60 @@ class Mail { @@ -21,23 +21,60 @@ class Mail {
21 */ 21 */
22 public Imap $client; 22 public Imap $client;
23 23
  24 + /**
  25 + * @var string
  26 + */
  27 + private string $username;
24 28
25 /** 29 /**
26 - * 登录imap服务器 30 + * @var string
  31 + */
  32 + private string $password;
  33 +
  34 + /**
  35 + * @var string
  36 + */
  37 + private string $server;
  38 +
  39 + /**
  40 + * Mail constructor.
27 * @param string $email 41 * @param string $email
28 * @param string $password 42 * @param string $password
29 * @param string $imap 43 * @param string $imap
  44 + */
  45 + public function __construct(string $email,string $password,string $imap)
  46 + {
  47 + $this->username = $email;
  48 + $this->password = $password;
  49 + $this->server = $imap;
  50 + }
  51 +
  52 + /**
  53 + * 登录imap服务器
  54 + * @param bool $pass_err
  55 + * @return int
30 * @author:dc 56 * @author:dc
31 - * @time 2023/2/5 10:46 57 + * @time 2023/3/14 10:03
32 */ 58 */
33 - public function login(string $email,string $password,string $imap) { 59 + public function login($pass_err=true):int {
34 60
35 $this->client = new Imap(); 61 $this->client = new Imap();
36 62
  63 + try {
37 // 是否初始成功 64 // 是否初始成功
38 - $this->client->login("ssl://{$imap}:993",$email,$password); 65 + $this->client->login("ssl://{$this->server}:993",$this->username,$this->password);
  66 + }catch (\Throwable $e){
  67 + if($pass_err && $e->getCode() == 403){
  68 + // 登录失败了 ,
  69 + db()->update(\Model\emailSql::$table,['pwd_error'=>1],dbWhere(['email'=>$this->username]));
  70 + }else{
  71 + logs($e->getMessage());
  72 + }
39 73
40 - return true; 74 + return $e->getCode() == 403 ? 0 : -1;
  75 +
  76 + }
  77 + return 1;
41 } 78 }
42 79
43 80
@@ -201,5 +201,15 @@ class MailFun { @@ -201,5 +201,15 @@ class MailFun {
201 201
202 } 202 }
203 203
  204 + /**
  205 + * 文件夹名 编译
  206 + * @param $folder
  207 + * @return string
  208 + * @author:dc
  209 + * @time 2023/3/14 9:37
  210 + */
  211 + public static function folderEncoding($folder):string {
  212 + return mb_convert_encoding($folder,'UTF7-IMAP','UTF-8');
  213 + }
204 214
205 } 215 }