正在显示
7 个修改的文件
包含
137 行增加
和
72 行删除
@@ -2,6 +2,7 @@ | @@ -2,6 +2,7 @@ | ||
2 | 2 | ||
3 | namespace App\Console\Commands; | 3 | namespace App\Console\Commands; |
4 | 4 | ||
5 | +use App\Models\EList; | ||
5 | use Helper\Mail\Mail; | 6 | use Helper\Mail\Mail; |
6 | use Illuminate\Console\Command; | 7 | use Illuminate\Console\Command; |
7 | use function Co\run; | 8 | use function Co\run; |
@@ -30,29 +31,33 @@ class Demo extends Command | @@ -30,29 +31,33 @@ class Demo extends Command | ||
30 | public function handle() | 31 | public function handle() |
31 | { | 32 | { |
32 | 33 | ||
33 | - run(function (){ | ||
34 | - go(function (){ | ||
35 | - | ||
36 | - $redis = swoole_redis(); | ||
37 | -// $a = $redis->eval(...swoole_redis_add('asdad:1',1,600)); | ||
38 | -// var_dump($a); | ||
39 | - $redis->rPush('syncMailBody',300); | ||
40 | -// $redis->rPush('syncMailBody',301); | ||
41 | -// $redis->rPush('syncMailBody',302); | ||
42 | -// $redis->rPush('syncMailBody',303); | ||
43 | -// $redis->rPush('syncMailBody',304); | ||
44 | -// $redis->rPush('syncMailBody',305); | ||
45 | -// $redis->rPush('syncMailBody',306); | ||
46 | -// $redis->rPush('syncMailBody',307); | ||
47 | -// $redis->rPush('syncMailBody',308); | ||
48 | -// $redis->rPush('syncMailBody',309); | ||
49 | - | ||
50 | - $redis->set('syncmailbodystop',1); | ||
51 | - | ||
52 | - }); | ||
53 | - | ||
54 | - }); | ||
55 | - | 34 | +// run(function (){ |
35 | +// go(function (){ | ||
36 | +// | ||
37 | +// | ||
38 | +// $redis = swoole_redis(); | ||
39 | +////// $a = $redis->eval(...swoole_redis_add('asdad:1',1,600)); | ||
40 | +////// var_dump($a); | ||
41 | +// for ($i=1;$i<=345;$i++){ | ||
42 | +// $redis->rPush('syncMailBody',$i); | ||
43 | +// } | ||
44 | +// | ||
45 | +//// $redis->rPush('syncMailBody',301); | ||
46 | +//// $redis->rPush('syncMailBody',302); | ||
47 | +//// $redis->rPush('syncMailBody',303); | ||
48 | +//// $redis->rPush('syncMailBody',304); | ||
49 | +//// $redis->rPush('syncMailBody',305); | ||
50 | +//// $redis->rPush('syncMailBody',306); | ||
51 | +//// $redis->rPush('syncMailBody',307); | ||
52 | +//// $redis->rPush('syncMailBody',308); | ||
53 | +//// $redis->rPush('syncMailBody',309); | ||
54 | +// | ||
55 | +// $redis->set('syncmailbodystop',1); | ||
56 | +// | ||
57 | +// }); | ||
58 | +// | ||
59 | +// }); | ||
60 | +// | ||
56 | 61 | ||
57 | 62 | ||
58 | 63 |
@@ -9,6 +9,7 @@ use Helper\Mail\Mail; | @@ -9,6 +9,7 @@ use Helper\Mail\Mail; | ||
9 | use Illuminate\Console\Command; | 9 | use Illuminate\Console\Command; |
10 | use Illuminate\Support\Facades\Cache; | 10 | use Illuminate\Support\Facades\Cache; |
11 | use Illuminate\Support\Facades\Log; | 11 | use Illuminate\Support\Facades\Log; |
12 | +use Swoole\Coroutine\MySQL; | ||
12 | use Swoole\Coroutine\Redis; | 13 | use Swoole\Coroutine\Redis; |
13 | use function Co\run; | 14 | use function Co\run; |
14 | 15 | ||
@@ -51,14 +52,16 @@ class SyncBody extends Command | @@ -51,14 +52,16 @@ class SyncBody extends Command | ||
51 | go(function () { | 52 | go(function () { |
52 | // 需要获取邮件的id | 53 | // 需要获取邮件的id |
53 | $isRun = true; | 54 | $isRun = true; |
54 | - while ($isRun){ | ||
55 | // @var $redis 这个必须放携程里面 | 55 | // @var $redis 这个必须放携程里面 |
56 | $redis = swoole_redis(); | 56 | $redis = swoole_redis(); |
57 | + $db = swoole_db(); | ||
58 | + while ($isRun){ | ||
59 | + | ||
57 | // 获取到邮件的数据id | 60 | // 获取到邮件的数据id |
58 | $id = $redis->lPop('syncMailBody'); | 61 | $id = $redis->lPop('syncMailBody'); |
59 | 62 | ||
60 | if($id){ | 63 | if($id){ |
61 | - $this->sync($redis,$id); | 64 | + $this->sync($redis,$db,$id); |
62 | }else { | 65 | }else { |
63 | // 暂停1秒 | 66 | // 暂停1秒 |
64 | \co::sleep(1); | 67 | \co::sleep(1); |
@@ -69,11 +72,14 @@ class SyncBody extends Command | @@ -69,11 +72,14 @@ class SyncBody extends Command | ||
69 | if($redis->get('syncmailbodystop') == 1){ | 72 | if($redis->get('syncmailbodystop') == 1){ |
70 | $isRun = false; | 73 | $isRun = false; |
71 | } | 74 | } |
72 | - // 关闭redis | 75 | + |
76 | + } | ||
77 | +// 关闭redis | ||
73 | $redis->close(); | 78 | $redis->close(); |
74 | $redis = null; | 79 | $redis = null; |
75 | - } | ||
76 | 80 | ||
81 | + $db->close(); | ||
82 | + $db = null; | ||
77 | 83 | ||
78 | }); | 84 | }); |
79 | } | 85 | } |
@@ -88,33 +94,40 @@ class SyncBody extends Command | @@ -88,33 +94,40 @@ class SyncBody extends Command | ||
88 | /** | 94 | /** |
89 | * 执行 | 95 | * 执行 |
90 | * @param $redis Redis | 96 | * @param $redis Redis |
97 | + * @param $db MySQL | ||
91 | * @param $id | 98 | * @param $id |
92 | * @author:dc | 99 | * @author:dc |
93 | * @time 2023/2/8 11:44 | 100 | * @time 2023/2/8 11:44 |
94 | */ | 101 | */ |
95 | - public function sync(&$redis,$id){ | 102 | + public function sync(&$redis,$db,$id){ |
96 | try { | 103 | try { |
97 | // 先暂用,锁上这个id | 104 | // 先暂用,锁上这个id |
98 | if($redis->eval(...swoole_redis_add('syncmailbodyrun:'.$id,$id,3))){ | 105 | if($redis->eval(...swoole_redis_add('syncmailbodyrun:'.$id,$id,3))){ |
99 | $this->echoStr('number:'.$id); | 106 | $this->echoStr('number:'.$id); |
100 | // 读取邮件信息 | 107 | // 读取邮件信息 |
101 | - $mail = EList::where('id',$id)->first(); | 108 | + $mail = swoole_db_first( |
109 | + $db, | ||
110 | + 'select `id`,`uid`,`msgno`,`folder_id`,`email_id` from `lists` where `id` = '.$id | ||
111 | + ); | ||
102 | if(!$mail){ | 112 | if(!$mail){ |
103 | return false; | 113 | return false; |
104 | } | 114 | } |
105 | 115 | ||
106 | - $email_id = $mail->email_id; | ||
107 | - $folder_id = $mail->folder_id; | 116 | + $email_id = $mail['email_id']; |
117 | + $folder_id = $mail['folder_id']; | ||
108 | 118 | ||
109 | /*** 获取邮箱信息 ***/ | 119 | /*** 获取邮箱信息 ***/ |
110 | $email_key = 'email_list:'.$email_id; | 120 | $email_key = 'email_list:'.$email_id; |
111 | // 判断是否有携程在查询了 | 121 | // 判断是否有携程在查询了 |
112 | if($redis->eval(...swoole_redis_add($email_key,1,600))){ | 122 | if($redis->eval(...swoole_redis_add($email_key,1,600))){ |
113 | // 查询邮箱 | 123 | // 查询邮箱 |
114 | - $emailModel = Email::where('id',$email_id)->first(); | 124 | + $emailModel = swoole_db_first( |
125 | + $db, | ||
126 | + 'select * from `emails` where `id` = '.$email_id | ||
127 | + ); | ||
115 | if($emailModel){ | 128 | if($emailModel){ |
116 | // 设置缓存 | 129 | // 设置缓存 |
117 | - $redis->set($email_key,$emailModel->toArray(),600); | 130 | + $redis->set($email_key,$emailModel,600); |
118 | }else { | 131 | }else { |
119 | // 删除缓存 | 132 | // 删除缓存 |
120 | $redis->delete($email_key); | 133 | $redis->delete($email_key); |
@@ -169,14 +182,17 @@ class SyncBody extends Command | @@ -169,14 +182,17 @@ class SyncBody extends Command | ||
169 | } | 182 | } |
170 | $this->echoStr('目录:'.$folder_name); | 183 | $this->echoStr('目录:'.$folder_name); |
171 | if($folder_name){ | 184 | if($folder_name){ |
185 | + // 登录imap服务器 | ||
186 | + Mail::login($email,$password,$imap); | ||
187 | + // 设置id | ||
188 | + Mail::$client[$email]->setId($email_id); | ||
189 | + | ||
172 | Mail::syncBody( | 190 | Mail::syncBody( |
173 | $id, | 191 | $id, |
174 | - $mail->msgno, | 192 | + $mail['msgno'], |
175 | $email_id, | 193 | $email_id, |
176 | $folder_name, | 194 | $folder_name, |
177 | - $email, | ||
178 | - $password, | ||
179 | - $imap | 195 | |
180 | ); | 196 | ); |
181 | } | 197 | } |
182 | } | 198 | } |
@@ -8,6 +8,7 @@ use Helper\Mail\Mail; | @@ -8,6 +8,7 @@ use Helper\Mail\Mail; | ||
8 | use Illuminate\Console\Command; | 8 | use Illuminate\Console\Command; |
9 | use Illuminate\Support\Facades\Cache; | 9 | use Illuminate\Support\Facades\Cache; |
10 | use Illuminate\Support\Facades\Log; | 10 | use Illuminate\Support\Facades\Log; |
11 | +use Swoole\Coroutine\MySQL; | ||
11 | use Swoole\Coroutine\Redis; | 12 | use Swoole\Coroutine\Redis; |
12 | use function Co\run; | 13 | use function Co\run; |
13 | 14 | ||
@@ -45,14 +46,8 @@ class SyncMailList extends Command | @@ -45,14 +46,8 @@ class SyncMailList extends Command | ||
45 | 'hook_flags'=>SWOOLE_HOOK_TCP, // redis需要的配置 | 46 | 'hook_flags'=>SWOOLE_HOOK_TCP, // redis需要的配置 |
46 | ]); | 47 | ]); |
47 | 48 | ||
48 | - // redis 配置 | ||
49 | - $redis_config = [ | ||
50 | - 'host' => env('REDIS_HOST','127.0.0.1'), | ||
51 | - 'port' => env('REDIS_PORT',6379), | ||
52 | - 'password' => env('REDIS_PASSWORD',null) | ||
53 | - ]; | ||
54 | 49 | ||
55 | - run(function () use ($rand,$max_coroutine,$redis_config){ | 50 | + run(function () use ($rand,$max_coroutine){ |
56 | // 获取邮箱总数量 | 51 | // 获取邮箱总数量 |
57 | $size = Email::where([])->count(); | 52 | $size = Email::where([])->count(); |
58 | // 最后一条数据的id | 53 | // 最后一条数据的id |
@@ -62,11 +57,11 @@ class SyncMailList extends Command | @@ -62,11 +57,11 @@ class SyncMailList extends Command | ||
62 | if ($max_coroutine){ | 57 | if ($max_coroutine){ |
63 | for ($i = $max_coroutine; $i > 0; $i--) { | 58 | for ($i = $max_coroutine; $i > 0; $i--) { |
64 | // 创建携程 | 59 | // 创建携程 |
65 | - go(function () use ($size,$rand,$lastId,$redis_config){ | 60 | + go(function () use ($size,$rand,$lastId){ |
66 | 61 | ||
67 | // redis 携程中无法使用laravel的cache的redis驱动 | 62 | // redis 携程中无法使用laravel的cache的redis驱动 |
68 | $redis = swoole_redis(); | 63 | $redis = swoole_redis(); |
69 | - | 64 | + $db = swoole_db(); |
70 | $n = 1; | 65 | $n = 1; |
71 | while ($n <= $lastId){ | 66 | while ($n <= $lastId){ |
72 | echo 'syncMail'.$rand.':'.$n;echo PHP_EOL; | 67 | echo 'syncMail'.$rand.':'.$n;echo PHP_EOL; |
@@ -76,11 +71,19 @@ class SyncMailList extends Command | @@ -76,11 +71,19 @@ class SyncMailList extends Command | ||
76 | ); | 71 | ); |
77 | // 是否已存在 | 72 | // 是否已存在 |
78 | if($add) { | 73 | if($add) { |
79 | - $this->sync($n); | 74 | + try { |
75 | + $this->sync($n,$db); | ||
76 | + }catch (\Throwable $e){ | ||
77 | + echo "协程(".\co::getCid()."):".$e->getMessage(); | ||
78 | + } | ||
79 | + | ||
80 | } | 80 | } |
81 | 81 | ||
82 | $n++; | 82 | $n++; |
83 | } | 83 | } |
84 | + $redis->close(); | ||
85 | + $db->close(); | ||
86 | + $redis = $db = null; | ||
84 | 87 | ||
85 | }); | 88 | }); |
86 | } | 89 | } |
@@ -93,35 +96,40 @@ class SyncMailList extends Command | @@ -93,35 +96,40 @@ class SyncMailList extends Command | ||
93 | 96 | ||
94 | /** | 97 | /** |
95 | * 开始同步执行 | 98 | * 开始同步执行 |
96 | - * @param int $n 第几条数据 | 99 | + * @param int $n |
100 | + * @param MySQL $db | ||
97 | * @author:dc | 101 | * @author:dc |
98 | - * @time 2023/2/5 17:21 | 102 | + * @time 2023/2/9 11:40 |
99 | */ | 103 | */ |
100 | - private function sync(int $n = 0){ | 104 | + private function sync(int $n,MySQL $db){ |
101 | 105 | ||
102 | /** @var $email Email */ | 106 | /** @var $email Email */ |
103 | - $email = Email::where(['id'=>$n])->first(); | 107 | + $email = swoole_db_first( |
108 | + $db, | ||
109 | + 'select * from `emails` where `id` = '.$n | ||
110 | + ); | ||
111 | + | ||
104 | // 密码没有错误,且状态正常的 | 112 | // 密码没有错误,且状态正常的 |
105 | - if ($email && $email->pwd_error == 0 && $email->status == Email::STATUS_ACTIVE){ | 113 | + if ($email && $email['pwd_error'] == 0 && $email['status'] == Email::STATUS_ACTIVE){ |
106 | // 登录imap服务器 | 114 | // 登录imap服务器 |
107 | - Mail::login($email->email,$email->password,$email->imap); | 115 | + Mail::login($email['email'],base64_decode($email['password']),$email['imap']); |
108 | // 设置id | 116 | // 设置id |
109 | - Mail::$client[$email->email]->setId($email->id); | 117 | + Mail::$client[$email['email']]->setId($email['id']); |
110 | // 同步文件夹 | 118 | // 同步文件夹 |
111 | - Mail::syncFolder($email->email); | 119 | + Mail::syncFolder($email['email']); |
112 | 120 | ||
113 | // 获取当前邮箱的所有文件夹 | 121 | // 获取当前邮箱的所有文件夹 |
114 | - $folders = Folder::_all($email->id); | 122 | + $folders = Folder::_all($email['id']); |
115 | // 目前只发现最高2级 | 123 | // 目前只发现最高2级 |
116 | foreach ($folders as $folder){ | 124 | foreach ($folders as $folder){ |
117 | if(empty($folder['_child'])){ | 125 | if(empty($folder['_child'])){ |
118 | // 同步邮件 | 126 | // 同步邮件 |
119 | - Mail::syncMail($email->email,$email->id,$folder['id'],$folder['origin_folder']); | 127 | + Mail::syncMail($email['email'],$email['id'],$folder['id'],$folder['origin_folder']); |
120 | }else{ | 128 | }else{ |
121 | // 循环子级目录,有子级的情况,父级不可操作,且不会有邮件 | 129 | // 循环子级目录,有子级的情况,父级不可操作,且不会有邮件 |
122 | foreach ($folder['_child'] as $f){ | 130 | foreach ($folder['_child'] as $f){ |
123 | // 同步邮件 | 131 | // 同步邮件 |
124 | - Mail::syncMail($email->email,$email->id,$f['id'],$folder['origin_folder'].'/'.$f['origin_folder']); | 132 | + Mail::syncMail($email['email'],$email['id'],$f['id'],$folder['origin_folder'].'/'.$f['origin_folder']); |
125 | } | 133 | } |
126 | } | 134 | } |
127 | 135 |
@@ -50,6 +50,7 @@ class MailApi | @@ -50,6 +50,7 @@ class MailApi | ||
50 | 50 | ||
51 | $model->imap = $formData['imap']; | 51 | $model->imap = $formData['imap']; |
52 | $model->smtp = $formData['smtp']; | 52 | $model->smtp = $formData['smtp']; |
53 | + $model->status = Email::STATUS_ACTIVE; | ||
53 | $model->password = @base64_encode($formData['password']); | 54 | $model->password = @base64_encode($formData['password']); |
54 | 55 | ||
55 | try { | 56 | try { |
@@ -877,8 +877,9 @@ class Imap { | @@ -877,8 +877,9 @@ class Imap { | ||
877 | * @author:dc | 877 | * @author:dc |
878 | * @time 2022/11/25 11:15 | 878 | * @time 2022/11/25 11:15 |
879 | */ | 879 | */ |
880 | - public function noop():void { | ||
881 | - $this->request('NOOP'); | 880 | + public function noop():bool { |
881 | + $status = $this->request('NOOP'); | ||
882 | + return $status[0] == 'ok'; | ||
882 | } | 883 | } |
883 | 884 | ||
884 | /** | 885 | /** |
@@ -35,10 +35,16 @@ class Mail { | @@ -35,10 +35,16 @@ class Mail { | ||
35 | * @time 2023/2/5 10:46 | 35 | * @time 2023/2/5 10:46 |
36 | */ | 36 | */ |
37 | public static function login(string $email,string $password,string $imap) { | 37 | public static function login(string $email,string $password,string $imap) { |
38 | + if(!empty(static::$client[$email]) && static::$client[$email] instanceof Imap){ | ||
39 | + if(static::$client[$email]->noop()){ | ||
40 | + return true; | ||
41 | + } | ||
42 | + } | ||
38 | static::$client[$email] = new Imap(); | 43 | static::$client[$email] = new Imap(); |
39 | // $imap->debug(); | 44 | // $imap->debug(); |
40 | // 是否初始成功 | 45 | // 是否初始成功 |
41 | static::$client[$email]->login("ssl://{$imap}:993",$email,$password); | 46 | static::$client[$email]->login("ssl://{$imap}:993",$email,$password); |
47 | + return true; | ||
42 | } | 48 | } |
43 | 49 | ||
44 | 50 | ||
@@ -89,7 +95,7 @@ class Mail { | @@ -89,7 +95,7 @@ class Mail { | ||
89 | public static function syncMail($email,$email_id,$folder_id,$folder='INBOX'):bool { | 95 | public static function syncMail($email,$email_id,$folder_id,$folder='INBOX'):bool { |
90 | // 选择文件夹 | 96 | // 选择文件夹 |
91 | try { | 97 | try { |
92 | - $status = Mail::$client[$email]->selectFolder($folder); | 98 | + $status = static::$client[$email]->selectFolder($folder); |
93 | }catch (\Throwable $e){ | 99 | }catch (\Throwable $e){ |
94 | Log::error($email.' 选择文件夹错误:'.$e->getMessage()); | 100 | Log::error($email.' 选择文件夹错误:'.$e->getMessage()); |
95 | return false; | 101 | return false; |
@@ -128,7 +134,7 @@ class Mail { | @@ -128,7 +134,7 @@ class Mail { | ||
128 | $dataids = EList::_getIdsByMsgno($email_id,$folder_id,$msgno); | 134 | $dataids = EList::_getIdsByMsgno($email_id,$folder_id,$msgno); |
129 | 135 | ||
130 | // 循环 | 136 | // 循环 |
131 | - $results = Mail::$client[$email]->fetchHeader($msgno); | 137 | + $results = static::$client[$email]->fetchHeader($msgno); |
132 | 138 | ||
133 | if($results){ | 139 | if($results){ |
134 | DB::beginTransaction(); | 140 | DB::beginTransaction(); |
@@ -211,23 +217,17 @@ class Mail { | @@ -211,23 +217,17 @@ class Mail { | ||
211 | * @param $email_id | 217 | * @param $email_id |
212 | * @param $folder_name | 218 | * @param $folder_name |
213 | * @param $email | 219 | * @param $email |
214 | - * @param $password | ||
215 | - * @param $imap | ||
216 | * @return bool | 220 | * @return bool |
217 | * @throws \Exception | 221 | * @throws \Exception |
218 | * @author:dc | 222 | * @author:dc |
219 | - * @time 2023/2/8 13:45 | 223 | + * @time 2023/2/9 10:29 |
220 | */ | 224 | */ |
221 | - public static function syncBody($id,$msgno, $email_id,$folder_name,$email, $password,$imap):bool { | 225 | + public static function syncBody($id,$msgno, $email_id,$folder_name,$email):bool { |
222 | 226 | ||
223 | - // 登录imap服务器 | ||
224 | - Mail::login($email,$password,$imap); | ||
225 | - // 设置id | ||
226 | - Mail::$client[$email]->setId($email_id); | ||
227 | // 选择文件夹 | 227 | // 选择文件夹 |
228 | - Mail::$client[$email]->selectFolder($folder_name); | 228 | + static::$client[$email]->selectFolder($folder_name); |
229 | 229 | ||
230 | - $body = Mail::$client[$email]->fetchBody([$msgno],storage_path('email/'.$email_id)); | 230 | + $body = static::$client[$email]->fetchBody([$msgno],storage_path('email/'.$email_id)); |
231 | 231 | ||
232 | if(!empty($body[$msgno]['RFC822.TEXT'])){ | 232 | if(!empty($body[$msgno]['RFC822.TEXT'])){ |
233 | \App\Models\Body::_insert($id,$body[$msgno]['RFC822.TEXT']); | 233 | \App\Models\Body::_insert($id,$body[$msgno]['RFC822.TEXT']); |
@@ -144,6 +144,40 @@ function swoole_redis_add($key,$val,$ttl=-1):array { | @@ -144,6 +144,40 @@ function swoole_redis_add($key,$val,$ttl=-1):array { | ||
144 | ]; | 144 | ]; |
145 | } | 145 | } |
146 | 146 | ||
147 | +/** | ||
148 | + * swoole 操作db | ||
149 | + * @return \Swoole\Coroutine\MySQL | ||
150 | + * @author:dc | ||
151 | + * @time 2023/2/8 16:48 | ||
152 | + */ | ||
153 | +function swoole_db():\Swoole\Coroutine\MySQL{ | ||
154 | + | ||
155 | + $swoole_mysql = new \Swoole\Coroutine\MySQL(); | ||
156 | + | ||
157 | + $swoole_mysql->connect([ | ||
158 | + 'host' => env('DB_HOST','127.0.0.1'), | ||
159 | + 'port' => env('DB_PORT',3306), | ||
160 | + 'user' => env('DB_USERNAME'), | ||
161 | + 'password' => env('DB_PASSWORD'), | ||
162 | + 'database' => env('DB_DATABASE'), | ||
163 | + ]); | ||
164 | + | ||
165 | + return $swoole_mysql; | ||
166 | +} | ||
167 | + | ||
168 | +/** | ||
169 | + * 查询一条 | ||
170 | + * @param $db \Swoole\Coroutine\MySQL | ||
171 | + * @param $query | ||
172 | + * @return mixed | ||
173 | + * @author:dc | ||
174 | + * @time 2023/2/8 17:15 | ||
175 | + */ | ||
176 | +function swoole_db_first(&$db,$query){ | ||
177 | + $row = $db->query($query); | ||
178 | + return $row[0]??null; | ||
179 | +} | ||
180 | + | ||
147 | 181 | ||
148 | 182 | ||
149 | 183 |
-
请 注册 或 登录 后发表评论