SyncMailList.php
4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?php
namespace App\Console\Commands;
use App\Models\Email;
use App\Models\Folder;
use Helper\Mail\Mail;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Swoole\Coroutine\Redis;
use function Co\run;
class SyncMailList extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'SyncMailList';
/**
* The console command description.
*
* @var string
*/
protected $description = '同步邮箱的邮件到本地';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
// 这个是防止前一个任务没有完成,反而无法取得资源。
$rand = date('dHi');
// 携程数量越大,需要的内存越大
$max_coroutine = 10000;
// swoole全局设置,需要在swoole运行前设置
\co::set([
'max_coroutine'=>$max_coroutine, // 最大携程数量
'hook_flags'=>SWOOLE_HOOK_TCP, // redis需要的配置
]);
// redis 配置
$redis_config = [
'host' => env('REDIS_HOST','127.0.0.1'),
'port' => env('REDIS_PORT',6379),
'password' => env('REDIS_PASSWORD',null)
];
run(function () use ($rand,$max_coroutine,$redis_config){
// 获取邮箱总数量
$size = Email::where([])->count();
// 最后一条数据的id
$lastId = Email::where([])->orderBy('id','desc')->value('id');
// 创建的携程数量
$max_coroutine = $size > $max_coroutine ? $max_coroutine : $size;
if ($max_coroutine){
for ($i = $max_coroutine; $i > 0; $i--) {
// 创建携程
go(function () use ($size,$rand,$lastId,$redis_config){
// redis 携程中无法使用laravel的cache的redis驱动
$redis = swoole_redis();
$n = 1;
while ($n <= $lastId){
echo 'syncMail'.$rand.':'.$n;echo PHP_EOL;
// 使用lua脚本
$add = $redis->eval(
...swoole_redis_add('syncMail'.$rand.':'.$n,$n,7200)
);
// 是否已存在
if($add) {
$this->sync($n);
}
$n++;
}
});
}
}
});
return Command::SUCCESS;
}
/**
* 开始同步执行
* @param int $n 第几条数据
* @author:dc
* @time 2023/2/5 17:21
*/
private function sync(int $n = 0){
/** @var $email Email */
$email = Email::where(['id'=>$n])->first();
// 密码没有错误,且状态正常的
if ($email && $email->pwd_error == 0 && $email->status == Email::STATUS_ACTIVE){
// 登录imap服务器
Mail::login($email->email,$email->password,$email->imap);
// 设置id
Mail::$client[$email->email]->setId($email->id);
// 同步文件夹
Mail::syncFolder($email->email);
// 获取当前邮箱的所有文件夹
$folders = Folder::_all($email->id);
// 目前只发现最高2级
foreach ($folders as $folder){
if(empty($folder['_child'])){
// 同步邮件
Mail::syncMail($email->email,$email->id,$folder['id'],$folder['origin_folder']);
}else{
// 循环子级目录,有子级的情况,父级不可操作,且不会有邮件
foreach ($folder['_child'] as $f){
// 同步邮件
Mail::syncMail($email->email,$email->id,$f['id'],$folder['origin_folder'].'/'.$f['origin_folder']);
}
}
}
}
}
}