正在显示
14 个修改的文件
包含
4137 行增加
和
57 行删除
@@ -4,74 +4,136 @@ | @@ -4,74 +4,136 @@ | ||
4 | 4 | ||
5 | use Swoole\Process; | 5 | use Swoole\Process; |
6 | 6 | ||
7 | -include_once __DIR__."/config.php"; | ||
8 | -include_once __DIR__."/function.php"; | ||
9 | 7 | ||
10 | 8 | ||
9 | +include_once __DIR__."/../vendor/autoload.php"; | ||
10 | + | ||
11 | 11 | ||
12 | function start(){ | 12 | function start(){ |
13 | - // 启动一个进程池进行管理 | 13 | + |
14 | +// 删除停止运行的值 | ||
15 | + redis()->delete(RUNNING_REDIS_KEY); | ||
16 | + | ||
17 | + /** 创建一个表 **/ | ||
18 | + $table = new Swoole\Table(128);// 128 行 | ||
19 | + $table->column('val', Swoole\Table::TYPE_INT); | ||
20 | + $table->create(); | ||
21 | + | ||
22 | + // 初始时,进行一次统计 | ||
23 | + $table->set('etotal',['val'=> db()->count(\Model\email::count())]); | ||
24 | + | ||
25 | +// 启动一个进程池进行管理 | ||
14 | $topPool = new Process\Pool(WORKER_NUM); | 26 | $topPool = new Process\Pool(WORKER_NUM); |
27 | + | ||
28 | + // 每10分钟统计一次邮箱数量 | ||
29 | + $timer_id = \Swoole\Timer::tick(600,function () use (&$table){ | ||
30 | + $table->set('etotal',['val'=> db()->count(\Model\email::count())]); | ||
31 | + }); | ||
32 | + | ||
33 | + // 每2秒执行一次 | ||
34 | + $timer_check_id = \Swoole\Timer::tick(2,function () use (&$table,$topPool){ | ||
35 | + // 是否停止脚本 | ||
36 | + $table->set('stop',['val'=> redis()->get(RUNNING_REDIS_KEY) === 'stop' ? 1 : 0]); | ||
37 | + | ||
38 | + // 检查是否结束了所有的协程同步代码 | ||
39 | + if ($table->get('stop','val')) { | ||
40 | + $stop_num = 0; | ||
41 | + foreach (range(0, WORKER_NUM) as $i) { | ||
42 | + if ($table->exists('ps' . $i)) { | ||
43 | + $stop_num++; | ||
44 | + } | ||
45 | + } | ||
46 | + if($stop_num >= WORKER_NUM){ | ||
47 | +// 退出进程 | ||
48 | + $topPool->shutdown(); | ||
49 | + } | ||
50 | + } | ||
51 | + | ||
52 | + // 邮件总数 | ||
53 | + $total = redis()->get('email_total',0); | ||
54 | + if($total > $table->get('etotal','val')){ | ||
55 | + $table->set('etotal',['val'=> $total]); | ||
56 | + } | ||
57 | + | ||
58 | + }); | ||
59 | + | ||
60 | + | ||
61 | + | ||
15 | // 这个是启用协程 | 62 | // 这个是启用协程 |
16 | $topPool->set(['enable_coroutine' => true]); | 63 | $topPool->set(['enable_coroutine' => true]); |
17 | // 协程配置 | 64 | // 协程配置 |
18 | \co::set([ | 65 | \co::set([ |
19 | - 'max_coroutine'=>1000, // 最大携程数量 | 66 | + 'max_coroutine'=>COROUTINE_MAX_NUM, // 最大携程数量 |
20 | 'hook_flags'=>SWOOLE_HOOK_TCP, // redis需要的配置 | 67 | 'hook_flags'=>SWOOLE_HOOK_TCP, // redis需要的配置 |
21 | ]); | 68 | ]); |
69 | + | ||
22 | // 开始工作 | 70 | // 开始工作 |
23 | - $topPool->on('WorkerStart',function (Process\Pool $pool,$worker_id){ | 71 | + $topPool->on('WorkerStart',function (Process\Pool $pool,$worker_id) use (&$table){ |
24 | _echo("进程({$worker_id})启动成功"); | 72 | _echo("进程({$worker_id})启动成功"); |
73 | + | ||
74 | + // 是否停止,这里进行阻塞 | ||
75 | + if ($table->get('stop','val')){ | ||
76 | + // 某个进程退出了 | ||
77 | + $table->set('ps'.$worker_id,['val'=>1]); | ||
78 | + | ||
79 | + co::sleep(1); | ||
80 | + return true; | ||
81 | + } | ||
82 | + | ||
25 | // 协程id集 | 83 | // 协程id集 |
26 | $cid = []; | 84 | $cid = []; |
27 | - // 删除停止运行的值 | ||
28 | - swoole_redis()->delete(RUNNING_REDIS_KEY); | ||
29 | - | ||
30 | -// \Co\run(function (){ | ||
31 | - // 开启多个协程 | ||
32 | - foreach (range(1,COROUTINE_NUM) as $i){ | ||
33 | - go(function () use ($cid,$worker_id){ | ||
34 | - // 协程id | ||
35 | - $cid[co::getCid()] = co::getCid(); | ||
36 | - | ||
37 | - $redis = swoole_redis(); | ||
38 | - | ||
39 | - // 同步操作 | ||
40 | - while (true){ | ||
41 | - | ||
42 | - // 开始同步 | ||
43 | - try { | ||
44 | - sync(); | ||
45 | - }catch (Throwable $e){ | ||
46 | - logs($e->getMessage(),LOG_PATH.'/'.$worker_id.'_'.co::getCid().'.log'); | ||
47 | - } | ||
48 | - | ||
49 | - // 是否停止 | ||
50 | - if($redis->get(RUNNING_REDIS_KEY) == 'stop'){ | ||
51 | - break; | ||
52 | - } | ||
53 | - // 阻塞1秒 | ||
54 | - co::sleep(1); | ||
55 | - } | ||
56 | - | ||
57 | - // 协程完成后执行的函数 | ||
58 | - co::defer(function () use ($cid){ | ||
59 | - _echo('正常关闭协程('.co::getCid().')'); | ||
60 | - unset($cid[co::getCid()]); | ||
61 | - }); | ||
62 | - | ||
63 | - }); | ||
64 | - } | ||
65 | 85 | ||
66 | -// }); | 86 | + $i = 0; |
87 | + $email_total = $table->get('etotal','val');//邮件总数量 | ||
88 | + $isRunMaxCNum = 1; // 允许最大协程数量,如果为0则停止所有协程工作,相当于停止脚本 | ||
67 | // 是否退出进程 | 89 | // 是否退出进程 |
68 | while (true){ | 90 | while (true){ |
69 | - if($cid){ | ||
70 | - co::sleep(1); | ||
71 | - }else{ | 91 | + $i++; |
92 | + // 每10秒 验证一次邮箱数量,好控制协程的数量 | ||
93 | + if($i>=10){ | ||
94 | + $email_total = $table->get('etotal','val'); | ||
95 | + $i = 0; | ||
96 | + } | ||
97 | + | ||
98 | + if(!$email_total){ | ||
99 | + break; | ||
100 | + } | ||
101 | + | ||
102 | + // 每个协程 分配 10个邮箱任务 | ||
103 | + $cnum = ceil($email_total/40); | ||
104 | + // 当前协程的数量 | ||
105 | + $nowCnum = count($cid); | ||
106 | + // 说明 需要新的协程了 | ||
107 | + if($cnum > $nowCnum){ | ||
108 | + // 开启所需要的协程数量 | ||
109 | + foreach (range(0,$cnum-$nowCnum) as $v){ | ||
110 | + // 启动一个协程 | ||
111 | + create_coroutine($cid,$isRunMaxCNum,$worker_id); | ||
112 | + } | ||
113 | + } | ||
114 | + // 暂时没有实现 减少协程数量操作 | ||
115 | +// else if ($cnum < $nowCnum){ | ||
116 | +// // 说明 协程数量过多,小于了1个协程处理10个邮箱的,资源闲置情况 | ||
117 | +// // 销毁多余协程 | ||
118 | +// $isRunMaxCNum = $nowCnum - $cnum; | ||
119 | +// } | ||
120 | + | ||
121 | + // 每3秒检查一次是否要停止 协程 | ||
122 | + if($i%3 === 0){ | ||
123 | +// _echo('是否收到退出信号:'.$table->get('stop','val')); | ||
124 | + if ($table->get('stop','val')){ | ||
125 | + // 停止 | ||
126 | + $isRunMaxCNum = 0; | ||
127 | + } | ||
128 | + } | ||
129 | + | ||
130 | + // 这个是检查 cid的如果协程全部退出,则退出进程 | ||
131 | + co::sleep(1); | ||
132 | + // 跳出无限循环了 | ||
133 | + if(!$cid){ | ||
72 | _echo('正常关闭进程('.$worker_id.')'); | 134 | _echo('正常关闭进程('.$worker_id.')'); |
73 | // 关闭当前进程 | 135 | // 关闭当前进程 |
74 | - $pool->shutdown(); | 136 | +// $pool->shutdown(); |
75 | break; | 137 | break; |
76 | } | 138 | } |
77 | } | 139 | } |
@@ -87,12 +149,55 @@ function start(){ | @@ -87,12 +149,55 @@ function start(){ | ||
87 | } | 149 | } |
88 | 150 | ||
89 | /** | 151 | /** |
152 | + * 创建协程 | ||
153 | + * @param array $cid | ||
154 | + * @param int $isRunMaxCNum | ||
155 | + * @param $worker_id | ||
156 | + * @author:dc | ||
157 | + * @time 2023/2/14 17:04 | ||
158 | + */ | ||
159 | +function create_coroutine(array &$cid,int &$isRunMaxCNum,$worker_id){ | ||
160 | + go(function () use (&$cid,&$isRunMaxCNum,$worker_id){ | ||
161 | + // 协程id | ||
162 | + $cid[co::getCid()] = co::getCid(); | ||
163 | + | ||
164 | + // 同步操作 | ||
165 | + while (true){ | ||
166 | + // 是否退出协程 | ||
167 | + if(!$isRunMaxCNum){ | ||
168 | + _echo('协程('.co::getCid().'): stop '.$isRunMaxCNum); | ||
169 | + break; | ||
170 | + } | ||
171 | + | ||
172 | + // 开始同步 | ||
173 | + try { | ||
174 | + sync(); | ||
175 | + }catch (\Throwable $e){ | ||
176 | + _echo($e->getMessage()); | ||
177 | + logs($e->getMessage().PHP_EOL.$e->getTraceAsString(),LOG_PATH.'/'.$worker_id.'_'.co::getCid().'.log'); | ||
178 | + } | ||
179 | + | ||
180 | + // 阻塞1秒 | ||
181 | + co::sleep(1); | ||
182 | + } | ||
183 | + | ||
184 | + // 协程完成后执行的函数 | ||
185 | + co::defer(function () use (&$cid){ | ||
186 | + _echo('正常关闭协程('.co::getCid().')'); | ||
187 | + unset($cid[co::getCid()]); | ||
188 | + }); | ||
189 | + | ||
190 | + }); | ||
191 | +} | ||
192 | + | ||
193 | + | ||
194 | +/** | ||
90 | * 开始同步 | 195 | * 开始同步 |
91 | * @author:dc | 196 | * @author:dc |
92 | * @time 2023/2/13 9:42 | 197 | * @time 2023/2/13 9:42 |
93 | */ | 198 | */ |
94 | function sync(){ | 199 | function sync(){ |
95 | - db()->first(); | 200 | + co::sleep(1); |
96 | } | 201 | } |
97 | 202 | ||
98 | 203 | ||
@@ -106,7 +211,7 @@ switch ($argv[1]){ | @@ -106,7 +211,7 @@ switch ($argv[1]){ | ||
106 | case 'stop':{ | 211 | case 'stop':{ |
107 | \Co\run(function (){ | 212 | \Co\run(function (){ |
108 | echo "正在退出程序...\n"; | 213 | echo "正在退出程序...\n"; |
109 | - swoole_redis()->set(RUNNING_REDIS_KEY,'stop'); | 214 | + redis()->set(RUNNING_REDIS_KEY,'stop'); |
110 | while (true){ | 215 | while (true){ |
111 | $num = exec("ps -ef | grep \"sync_email.php start\" | grep -v grep | wc -l"); | 216 | $num = exec("ps -ef | grep \"sync_email.php start\" | grep -v grep | wc -l"); |
112 | if(!$num){ | 217 | if(!$num){ |
@@ -128,7 +233,6 @@ switch ($argv[1]){ | @@ -128,7 +233,6 @@ switch ($argv[1]){ | ||
128 | } | 233 | } |
129 | } | 234 | } |
130 | 235 | ||
131 | -exit(); | ||
132 | 236 | ||
133 | 237 | ||
134 | 238 |
@@ -4,8 +4,8 @@ error_reporting(E_ERROR | E_NOTICE); | @@ -4,8 +4,8 @@ error_reporting(E_ERROR | E_NOTICE); | ||
4 | 4 | ||
5 | // 开启4个进程 | 5 | // 开启4个进程 |
6 | define('WORKER_NUM',4); | 6 | define('WORKER_NUM',4); |
7 | -// 开启100个协程 | ||
8 | -define('COROUTINE_NUM',100); | 7 | +// 开启最大1000个协程 |
8 | +define('COROUTINE_MAX_NUM',1000); | ||
9 | // 是否继续运行 | 9 | // 是否继续运行 |
10 | define('RUNNING_REDIS_KEY','worker_is_running'); | 10 | define('RUNNING_REDIS_KEY','worker_is_running'); |
11 | // 记录日志的目录 | 11 | // 记录日志的目录 |
@@ -37,8 +37,13 @@ class Home { | @@ -37,8 +37,13 @@ class Home { | ||
37 | app()->e('smtp_verify_error'); | 37 | app()->e('smtp_verify_error'); |
38 | } | 38 | } |
39 | 39 | ||
40 | + // 进行远程登录,验证 | ||
41 | + | ||
42 | + | ||
40 | // 查询数据 | 43 | // 查询数据 |
41 | $model = db()->first(\Model\email::first($formData['email'])); | 44 | $model = db()->first(\Model\email::first($formData['email'])); |
45 | + | ||
46 | + | ||
42 | if(!$model){ | 47 | if(!$model){ |
43 | $model = new Email(); | 48 | $model = new Email(); |
44 | $model->email = $formData['email']; | 49 | $model->email = $formData['email']; |
@@ -105,6 +105,23 @@ class DbPool { | @@ -105,6 +105,23 @@ class DbPool { | ||
105 | 105 | ||
106 | } | 106 | } |
107 | 107 | ||
108 | + /** | ||
109 | + * 统计数量 | ||
110 | + * @param string $sql | ||
111 | + * @return int | ||
112 | + * @author:dc | ||
113 | + * @time 2023/2/14 16:19 | ||
114 | + */ | ||
115 | + public function count(string $sql):int{ | ||
116 | + $query = $this->client->prepare($sql); | ||
117 | + | ||
118 | + if($query->execute()){ | ||
119 | + return $query->fetch(\PDO::FETCH_COLUMN); | ||
120 | + } | ||
121 | + | ||
122 | + return 0; | ||
123 | + } | ||
124 | + | ||
108 | 125 | ||
109 | /** | 126 | /** |
110 | * 查询一条数据 | 127 | * 查询一条数据 |
lib/Mail/Body.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace Helper\Mail; | ||
4 | + | ||
5 | +use Helper\Mail\MailFun; | ||
6 | + | ||
7 | +/** | ||
8 | + * 解析邮件body内容 | ||
9 | + * 通过 fetch msgno RFC822.text 获取到的内容 | ||
10 | + * 此内容包含html 文本 附件 | ||
11 | + * @author:dc | ||
12 | + * @time 2022/8/12 9:15 | ||
13 | + * Class Body | ||
14 | + * @package App\Mail\lib | ||
15 | + */ | ||
16 | +class Body { | ||
17 | + | ||
18 | + /** | ||
19 | + * @var string | ||
20 | + */ | ||
21 | + private $body; | ||
22 | + | ||
23 | + /** | ||
24 | + * | ||
25 | + * @var array | ||
26 | + */ | ||
27 | + private $item = []; | ||
28 | + | ||
29 | + /** | ||
30 | + * 保存的目录 | ||
31 | + * @var string | ||
32 | + */ | ||
33 | + private $fileSavePath; | ||
34 | + | ||
35 | + | ||
36 | + /** | ||
37 | + * Body constructor. | ||
38 | + * @param string $body | ||
39 | + * @param string $fileSavePath | ||
40 | + */ | ||
41 | + public function __construct(string $body, string $fileSavePath='/') | ||
42 | + { | ||
43 | + $this->body = $body = trim($body); | ||
44 | + | ||
45 | + $this->fileSavePath = $fileSavePath; | ||
46 | + | ||
47 | + // 这个是描述特殊文本 | ||
48 | + if(strpos($body,'This is a multi-part message in MIME format.')===0){ | ||
49 | + $body = trim($body,'This is a multi-part message in MIME format.'); | ||
50 | + $body = trim($body); | ||
51 | + } | ||
52 | + | ||
53 | + // 163 有 | ||
54 | + if(strpos($body,'------=_Part')!==false){ | ||
55 | + $this->parse($body,'------=_Part'); | ||
56 | + } | ||
57 | + elseif (mb_strpos($body,'------=_NextPart')!==false){ | ||
58 | + $this->parse($body,'------=_NextPart'); | ||
59 | + } | ||
60 | + elseif (mb_strpos($body,'----_NmP')!==false){ | ||
61 | + $this->parse($body,'----_NmP'); | ||
62 | + } | ||
63 | + elseif (mb_strpos($body,'--_=_swift')!==false){ | ||
64 | + $this->parse($body,'--_=_swift'); | ||
65 | + } | ||
66 | + elseif (mb_strpos($body,'----==_mimepart')!==false){ | ||
67 | + $this->parse($body,'----==_mimepart'); | ||
68 | + } | ||
69 | + elseif (mb_strpos($body,'--------------Boundary')!==false){ | ||
70 | + $this->parse($body,'--------------Boundary'); | ||
71 | + } | ||
72 | + elseif (mb_strpos($body,'--=-')!==false){ | ||
73 | + $this->parse($body,'--=-'); | ||
74 | + } | ||
75 | + // 很多--开始的,且不规则 | ||
76 | + elseif(strpos($body,'--')===0){ | ||
77 | + // 获取第一行 | ||
78 | + $tag = $this->body_get_tag($body,'--'); | ||
79 | + // 以第一行为标准 | ||
80 | + $this->parse($body,trim($tag)); | ||
81 | + } | ||
82 | + // 直接html | ||
83 | + elseif (mb_strpos($body,'<')===0){ | ||
84 | + $body = quoted_printable_decode($body); | ||
85 | +// preg_match("/<meta(?!\s*(?:name|value)\s*=)(?:[^>]*?content\s*=[\s\"']*)?([^>]*?)[\s\"';]*charset\s*=[\s\"']*([^\s\"'\/>]*)/",$body,$icon); | ||
86 | +// if(!empty($icon[2])){ | ||
87 | +// // 解码 | ||
88 | +// $body = mb_convert_encoding($body,'utf-8',$icon[2]); | ||
89 | +// } | ||
90 | + $this->setItem(['type'=>'text/html','body'=>$body]); | ||
91 | + } | ||
92 | + else{ | ||
93 | + // qq的是base64 | ||
94 | + if(rtrim($body,'=') == rtrim(base64_encode(base64_decode($body)),'=')){ | ||
95 | + $this->setItem(['type'=>'text/plain','body'=>base64_decode($body)]); | ||
96 | + }else{ | ||
97 | + $this->setItem(['type'=>'text/plain','body'=>$body]); | ||
98 | + } | ||
99 | + | ||
100 | + } | ||
101 | + | ||
102 | + | ||
103 | + } | ||
104 | + | ||
105 | + /** | ||
106 | + * 获取标签 | ||
107 | + * @param $body | ||
108 | + * @param $tag | ||
109 | + * @return mixed|string | ||
110 | + * @author:dc | ||
111 | + * @time 2022/8/12 10:49 | ||
112 | + */ | ||
113 | + private function body_get_tag($body,$tag){ | ||
114 | + preg_match("/{$tag}[\w\W].*/i",$body,$result); | ||
115 | + if(!empty($result[0])) { | ||
116 | + return $result[0]; | ||
117 | + } | ||
118 | + return ''; | ||
119 | + } | ||
120 | + | ||
121 | + /** | ||
122 | + * @param $item | ||
123 | + */ | ||
124 | + private function setItem($item): void | ||
125 | + { | ||
126 | + $this->item[] = $item; | ||
127 | + } | ||
128 | + | ||
129 | + | ||
130 | + /** | ||
131 | + * @return [] | ||
132 | + */ | ||
133 | + public function getItem(): array | ||
134 | + { | ||
135 | + return $this->item; | ||
136 | + } | ||
137 | + | ||
138 | + | ||
139 | + /** | ||
140 | + * 开始解析 | ||
141 | + * @param string $body | ||
142 | + * @param string $tag | ||
143 | + * @return array | ||
144 | + * @author:dc | ||
145 | + * @time 2022/8/12 9:50 | ||
146 | + */ | ||
147 | + private function parse(string $body, string $tag){ | ||
148 | + | ||
149 | + // 删除第一个标签前面的数据,一般情况无用 | ||
150 | + $body = mb_substr($this->body,strpos($this->body,$tag),99999999999); | ||
151 | + | ||
152 | + // 有附件的情况 | ||
153 | + preg_match('/boundary="([-_A-Za-z0-9=\.]{1,})"/i',$body,$boundary); | ||
154 | + if($boundary[0]??''){ | ||
155 | + $body = str_replace($boundary[0],'',$body); | ||
156 | +// $body = mb_substr($body,mb_strpos($body,$boundary[0])+strlen($boundary[0]),99999999999); | ||
157 | + } | ||
158 | + // 附件情况 | ||
159 | + if(!empty($boundary[1])){ | ||
160 | + preg_match_all('/.*'.$boundary[1].'.*/i',$body,$boundary_tag); | ||
161 | + $body = str_replace($boundary_tag[0],'{--tag--}',$body); | ||
162 | + } | ||
163 | + // 查找tag块 | ||
164 | + preg_match_all("/(".$tag.".*+\n)/i",$body."\r\n\r\n",$he); | ||
165 | + // 把每个tag块分开成数组 | ||
166 | + if(!empty($he[0])){ | ||
167 | + foreach ($he[0] as $hk=>$h){ | ||
168 | + $he[0][$hk] = trim($h); | ||
169 | + } | ||
170 | + arsort($he[0]); | ||
171 | + $body = str_replace($he[0],'{--tag--}',$body); | ||
172 | + } | ||
173 | + $body = explode('{--tag--}',$body); | ||
174 | + // 处理 | ||
175 | + foreach ($body as $key=>$item){ | ||
176 | + $data = []; | ||
177 | + | ||
178 | + $item = trim($item); | ||
179 | + // 附件的头 | ||
180 | + if(!$item) { continue; } | ||
181 | + | ||
182 | + // 邮件体包含邮件体 | ||
183 | + if(preg_match("/boundary=\"([-_a-z0-9]{5,})\"/Ui",$item,$bm)){ | ||
184 | + if (strpos($item,$bm[1].'--')!==false){ | ||
185 | + $data = (new self('--'.$bm[1]."\r\n".$item,$this->fileSavePath))->getItem(); | ||
186 | +// $this->setItem($data); | ||
187 | + // 合并邮件体 | ||
188 | + $this->item = array_merge($this->item,$data); | ||
189 | + } | ||
190 | + continue; | ||
191 | + } | ||
192 | + | ||
193 | + // 先解码解码 | ||
194 | + $encode = $this->body_match_tag('Content-Transfer-Encoding:',$item); | ||
195 | + if($encode){ | ||
196 | + $data['encode'] = strtolower($encode['text']); | ||
197 | + $item = str_replace($encode['origin'],'',$item); | ||
198 | + } | ||
199 | + | ||
200 | + // 内容类型 | ||
201 | + $type = $this->preg_match_type($item); | ||
202 | + if($type){ | ||
203 | + $data['type'] = strtolower($type['type']); | ||
204 | + // 编码 | ||
205 | + if(isset($type['charset'])){ | ||
206 | + $data['charset'] = strtolower($type['charset']); | ||
207 | + } | ||
208 | + // nama。附件 | ||
209 | + if(isset($type['name'])){ | ||
210 | + $data['name'] = $type['name']; | ||
211 | + } | ||
212 | + // 删除 | ||
213 | + $item = str_replace($type['origin'],'',$item); | ||
214 | + } | ||
215 | + | ||
216 | + // | ||
217 | + if(empty($data['charset'])){ | ||
218 | + // 编码 | ||
219 | + $code = $this->preg_match_charset($item); | ||
220 | + if($code){ | ||
221 | + $data['charset'] = strtolower($code['charset']); | ||
222 | + | ||
223 | + $item = str_replace($code['origin'],'',$item); | ||
224 | + } | ||
225 | + } | ||
226 | + | ||
227 | + // 先匹配留存文件名称 | ||
228 | + preg_match('/filename="(\w?.*)"/',$item,$filename); | ||
229 | + if(!empty($filename[1])){ | ||
230 | + $filename = MailFun::decodeMimeStr($filename[1]); | ||
231 | + } | ||
232 | + | ||
233 | + | ||
234 | + // 删除不需要的tag属性,如果需要进进行解析 | ||
235 | + $item = $this->body_remove_tag($item,'Content-Description:'); | ||
236 | + $item = $this->body_remove_tag($item,'Content-Disposition:'); | ||
237 | + $item = $this->body_remove_tag($item,'Mime-Version:'); | ||
238 | + | ||
239 | + $data['body'] = trim($item); | ||
240 | + | ||
241 | + if(!empty($data['type'])){ | ||
242 | + // 邮件头 | ||
243 | + if($data['type'] == 'multipart/alternative'){ | ||
244 | + | ||
245 | + } | ||
246 | + // 是文本还是附件 | ||
247 | + else if(strpos($data['type'],'text/') === 0 ){ | ||
248 | + // body解密 | ||
249 | + switch($data['encode']??''){ | ||
250 | + case 'base64': { | ||
251 | + $data['body'] = base64_decode($data['body']); | ||
252 | + break; | ||
253 | + } | ||
254 | + case 'quoted-printable': { | ||
255 | + $data['body'] = quoted_printable_decode($data['body']); | ||
256 | + break; | ||
257 | + } | ||
258 | + case '8bit': { | ||
259 | + try { | ||
260 | + $data['body'] = DeCoding::de8bit($data['body']); | ||
261 | + $data['body'] = quoted_printable_decode($data['body']); | ||
262 | + }catch (\Throwable $e){ | ||
263 | + | ||
264 | + } | ||
265 | + | ||
266 | + break; | ||
267 | + } | ||
268 | + } | ||
269 | + | ||
270 | + // 转码 | ||
271 | +// if(isset($data['charset']) && $data['charset']){ | ||
272 | +// $debody = @mb_convert_encoding($data['body'],'utf-8',$data['charset']); | ||
273 | +// if($debody){ | ||
274 | +// $data['body'] = $debody; | ||
275 | +// $debody = null; | ||
276 | +// } | ||
277 | +// } | ||
278 | + | ||
279 | + | ||
280 | + } | ||
281 | + // 系统退信//里面包含了发送邮件所有内容,这里不记录 | ||
282 | + elseif (strpos($data['type'],'message') === 0){ | ||
283 | + $data['body'] = '';// 一般不需要这些内容,如有需要就要重新解析 | ||
284 | + } | ||
285 | + elseif (!empty($data['type']) && $data['body']){ | ||
286 | + // 解析附件 | ||
287 | + $data = $this->parseFile($data,$filename); | ||
288 | + } | ||
289 | + } | ||
290 | + | ||
291 | + $this->setItem($data); | ||
292 | + | ||
293 | + } | ||
294 | + | ||
295 | + } | ||
296 | + | ||
297 | + | ||
298 | + /** | ||
299 | + * 解析文件 | ||
300 | + * @param $item | ||
301 | + * @return array|mixed | ||
302 | + * @author:dc | ||
303 | + * @time 2022/8/12 10:40 | ||
304 | + */ | ||
305 | + private function parseFile($item,$filename=''){ | ||
306 | + $data = []; | ||
307 | + // 查找文件名 | ||
308 | + | ||
309 | + $data['filename'] = $this->file_save_name($item['body'],'filename'); | ||
310 | + $data['name'] = $this->file_save_name($item['body'],'name'); | ||
311 | + $data['name'] = $data['name'] ? : ($item['name']??$filename); | ||
312 | + $data['filename'] = $data['filename'] ? : $data['name']; | ||
313 | + | ||
314 | + // 是否有文件名 | ||
315 | + if(empty($data['filename']) || strpos($data['filename'],'.')===false){ | ||
316 | + return $item; | ||
317 | + } | ||
318 | + | ||
319 | + $ext = explode('.',$data['filename']); | ||
320 | + $ext = end($ext); | ||
321 | + | ||
322 | +// if(!empty($item['type'])){ | ||
323 | +// // 文件类型来判断后缀 | ||
324 | +// // // download it from http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types | ||
325 | +// if(is_readable(__DIR__.'/mime.types')){ | ||
326 | +// $f = fopen(__DIR__.'/mime.types','r'); | ||
327 | +// while(!feof($f)){ | ||
328 | +// $fext = fgets($f); | ||
329 | +// if($fext){ | ||
330 | +// $fext = strtolower($fext); | ||
331 | +// $item['type'] = strtolower($item['type']); | ||
332 | +// // 找到了类型后缀 | ||
333 | +// if(strpos($fext,$item['type']) === 0){ | ||
334 | +// $ext = trim(str_replace($item['type'],'',$fext)); | ||
335 | +// break;//找到了要跳出循环 | ||
336 | +// } | ||
337 | +// } | ||
338 | +// } | ||
339 | +// // 关闭文件 | ||
340 | +// fclose($f); | ||
341 | +// } | ||
342 | +// } | ||
343 | + | ||
344 | + // 找不到后缀,说明不是文件 | ||
345 | +// if(empty($ext)){ | ||
346 | + // 文件后缀 | ||
347 | +// $ext = explode('.',$data['filename']); | ||
348 | +// $ext = count($ext) > 1 ? ($ext[count($ext)-1]??'') : ''; | ||
349 | + // 直接返回 | ||
350 | +// return $item['body']; | ||
351 | +// } | ||
352 | + | ||
353 | + | ||
354 | + // content id | ||
355 | + preg_match("/Content-ID:[\s].*<[\w\W]{1,}>/i",$item['body'],$result); | ||
356 | + if (!empty($result[0])){ | ||
357 | + $data['content-id'] = explode('<',$result[0]); | ||
358 | + $data['content-id'] = $data['content-id'][1]; | ||
359 | + $data['content-id'] = trim($data['content-id']); | ||
360 | + $data['content-id'] = trim($data['content-id'],'>'); | ||
361 | + | ||
362 | + $item['body'] = str_replace($result[0],'',$item['body']); | ||
363 | + } | ||
364 | + | ||
365 | + $item['body'] = str_replace($result,'',$item['body']); | ||
366 | + | ||
367 | + | ||
368 | + $content = base64_decode(trim($item['body'])); | ||
369 | + | ||
370 | + if($content){ | ||
371 | + // 目录 | ||
372 | + $data['path'] = $this->fileSavePath; | ||
373 | + if(!is_dir($data['path'])){ | ||
374 | + mkdir($data['path'],0775,true); | ||
375 | + } | ||
376 | + $data['signName'] = md5($content).($ext ? '.'.$ext : ''); | ||
377 | + $data['path'] = $data['path'].'/'.$data['signName']; | ||
378 | + // 保存文件 | ||
379 | + @file_put_contents($data['path'],$content); | ||
380 | + } | ||
381 | + | ||
382 | + | ||
383 | + return $data; | ||
384 | + } | ||
385 | + | ||
386 | + // 获取文件名称 | ||
387 | + private function file_save_name(&$body,$tag){ | ||
388 | + preg_match('/'.$tag.'="[(\S\W.*\s.*)]{1,}"/i',$body,$result); | ||
389 | + if($result[0]??''){ | ||
390 | + $body = str_replace($result[0],'',$body); | ||
391 | + } | ||
392 | + $val = trim(str_replace([$tag.'=','"',"'"],'',$result[0]??'')); | ||
393 | + if ($val && strpos($val,'=?')===0){ | ||
394 | + | ||
395 | + $val = iconv_mime_decode($val,ICONV_MIME_DECODE_CONTINUE_ON_ERROR,'utf-8'); | ||
396 | + } | ||
397 | + | ||
398 | + return $val; | ||
399 | + } | ||
400 | + | ||
401 | + /** | ||
402 | + * 删除tag | ||
403 | + * @param $body | ||
404 | + * @param $tag | ||
405 | + * @return mixed|string|string[] | ||
406 | + * @author:dc | ||
407 | + * @time 2022/8/12 10:34 | ||
408 | + */ | ||
409 | + private function body_remove_tag($body,$tag){ | ||
410 | + preg_match("/{$tag}[\w\W].*/i",$body,$result); | ||
411 | + if(!empty($result[0])) { | ||
412 | + $body = str_replace($result, '', $body); | ||
413 | + } | ||
414 | + return $body; | ||
415 | + } | ||
416 | + | ||
417 | + /** | ||
418 | + * 读取编码 | ||
419 | + * @param $item | ||
420 | + * @return array | ||
421 | + * @author:dc | ||
422 | + * @time 2022/8/12 10:28 | ||
423 | + */ | ||
424 | + private static function preg_match_charset($item){ | ||
425 | + // 匹配内容 type | ||
426 | + preg_match('/charset[ \t]{0,}=[ \t]{0,}"?[ \t0-9a-zA-Z-]{1,}"?/i',$item,$result); | ||
427 | + | ||
428 | + if(!empty($result[0])){ | ||
429 | + $ret['origin'] = trim($result[0]); | ||
430 | + // charset | ||
431 | + $ret['charset'] = trim(str_replace(['charset','=','"',"'"],'',$ret['origin'])); | ||
432 | + | ||
433 | + return $ret; | ||
434 | + } | ||
435 | + return []; | ||
436 | + } | ||
437 | + | ||
438 | + /** | ||
439 | + * 解析type | ||
440 | + * @param $item | ||
441 | + * @return array | ||
442 | + * @author:dc | ||
443 | + * @time 2022/8/12 10:26 | ||
444 | + */ | ||
445 | + private function preg_match_type($item){ | ||
446 | + // 匹配内容 type | ||
447 | + preg_match("/Content-Type:[\w\W].*/i",$item,$result); | ||
448 | + | ||
449 | + if(!empty($result[0])){ | ||
450 | + $ret['origin'] = trim($result[0]); | ||
451 | + // type | ||
452 | + $type = str_replace(['Content-Type:','"',"'"],'',$ret['origin']); | ||
453 | + $type = explode(';',$type); | ||
454 | + // 类型 | ||
455 | + $ret['type'] = trim($type[0]); | ||
456 | + if(isset($type[1]) && $type[1]){ | ||
457 | + // 编码 | ||
458 | + $r = explode('=',$type[1]); | ||
459 | + $ret[strtolower(trim($r[0]))] = trim($r[1]??''); | ||
460 | + } | ||
461 | + return $ret; | ||
462 | + } | ||
463 | + return []; | ||
464 | + } | ||
465 | + | ||
466 | + /** | ||
467 | + * 匹配tag | ||
468 | + * @param $tag | ||
469 | + * @param $item | ||
470 | + * @return array | ||
471 | + * @author:dc | ||
472 | + * @time 2022/8/12 10:05 | ||
473 | + */ | ||
474 | + private function body_match_tag($tag,$item){ | ||
475 | + // tag Content-Transfer-Encoding: | ||
476 | + preg_match("/".$tag."[\w\W].*/i",$item,$result); | ||
477 | + | ||
478 | + if(!empty($result[0])){ | ||
479 | + $ret['origin'] = trim($result[0]); | ||
480 | + // charset | ||
481 | + $ret['text'] = trim(str_replace([$tag,'"',"'"],'',$ret['origin'])); | ||
482 | + | ||
483 | + return $ret; | ||
484 | + } | ||
485 | + return []; | ||
486 | + } | ||
487 | + | ||
488 | + | ||
489 | +} |
lib/Mail/DeCoding.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace Helper\Mail; | ||
4 | + | ||
5 | +/** | ||
6 | + * 解码邮件内容 | ||
7 | + * @author:dc | ||
8 | + * @time 2022/8/12 9:33 | ||
9 | + * Class DeCoding | ||
10 | + * @package App\Mail\lib\MailParse | ||
11 | + */ | ||
12 | +class DeCoding { | ||
13 | + | ||
14 | + | ||
15 | + /** | ||
16 | + * @param $sText | ||
17 | + * @param bool $bEmulate_imap_8bit | ||
18 | + * @return string | ||
19 | + * @author:dc | ||
20 | + * @time 2022/8/12 9:34 | ||
21 | + */ | ||
22 | + public static function de8bit($sText,$bEmulate_imap_8bit=true) { | ||
23 | + // split text into lines | ||
24 | + $aLines=explode(chr(13).chr(10),$sText); | ||
25 | + | ||
26 | + for ($i=0;$i<count($aLines);$i++) { | ||
27 | + $sLine =& $aLines[$i]; | ||
28 | + if (strlen($sLine)===0) continue; // do nothing, if empty | ||
29 | + | ||
30 | + $sRegExp = '/[^\x09\x20\x21-\x3C\x3E-\x7E]/e'; | ||
31 | + | ||
32 | + // imap_8bit encodes x09 everywhere, not only at lineends, | ||
33 | + // for EBCDIC safeness encode !"#$@[\]^`{|}~, | ||
34 | + // for complete safeness encode every character :) | ||
35 | + if ($bEmulate_imap_8bit) | ||
36 | + $sRegExp = '/[^\x20\x21-\x3C\x3E-\x7E]/e'; | ||
37 | + | ||
38 | + $sReplmt = 'sprintf( "=%02X", ord ( "$0" ) ) ;'; | ||
39 | + $sLine = preg_replace( $sRegExp, $sReplmt, $sLine ); | ||
40 | + | ||
41 | + // encode x09,x20 at lineends | ||
42 | + { | ||
43 | + $iLength = strlen($sLine); | ||
44 | + $iLastChar = ord($sLine{$iLength-1}); | ||
45 | + | ||
46 | + // !!!!!!!! | ||
47 | + // imap_8_bit does not encode x20 at the very end of a text, | ||
48 | + // here is, where I don't agree with imap_8_bit, | ||
49 | + // please correct me, if I'm wrong, | ||
50 | + // or comment next line for RFC2045 conformance, if you like | ||
51 | + if (!($bEmulate_imap_8bit && ($i==count($aLines)-1))) | ||
52 | + | ||
53 | + if (($iLastChar==0x09)||($iLastChar==0x20)) { | ||
54 | + $sLine{$iLength-1}='='; | ||
55 | + $sLine .= ($iLastChar==0x09)?'09':'20'; | ||
56 | + } | ||
57 | + } // imap_8bit encodes x20 before chr(13), too | ||
58 | + // although IMHO not requested by RFC2045, why not do it safer :) | ||
59 | + // and why not encode any x20 around chr(10) or chr(13) | ||
60 | + if ($bEmulate_imap_8bit) { | ||
61 | + $sLine=str_replace(' =0D','=20=0D',$sLine); | ||
62 | + //$sLine=str_replace(' =0A','=20=0A',$sLine); | ||
63 | + //$sLine=str_replace('=0D ','=0D=20',$sLine); | ||
64 | + //$sLine=str_replace('=0A ','=0A=20',$sLine); | ||
65 | + } | ||
66 | + | ||
67 | + // finally split into softlines no longer than 76 chars, | ||
68 | + // for even more safeness one could encode x09,x20 | ||
69 | + // at the very first character of the line | ||
70 | + // and after soft linebreaks, as well, | ||
71 | + // but this wouldn't be caught by such an easy RegExp | ||
72 | + preg_match_all( '/.{1,73}([^=]{0,2})?/', $sLine, $aMatch ); | ||
73 | + $sLine = implode( '=' . chr(13).chr(10), $aMatch[0] ); // add soft crlf's | ||
74 | + } | ||
75 | + | ||
76 | + // join lines into text | ||
77 | + return implode(chr(13).chr(10),$aLines); | ||
78 | + } | ||
79 | +} |
lib/Mail/Imap.php
0 → 100644
1 | +<?php | ||
2 | +declare(strict_types=1); | ||
3 | + | ||
4 | +namespace Helper\Mail; | ||
5 | + | ||
6 | +use Helper\Mail\Body; | ||
7 | + | ||
8 | + | ||
9 | +/** | ||
10 | + * imap协议直连服务器无需 imap扩展 | ||
11 | + * @time 2022/8/5 14:17 | ||
12 | + * Class Imap | ||
13 | + * @package App\Mail\lib\socket | ||
14 | + */ | ||
15 | +class Imap { | ||
16 | + | ||
17 | + /** | ||
18 | + * @var resource | ||
19 | + */ | ||
20 | + private $socket; | ||
21 | + | ||
22 | + /** | ||
23 | + * ssl://imap.qq.com:993 | ||
24 | + * @var string | ||
25 | + */ | ||
26 | + private $host; | ||
27 | + | ||
28 | + /** 邮箱 | ||
29 | + * @var | ||
30 | + */ | ||
31 | + private $username; | ||
32 | + | ||
33 | + /** | ||
34 | + * 邮箱密码,单独设置的imap密码 | ||
35 | + * @var | ||
36 | + */ | ||
37 | + private $password; | ||
38 | + | ||
39 | + /** | ||
40 | + * 请求时增加的tag | ||
41 | + * @var int | ||
42 | + */ | ||
43 | + private $tagNum = 0; | ||
44 | + | ||
45 | + /** | ||
46 | + * 标签名称 | ||
47 | + * @var string | ||
48 | + */ | ||
49 | + private $tagName = 'A'; | ||
50 | + | ||
51 | + /** | ||
52 | + * imap服务器设置id 邮箱邮件服务器是必须的 | ||
53 | + * @var string[] | ||
54 | + */ | ||
55 | + private $imapId = [ | ||
56 | + 'name' => 'global so Client', | ||
57 | + 'version' => '1', | ||
58 | + 'os' => 'global so', | ||
59 | + 'os-version' => '1.0' | ||
60 | + ]; | ||
61 | + | ||
62 | + /** | ||
63 | + * 用户的id,email表 | ||
64 | + * @var int | ||
65 | + */ | ||
66 | + public $id = 0; | ||
67 | + | ||
68 | + /** | ||
69 | + * 超时时间 | ||
70 | + * @var int | ||
71 | + */ | ||
72 | + private $timeout = 30; | ||
73 | + | ||
74 | + /** | ||
75 | + * 搜索字段,标题,邮件主题 | ||
76 | + */ | ||
77 | + const SEARCH_FILED_SUBJECT = 'SUBJECT'; | ||
78 | + | ||
79 | + /** | ||
80 | + * 搜索字段,发件人 | ||
81 | + */ | ||
82 | + const SEARCH_FILED_FROM = 'FROM'; | ||
83 | + | ||
84 | + /** | ||
85 | + * 搜索字段,收件人 | ||
86 | + */ | ||
87 | + const SEARCH_FILED_TO = 'TO'; | ||
88 | + | ||
89 | +// const SEARCH_FILED_SUBJECT = 'RFC822.TEXT'; | ||
90 | + | ||
91 | + | ||
92 | + /** | ||
93 | + * 邮件便签 | ||
94 | + * @var string[] | ||
95 | + */ | ||
96 | + public $flags = [ | ||
97 | + 'SEEN' => '\\Seen', // 已读 | ||
98 | + 'DELETED' => '\\Deleted', //删除 | ||
99 | + 'ANSWERED' => '\\Answered',//已回复 | ||
100 | + 'DRAFT' => '\\Draft',//草稿 | ||
101 | + 'FLAGGED' => '\\Flagged',//星标 | ||
102 | + 'FORWARDED' => '$Forwarded', | ||
103 | + 'MDNSENT' => '$MDNSent', | ||
104 | + '*' => '\\*', | ||
105 | + ]; | ||
106 | + | ||
107 | + /** | ||
108 | + * 已读 标记 | ||
109 | + */ | ||
110 | + const FLAGS_SEEN = 'SEEN'; | ||
111 | + | ||
112 | + /** | ||
113 | + * 删除 标记 | ||
114 | + */ | ||
115 | + const FLAGS_DELETED = 'DELETED'; | ||
116 | + | ||
117 | + /** | ||
118 | + * 已回复 标记 | ||
119 | + */ | ||
120 | + const FLAGS_ANSWERED = 'ANSWERED'; | ||
121 | + | ||
122 | + /** | ||
123 | + * 草稿 标记 | ||
124 | + */ | ||
125 | + const FLAGS_DRAFT = 'DRAFT'; | ||
126 | + | ||
127 | + /** | ||
128 | + * 星标 标记 | ||
129 | + */ | ||
130 | + const FLAGS_FLAGGED = 'FLAGGED'; | ||
131 | + | ||
132 | + /** | ||
133 | + * 添加邮件标签 | ||
134 | + */ | ||
135 | + const FLAGS_APPEND = '+'; | ||
136 | + | ||
137 | + /** | ||
138 | + * 删除邮件标签 | ||
139 | + */ | ||
140 | + const FLAGS_REMOVE = '-'; | ||
141 | + | ||
142 | + | ||
143 | + /** | ||
144 | + * 是否自动关闭 | ||
145 | + * @var bool | ||
146 | + */ | ||
147 | + private $auto_colse = true; | ||
148 | + | ||
149 | + /** | ||
150 | + * 调试模式 | ||
151 | + * @var bool | ||
152 | + */ | ||
153 | + private $debug = false; | ||
154 | + | ||
155 | + /** | ||
156 | + * 调试,记录日志的目录 | ||
157 | + * @var string | ||
158 | + */ | ||
159 | + private $debugWritePath = ''; | ||
160 | + | ||
161 | + /** | ||
162 | + * 登录imap服务器 | ||
163 | + * @param string $host ssl://imap.qq.com:993 imap.qq.com:143 | ||
164 | + * @param string $username 邮箱地址 xxxxx@xx.com | ||
165 | + * @param string $password 密码,此密码非邮箱登录密码,是imap服务器单独设置的密码 | ||
166 | + * @param bool $readOnly 是否以只读模式打开邮箱 | ||
167 | + * @return bool | ||
168 | + * @throws \Exception | ||
169 | + * @author:dc | ||
170 | + * @time 2022/11/25 11:06 | ||
171 | + */ | ||
172 | + public function login(string $host,string $username,string $password,bool $readOnly=false){ | ||
173 | + $this->host = $host; | ||
174 | + $this->username = $username; | ||
175 | + $this->password = $password; | ||
176 | + | ||
177 | + // 查看服务器所支持的功能列表 | ||
178 | +// $this->request('CAPABILITY'); | ||
179 | + | ||
180 | + // 设置id,必须在登录前,163是强制的 | ||
181 | + $strId = ''; | ||
182 | + foreach ($this->imapId as $k=>$str){ | ||
183 | + if(!is_array($str)){ | ||
184 | + $strId .= '"'.str_replace(['"',"'"],'',$k).'" "'.str_replace(['"',"'"],'',$str).'" '; | ||
185 | + } | ||
186 | + } | ||
187 | +// "name" "测试本地 Client" "version" "1" "os" "测试本地" "os-version" "1.0" | ||
188 | + $this->request('ID ('.trim($strId).')');// 这里就不处理命令返回的信箱了 | ||
189 | + | ||
190 | + // 登录 | ||
191 | + $result = $this->request("LOGIN {$username} {$password}"); | ||
192 | + | ||
193 | + //解析登录数据每个服务商返回的登录结果不一样,很难兼容 | ||
194 | + if($result[0] != 'ok'){ | ||
195 | + throw new \Exception('IMAP Login Error:'.end($result[1])); | ||
196 | + } | ||
197 | + | ||
198 | + // 是否是只读模式 | ||
199 | + // 只读模式不可操作邮箱任何内容,只可查看 | ||
200 | + if($readOnly){ | ||
201 | + $this->request('EXAMINE '.$username); | ||
202 | + } | ||
203 | + | ||
204 | + return true; | ||
205 | + } | ||
206 | + | ||
207 | + /** | ||
208 | + * email表的id | ||
209 | + * @return int | ||
210 | + * @author:dc | ||
211 | + * @time 2023/2/5 11:13 | ||
212 | + */ | ||
213 | + public function getId(){ | ||
214 | + return $this->id; | ||
215 | + } | ||
216 | + | ||
217 | + /** | ||
218 | + * 设置id | ||
219 | + * @param int $id | ||
220 | + * @author:dc | ||
221 | + * @time 2023/2/5 11:16 | ||
222 | + */ | ||
223 | + public function setId(int $id){ | ||
224 | + $this->id = $id; | ||
225 | + } | ||
226 | + | ||
227 | + | ||
228 | + /** | ||
229 | + * 退出当前操作的邮箱 | ||
230 | + * 一般情况不需要 | ||
231 | + * @return bool | ||
232 | + * @throws \Exception | ||
233 | + * @author:dc | ||
234 | + * @time 2022/11/25 10:46 | ||
235 | + */ | ||
236 | + public function loginOut():bool { | ||
237 | + return $this->request('LOGOUT')[0] == 'ok'; | ||
238 | + } | ||
239 | + | ||
240 | + /** | ||
241 | + * @param resource $socket | ||
242 | + */ | ||
243 | + public function setSocket($socket,$auto_colse=true): void | ||
244 | + { | ||
245 | + $this->socket = $socket; | ||
246 | + // 是否自动关闭 | ||
247 | + $this->auto_colse = $auto_colse; | ||
248 | + } | ||
249 | + | ||
250 | + | ||
251 | + /** | ||
252 | + * 删除带有delete标签的邮件,删除的邮件不可恢复。 | ||
253 | + * 类似清空 | ||
254 | + * @return bool | ||
255 | + * @throws \Exception | ||
256 | + * @author:dc | ||
257 | + * @time 2022/11/25 10:55 | ||
258 | + */ | ||
259 | + public function clearDelete():bool { | ||
260 | + return $this->request('EXPUNGE')[0] == 'ok'; | ||
261 | + } | ||
262 | + | ||
263 | + /** | ||
264 | + * [ | ||
265 | + [EXISTS] => 67 总邮件数 | ||
266 | + [RECENT] => 1 最新的邮件 | ||
267 | + [UIDVALIDITY] => 1 | ||
268 | + [FLAGS] => Array 此文件夹可以操控的标签 | ||
269 | + ( | ||
270 | + [0] => \Answered 回复 | ||
271 | + [1] => \Seen 已读 | ||
272 | + [2] => \Deleted 删除 | ||
273 | + [3] => \Draft 草稿 | ||
274 | + [4] => \Flagged 星标 | ||
275 | + ) | ||
276 | + | ||
277 | + [PERMANENTFLAGS] => Array | ||
278 | + ( | ||
279 | + [0] => \Answered | ||
280 | + [1] => \Seen | ||
281 | + [2] => \Deleted | ||
282 | + [3] => \Draft | ||
283 | + [4] => \Flagged | ||
284 | + ) | ||
285 | + ] | ||
286 | + * 选择文件夹 | ||
287 | + * @param string $folder | ||
288 | + * @return array | ||
289 | + * @throws \Exception | ||
290 | + * @author:dc | ||
291 | + * @time 2022/11/22 16:28 | ||
292 | + */ | ||
293 | + public function selectFolder($folder='INBOX'){ | ||
294 | + | ||
295 | + // 选择文件夹 | ||
296 | + $result = $this->request("SELECT \"{$folder}\""); | ||
297 | + if($result[0] != 'ok'){ | ||
298 | + throw new \Exception('select folder error:'.end($result[1])); | ||
299 | + } | ||
300 | + | ||
301 | + $list = []; | ||
302 | + foreach ($result[1] as $item){ | ||
303 | + $item = trim($item); | ||
304 | + // 总数量 | ||
305 | + if(preg_match("/^\* (\d+) EXISTS$/i",$item,$m)){ | ||
306 | + $list['EXISTS'] = $m[1]; | ||
307 | + } | ||
308 | + // 最近的 | ||
309 | + elseif (preg_match("/^\* (\d+) RECENT$/i",$item,$m)){ | ||
310 | + $list['RECENT'] = $m[1]; | ||
311 | + } | ||
312 | + // 未读 | ||
313 | + elseif (preg_match("/^\*.*\[UNSEEN (\d+)\]/i",$item,$m)){ | ||
314 | + $list['UNSEEN'] = $m[1]; | ||
315 | + } | ||
316 | + // tag | ||
317 | + elseif (preg_match("/^\* FLAGS \((.*)\)$/i",$item,$m)){ | ||
318 | + $list['FLAGS'] = explode(' ',$m[1]); | ||
319 | + } | ||
320 | + // 其他 | ||
321 | + elseif (preg_match("/^\*.*\[(.*)\]/i",$item,$m)){ | ||
322 | +// 是否有(),有小扩号就是数组 | ||
323 | +// * OK [PERMANENTFLAGS (\* \Answered \Flagged \Deleted \Draft \Seen)] Permanent flags | ||
324 | + if(preg_match("/\((.*)\)/i",$item,$m2)){ | ||
325 | + $em = explode(' ',$m[1]); | ||
326 | + $list[$em[0]] = explode(' ',$m2[1]); | ||
327 | + }else{ | ||
328 | + $em = explode(' ',$m[1]); | ||
329 | + $list[$em[0]] = $em[1]; | ||
330 | + } | ||
331 | + } | ||
332 | + } | ||
333 | + | ||
334 | + return $list; | ||
335 | + } | ||
336 | + | ||
337 | + /** | ||
338 | + * 关闭当前打开的文件夹, | ||
339 | + * 使用selectFolder后才可以使用此函数 | ||
340 | + * @return bool | ||
341 | + * @throws \Exception | ||
342 | + * @author:dc | ||
343 | + * @time 2022/11/25 10:40 | ||
344 | + */ | ||
345 | + public function closeFolder():bool{ | ||
346 | + return $this->request('CLOSE')['0'] == 'ok'; | ||
347 | + } | ||
348 | + | ||
349 | + /** | ||
350 | + * 搜索邮件,如果要获得列表,需要配合fetch使用 | ||
351 | + * @param array $criteria 搜索[key=>value,...] | ||
352 | + * @param bool $return_uid 是否返回uid,默认返回邮件编号 | ||
353 | + * @return array 返回的是搜索出来的uid,每个文件夹下面uid是唯一的 | ||
354 | + * @throws \Exception | ||
355 | + * @author:dc | ||
356 | + * @time 2022/11/24 15:46 | ||
357 | + */ | ||
358 | + public function search(array $criteria,$return_uid = false):array{ | ||
359 | + // 命令,是否返回uid | ||
360 | + $cmd = ($return_uid ? 'UID ' : '').'SEARCH'; | ||
361 | + | ||
362 | + foreach ($criteria as $k=>$v){ | ||
363 | + $v = addslashes($v); | ||
364 | + $cmd .= " {$k} \"{$v}\""; | ||
365 | + } | ||
366 | + | ||
367 | + // 获取搜索到的 uid | ||
368 | + $result = $this->request($cmd); | ||
369 | + | ||
370 | + if($result[0] != 'ok'){ | ||
371 | + throw new \Exception('search error:'.end($result[1])); | ||
372 | + } | ||
373 | + | ||
374 | + $uids = []; | ||
375 | + foreach ($result[1] as $item){ | ||
376 | + // 匹配uid | ||
377 | + if(preg_match("/^\* SEARCH ([0-9\s]{1,})$/i",$item,$m)){ | ||
378 | + $uids = array_merge($uids,explode(' ',$m[1])); | ||
379 | + } | ||
380 | + } | ||
381 | + | ||
382 | + return $uids; | ||
383 | + } | ||
384 | + | ||
385 | + | ||
386 | + /** | ||
387 | + * 设置标签,删除标签 | ||
388 | + * @param string|int|array $data 邮件的编号或者uid | ||
389 | + * @param array $flag 标记属性 [Imap::FLAGS_SEEN,..] | ||
390 | + * @param string $mod 删除或者添加 Imap::FLAGS_APPEND|Imap::FLAGS_REMOVE | ||
391 | + * @param bool $is_uid 是否使用uid进行标记 | ||
392 | + * @return bool | ||
393 | + * @throws \Exception | ||
394 | + * @author:dc | ||
395 | + * @time 2022/11/24 16:58 | ||
396 | + */ | ||
397 | + public function flags($data,array $flag,string $mod = self::FLAGS_APPEND,bool $is_uid = false):bool { | ||
398 | + | ||
399 | + if(is_array($data)){ | ||
400 | + $data = implode(',',$data); | ||
401 | + } | ||
402 | + | ||
403 | + // flags 标记 | ||
404 | + foreach ($flag as $k=>$item){ | ||
405 | + if(!isset($this->flags[$item])){ | ||
406 | + unset($flag[$k]); | ||
407 | + }else{ | ||
408 | + $flag[$k] = $this->flags[$item]; | ||
409 | + } | ||
410 | + } | ||
411 | + | ||
412 | + // 是否是规定中的值 | ||
413 | + if(!in_array($mod,[self::FLAGS_APPEND,self::FLAGS_REMOVE])){ | ||
414 | + throw new \Exception('set flags error: mod'); | ||
415 | + } | ||
416 | + | ||
417 | + // 请求标记 | ||
418 | + $result = $this->request(($is_uid?'UID ':'')."STORE {$data} {$mod}FLAGS.SILENT (".implode(' ',$flag).")"); | ||
419 | + | ||
420 | + return $result[0] == 'ok'; | ||
421 | + } | ||
422 | + | ||
423 | + /** | ||
424 | + * 获取邮箱所有文件夹 | ||
425 | + * @return array | ||
426 | + * @throws \Exception | ||
427 | + * @author:dc | ||
428 | + * @time 2022/11/24 17:20 | ||
429 | + */ | ||
430 | + public function getFolder():array { | ||
431 | + // 获取数据 | ||
432 | + $result = $this->request('LIST "" *'); | ||
433 | + | ||
434 | + $folder = []; | ||
435 | + foreach ($result[1] as $item){ | ||
436 | + // 解析源数据 | ||
437 | + if(preg_match('/^\* LIST \(([\\a-z\s]{0,})\) "(.*)" "(.*)"/Ui',$item,$m)){ | ||
438 | + $folder[] = [ | ||
439 | + 'parent' => $m[2], | ||
440 | + // 源文件夹名称,在进行 select的时候必须用未解析的文件夹名称 | ||
441 | + 'folder' => $m[3], | ||
442 | + // 解析过的文件夹名称 | ||
443 | + 'parseFolder' => mb_convert_encoding($m[3], 'UTF-8', 'UTF7-IMAP'), | ||
444 | + // 是否可选择 | ||
445 | + 'isSelect' => strpos($m[1],'NoSelect')===false, | ||
446 | + ]; | ||
447 | + } | ||
448 | + } | ||
449 | + | ||
450 | + return $folder; | ||
451 | + } | ||
452 | + | ||
453 | + /** | ||
454 | + * 创建文件夹 | ||
455 | + * $folder 目录 创建二级目录用/ a/b | ||
456 | + * @param string $folder | ||
457 | + * @return bool | ||
458 | + * @throws \Exception | ||
459 | + * @author:dc | ||
460 | + * @time 2022/11/24 23:35 | ||
461 | + */ | ||
462 | + public function folderCreate(string $folder):bool { | ||
463 | + // 需要转码 | ||
464 | + $folder = mb_convert_encoding($folder,'UTF7-IMAP','UTF-8'); | ||
465 | +// A003 CREATE owatagusiam 顶级 | ||
466 | +// A003 CREATE owatagusiam/owatagusiam2 有上下级关系的文件夹 | ||
467 | + $res = $this->request('CREATE '.$folder); | ||
468 | + | ||
469 | + if ($res[0] == 'ok'){ | ||
470 | + return true; | ||
471 | + } | ||
472 | + | ||
473 | + throw new \Exception('create folder error:'.end($res[1])); | ||
474 | + | ||
475 | + } | ||
476 | + | ||
477 | + /** | ||
478 | + * 修改文件夹名称 | ||
479 | + * @param string $oldFolder 久文件夹名称 | ||
480 | + * @param string $newFolder 新文件夹名称 | ||
481 | + * @return bool | ||
482 | + * @throws \Exception | ||
483 | + * @author:dc | ||
484 | + * @time 2022/11/25 10:24 | ||
485 | + */ | ||
486 | + public function folderRename(string $oldFolder, string $newFolder){ | ||
487 | + // 需要转码 | ||
488 | + $newFolder = mb_convert_encoding($newFolder,'UTF7-IMAP','UTF-8'); | ||
489 | +// RENAME oldfolder newfolder | ||
490 | + $res = $this->request("RENAME {$oldFolder} {$newFolder}"); | ||
491 | + | ||
492 | + if ($res[0] == 'ok'){ | ||
493 | + return true; | ||
494 | + } | ||
495 | + | ||
496 | + throw new \Exception('rename folder error:'.end($res[1])); | ||
497 | + } | ||
498 | + | ||
499 | + /** | ||
500 | + * 删除文件夹 | ||
501 | + * @param string $folder | ||
502 | + * @return bool | ||
503 | + * @throws \Exception | ||
504 | + * @author:dc | ||
505 | + * @time 2022/11/25 10:25 | ||
506 | + */ | ||
507 | + public function folderDelete(string $folder):bool{ | ||
508 | + | ||
509 | +// A683 DELETE blurdybloop/test | ||
510 | + $res = $this->request('DELETE '.$folder); | ||
511 | + | ||
512 | + if ($res[0] == 'ok'){ | ||
513 | + return true; | ||
514 | + } | ||
515 | + | ||
516 | + throw new \Exception('rename folder error:'.end($res[1])); | ||
517 | + | ||
518 | + } | ||
519 | + | ||
520 | + | ||
521 | + /** | ||
522 | + * 获取邮件头,并解析 | ||
523 | + * @param $data | ||
524 | + * @param false $is_uid | ||
525 | + * @return array | ||
526 | + * @throws \Exception | ||
527 | + * @author:dc | ||
528 | + * @time 2022/11/23 14:25 | ||
529 | + */ | ||
530 | + public function fetchHeader($data,$is_uid = false){ | ||
531 | + $result = $this->fetch($data,'header',$is_uid); | ||
532 | + // 解析header字段 | ||
533 | + foreach ($result as $key=>$item){ | ||
534 | + $result[$key]['HEADER.FIELDS'] = $this->parseHeader($item['HEADER.FIELDS']); | ||
535 | + } | ||
536 | + | ||
537 | + return $result; | ||
538 | + | ||
539 | + } | ||
540 | + | ||
541 | + /** | ||
542 | + * 解析header字段 | ||
543 | + * @param $header | ||
544 | + * @return array | ||
545 | + * @author:dc | ||
546 | + * @time 2022/11/23 14:54 | ||
547 | + */ | ||
548 | + public function parseHeader($header){ | ||
549 | + /****** 把数据中的 : 转换一下 *******/ | ||
550 | + $header = explode("\n",$header); | ||
551 | + foreach ($header as $k=>$str){ | ||
552 | + $first_str = ''; | ||
553 | + if(substr_count($str,':') > 1){ | ||
554 | + $str = explode(':',$str); | ||
555 | + $first_str = $str[0]; | ||
556 | + if($first_str){ | ||
557 | + unset($str[0]); | ||
558 | + } | ||
559 | + $str = implode('_(_(_(_0_)_)_)_',$str); | ||
560 | + if($first_str) $str = $first_str.':'.$str; | ||
561 | + } | ||
562 | + $header[$k] = empty($first_str) ? $str : ltrim($str); | ||
563 | + } | ||
564 | + $header = implode("\n",$header); | ||
565 | + /******end*******/ | ||
566 | + | ||
567 | + preg_match_all( | ||
568 | + "/^([^\r\n:]+)\s*[:]\s*([^\r\n:]+(?:[\r]?[\n][ \t][^\r\n]+)*)/m", | ||
569 | + $header, | ||
570 | + $matches, | ||
571 | + PREG_SET_ORDER | ||
572 | + ); | ||
573 | + $headers = []; | ||
574 | + foreach($matches as $match){ | ||
575 | + $match[2] = str_replace(['_(_(_(_0_)_)_)_'],[':'],$match[2]); | ||
576 | + if(strpos($match[2],'=?')!==false){ | ||
577 | + $match2=iconv_mime_decode($match[2],ICONV_MIME_DECODE_CONTINUE_ON_ERROR,'utf-8'); | ||
578 | + $match[2] = $match2; | ||
579 | + } | ||
580 | + | ||
581 | + if(isset($headers[$match[1]]) && is_array($headers[$match[1]])){ | ||
582 | + $headers[$match[1]][]=$match[2]; | ||
583 | + }elseif(isset($headers[$match[1]])){ | ||
584 | + $headers[$match[1]]=array($headers[$match[1]],$match[2]); | ||
585 | + }else{ | ||
586 | + $headers[$match[1]]=$match[2]; | ||
587 | + } | ||
588 | + } | ||
589 | + return $headers; | ||
590 | + | ||
591 | + } | ||
592 | + | ||
593 | + | ||
594 | + /** | ||
595 | + * 获取邮件内容,包括附件 | ||
596 | + * @param mixed $data 1,1:10,[1,2,3] | ||
597 | + * @param string $saveFilePath 保存附件的目录 | ||
598 | + * @param bool $is_uid 是否是UID查询 | ||
599 | + * @throws \Exception | ||
600 | + * @author:dc | ||
601 | + * @time 2022/11/23 17:01 | ||
602 | + */ | ||
603 | + public function fetchBody($data,$saveFilePath=__DIR__,$is_uid = false){ | ||
604 | + // 取得body | ||
605 | + $result = $this->fetch($data,'body',$is_uid); | ||
606 | + foreach ($result as &$item){ | ||
607 | + if (!empty($item['RFC822.TEXT'])){ | ||
608 | + // 解析 | ||
609 | + $item['RFC822.TEXT'] = (new Body($item['RFC822.TEXT'],$saveFilePath))->getItem(); | ||
610 | + } | ||
611 | + } | ||
612 | + | ||
613 | + return $result; | ||
614 | + } | ||
615 | + | ||
616 | + | ||
617 | + | ||
618 | + /** | ||
619 | + * @param $data | ||
620 | + * @param false $is_uid | ||
621 | + * @return array | ||
622 | + * @throws \Exception | ||
623 | + * @author:dc | ||
624 | + * @time 2022/11/23 10:46 | ||
625 | + */ | ||
626 | + public function fetch($data,$header2Body='header',$is_uid = false):array{ | ||
627 | + // string 必须是 0:99 开始:结束 | ||
628 | + if(is_numeric($data)){ | ||
629 | + $data = intval($data); | ||
630 | + } | ||
631 | + elseif(is_string($data)){ | ||
632 | + if(!preg_match("/^\d+:\d+$/",$data)){ | ||
633 | + $data = ''; | ||
634 | + } | ||
635 | + }elseif (is_array($data)){ | ||
636 | + foreach ($data as $k=>$v){ | ||
637 | + if(!is_numeric($v)){ | ||
638 | + unset($data[$k]); | ||
639 | + } | ||
640 | + } | ||
641 | + $data = array_unique(array_values($data)); | ||
642 | + $data = implode(',',$data); | ||
643 | + } | ||
644 | + | ||
645 | + if(empty($data)){ | ||
646 | + throw new \Exception('fetch data error'); | ||
647 | + } | ||
648 | + | ||
649 | + // (UID RFC822.SIZE RFC822.HEADER FLAGS INTERNALDATE BODYSTRUCTURE BODY.PEEK[HEADER.FIELDS (DATE FROM TO SUBJECT CONTENT-TYPE CC REPLY-TO LIST-POST DISPOSITION-NOTIFICATION-TO X-PRIORITY CONTENT-TRANSFER-ENCODING BCC IN-REPLY-TO MAIL-FOLLOWUP-TO MAIL-REPLY-TO MESSAGE-ID REFERENCES RESENT-BCC RETURN-PATH SENDER X-DRAFT-INFO)]) | ||
650 | + // 指定字段 BODY.PEEK[HEADER.FIELDS (DATE FROM TO ...)] | ||
651 | + // 所有header字段 RFC822.HEADER | ||
652 | + // RFC822.TEXT 内容包括附件 | ||
653 | + // body字段必须放最后 | ||
654 | + if($header2Body=='header'){ | ||
655 | +// BODY.peek必须放最后 | ||
656 | + $filed = 'UID FLAGS INTERNALDATE RFC822.SIZE BODYSTRUCTURE BODY.PEEK[HEADER.FIELDS (DATE FROM TO SUBJECT CONTENT-TYPE CC REPLY-TO LIST-POST DISPOSITION-NOTIFICATION-TO X-PRIORITY CONTENT-TRANSFER-ENCODING BCC IN-REPLY-TO MAIL-FOLLOWUP-TO MAIL-REPLY-TO MESSAGE-ID REFERENCES RESENT-BCC RETURN-PATH SENDER X-DRAFT-INFO)]'; | ||
657 | + }elseif($header2Body=='body'){ | ||
658 | + $filed = 'RFC822.TEXT'; | ||
659 | + }else{ | ||
660 | + $filed = 'UID FLAGS INTERNALDATE'; | ||
661 | + } | ||
662 | + | ||
663 | + // 读取数据 | ||
664 | + $result = $this->request(($is_uid?'UID ':'')."FETCH {$data} ($filed)"); | ||
665 | + | ||
666 | + if($result[0] != 'ok'){ | ||
667 | + throw new \Exception('fetch error:'.end($result[1])); | ||
668 | + } | ||
669 | + | ||
670 | + // 开始解析数据 | ||
671 | + $list = []; | ||
672 | + foreach ($result[1] as $item){ | ||
673 | + $item = trim($item); | ||
674 | + // 匹配出id和数据 | ||
675 | + if(preg_match("/\* (\d+) FETCH \(([\w\s\d\r\n\W]{1,})\)$/i",$item,$line)){ | ||
676 | + $list[$line[1]] = $this->parseFetch($line[2]); | ||
677 | + } | ||
678 | + } | ||
679 | + | ||
680 | + // 返回结果 | ||
681 | + return $list; | ||
682 | + | ||
683 | + } | ||
684 | + | ||
685 | + /** | ||
686 | + * 解析头部信息,只能解析固定字段的属性 | ||
687 | + * @param string $line | ||
688 | + * @return array | ||
689 | + * @author:dc | ||
690 | + * @time 2022/11/22 18:06 | ||
691 | + */ | ||
692 | + public function parseFetch($line):array{ | ||
693 | + $result = []; | ||
694 | + $line = ltrim($line); | ||
695 | + $header = explode(' ',$line); | ||
696 | + do{ | ||
697 | + | ||
698 | + switch ($header[0]){ | ||
699 | + case 'UID':{ | ||
700 | + $result['UID'] = $header[1]; | ||
701 | + array_splice($header,0,2); | ||
702 | + break; | ||
703 | + } | ||
704 | + case 'FLAGS':{ | ||
705 | + // 标记,标签 | ||
706 | + $result['FLAGS'] = $this->pregFiled( | ||
707 | + $header, | ||
708 | + "/^\(([\\a-z\s]{0,})\)/Ui" | ||
709 | + ); | ||
710 | + $result['FLAGS'] = $result['FLAGS'] ? explode(' ',$result['FLAGS']) : []; | ||
711 | + break; | ||
712 | + } | ||
713 | + case 'INTERNALDATE':{ | ||
714 | + // 内部时间 | ||
715 | + $result['INTERNALDATE'] = $this->pregFiled( | ||
716 | + $header, | ||
717 | + "/^\"([\\a-z\d\s]{0,})\"/Ui" | ||
718 | + ); | ||
719 | + break; | ||
720 | + } | ||
721 | + case 'RFC822.SIZE':{ | ||
722 | + $result['RFC822.SIZE'] = $header[1]; | ||
723 | + array_splice($header,0,2); | ||
724 | + break; | ||
725 | + } | ||
726 | + case 'BODYSTRUCTURE':{ | ||
727 | + array_shift($header); | ||
728 | + $result['BODYSTRUCTURE'] = ''; | ||
729 | + $leftNum = $RightNum = 0; | ||
730 | + foreach ($header as $key=>$str){ | ||
731 | + // 还有括号不对等的情况,无语了 | ||
732 | + if($str == 'BODY[HEADER.FIELDS'){ | ||
733 | + break; | ||
734 | + } | ||
735 | + // 找出现的次数 | ||
736 | + $leftNum += substr_count($str,'('); | ||
737 | + $RightNum += substr_count($str,')'); | ||
738 | + // 拼接起来 | ||
739 | + $result['BODYSTRUCTURE'] .= ' '.$str; | ||
740 | + unset($header[$key]); | ||
741 | + // 说明找到结束了 | ||
742 | + if($leftNum===$RightNum){ | ||
743 | + break; | ||
744 | + } | ||
745 | + } | ||
746 | + $header = array_values($header); | ||
747 | + break; | ||
748 | + } | ||
749 | + // RFC822.TEXT不能和 BODY[HEADER.FIELDS 同时存在,否则解析失败 | ||
750 | + case 'RFC822.TEXT':{ | ||
751 | + array_shift($header); | ||
752 | + $result['RFC822.TEXT'] = implode(' ',$header); | ||
753 | + $header = []; | ||
754 | + break; | ||
755 | + } | ||
756 | + case 'RFC822.HEADER':{ | ||
757 | + array_shift($header); | ||
758 | + $result['RFC822.HEADER'] = implode(' ',$header); | ||
759 | + $header = []; | ||
760 | + break; | ||
761 | + } | ||
762 | + case 'BODY[HEADER.FIELDS':{ | ||
763 | + // header | ||
764 | + $header = implode(' ',$header); | ||
765 | + preg_match("/^BODY\[HEADER.FIELDS.*\]/Ui",$header,$m); | ||
766 | + // 结果,提出掉字段字符 | ||
767 | + $result['HEADER.FIELDS'] = ltrim(mb_substr($header,mb_strlen($m[0]),mb_strlen($header))); | ||
768 | + $header = [];//表示结束了 | ||
769 | + break; | ||
770 | + } | ||
771 | + default:{ | ||
772 | + array_shift($header); | ||
773 | + break; | ||
774 | + } | ||
775 | + } | ||
776 | + }while($header); | ||
777 | + | ||
778 | + return $result; | ||
779 | + } | ||
780 | + | ||
781 | + /** | ||
782 | + * 匹配字段中的值 | ||
783 | + * @param $header | ||
784 | + * @param $preg | ||
785 | + * @return mixed|string | ||
786 | + * @author:dc | ||
787 | + * @time 2022/11/23 14:38 | ||
788 | + */ | ||
789 | + private function pregFiled(&$header,$preg){ | ||
790 | + array_shift($header); | ||
791 | + // 组成字符串 | ||
792 | + $header = implode(' ',$header); | ||
793 | + // 找flags,非贪婪模式 | ||
794 | + if(preg_match($preg,$header,$m)){ | ||
795 | + $header = mb_substr($header,mb_strlen($m[0]),mb_strlen($header)); | ||
796 | + } | ||
797 | + // 打散成数组 | ||
798 | + $header = explode(' ',$header); | ||
799 | + | ||
800 | + return $m[1]??''; | ||
801 | + } | ||
802 | + | ||
803 | + /** | ||
804 | + * imap服务器设置的id | ||
805 | + * @param array|string $id | ||
806 | + * @author:dc | ||
807 | + * @time 2022/11/22 11:53 | ||
808 | + */ | ||
809 | + public function setImapId($id){ | ||
810 | + if(is_array($id)){ | ||
811 | + $this->imapId = array_merge($this->imapId,$id); | ||
812 | + }else{ | ||
813 | + $this->imapId['name'] = $id; | ||
814 | + } | ||
815 | + } | ||
816 | + | ||
817 | + | ||
818 | + /** | ||
819 | + * 打开socket链接 | ||
820 | + * @param int $timeout | ||
821 | + * @throws \Exception | ||
822 | + * @author:dc | ||
823 | + * @time 2022/11/22 14:13 | ||
824 | + */ | ||
825 | + private function socketOpen(int $timeout = 30){ | ||
826 | + if(!is_resource($this->socket)){ | ||
827 | + $this->timeout = $timeout ? : 30; | ||
828 | + // 链接服务器 | ||
829 | + $this->socket = stream_socket_client($this->host, $errno, $error, $this->timeout); | ||
830 | + | ||
831 | + if($error){ | ||
832 | + throw new \Exception("socket error: {$error}"); | ||
833 | + } | ||
834 | + | ||
835 | + if (!$this->socket) { | ||
836 | + throw new \Exception("{$this->host} connection fail."); | ||
837 | + } | ||
838 | + | ||
839 | + stream_set_timeout($this->socket, $this->timeout); | ||
840 | + }else{ | ||
841 | + // 是否超时,超时关闭 | ||
842 | + $meta = stream_get_meta_data($this->socket); | ||
843 | + if (isset($meta['timed_out']) && $meta['timed_out'] !== false) { | ||
844 | + $this->socketClose(); | ||
845 | + // 重新链接 | ||
846 | + $this->socketOpen(); | ||
847 | + } | ||
848 | + } | ||
849 | + } | ||
850 | + | ||
851 | + | ||
852 | + /** | ||
853 | + * 最后一次执行时候的tag | ||
854 | + * @return string | ||
855 | + * @author:dc | ||
856 | + * @time 2022/11/22 13:54 | ||
857 | + */ | ||
858 | + protected function getLastTag(){ | ||
859 | + return sprintf('%s%d', $this->tagName, $this->tagNum); | ||
860 | + } | ||
861 | + | ||
862 | + /** | ||
863 | + * 获取下一次执行的tag | ||
864 | + * @return string | ||
865 | + * @author:dc | ||
866 | + * @time 2022/11/22 13:52 | ||
867 | + */ | ||
868 | + protected function getNextTag(){ | ||
869 | + $this->tagNum += 1; | ||
870 | + return sprintf('%s%d', $this->tagName, $this->tagNum); | ||
871 | + } | ||
872 | + | ||
873 | + /** | ||
874 | + * 向服务器发送一个noop消息,表示什么也不做, | ||
875 | + * 只是用来保持通信,避免长久没有操作,丢失掉连接 | ||
876 | + * @throws \Exception | ||
877 | + * @author:dc | ||
878 | + * @time 2022/11/25 11:15 | ||
879 | + */ | ||
880 | + public function noop():bool { | ||
881 | + $status = $this->request('NOOP'); | ||
882 | + return $status[0] == 'ok'; | ||
883 | + } | ||
884 | + | ||
885 | + /** | ||
886 | + * debug模式 | ||
887 | + * @param bool $debug | ||
888 | + * @param string $logPath | ||
889 | + * @author:dc | ||
890 | + * @time 2022/12/6 11:10 | ||
891 | + */ | ||
892 | + public function debug($debug=true,$logPath=''){ | ||
893 | + $this->debug = $debug; | ||
894 | + $this->debugWritePath = $logPath ? $logPath : storage_path('logs'); | ||
895 | + } | ||
896 | + | ||
897 | + /** | ||
898 | + * 记录日志 | ||
899 | + * @param string $message | ||
900 | + * @author:dc | ||
901 | + * @time 2022/12/6 11:13 | ||
902 | + */ | ||
903 | + private function log(string $message){ | ||
904 | + if($this->debug){ | ||
905 | + if(!is_dir($this->debugWritePath)){ | ||
906 | + @mkdir($this->debugWritePath,0775,true); | ||
907 | + } | ||
908 | + @file_put_contents($this->debugWritePath.'/imap.log',date('Y-m-d H:i:s ').$message.PHP_EOL,FILE_APPEND); | ||
909 | + } | ||
910 | + } | ||
911 | + | ||
912 | + /** | ||
913 | + * 获取数据集 | ||
914 | + * @param $cmd | ||
915 | + * @return array | ||
916 | + * @throws \Exception | ||
917 | + * @author:dc | ||
918 | + * @time 2022/11/22 11:41 | ||
919 | + */ | ||
920 | + public function request($cmd){ | ||
921 | + // 链接 | ||
922 | + $this->socketOpen(); | ||
923 | + | ||
924 | + $tag = $this->getNextTag(); | ||
925 | + | ||
926 | + // 命令行必须要结束换行 | ||
927 | + $cmd = trim($tag.' '.$cmd); | ||
928 | + | ||
929 | + // 记录日志 | ||
930 | + $this->log($cmd); | ||
931 | + | ||
932 | + // 写入数据 | ||
933 | + $r = fwrite($this->socket, $cmd."\r\n"); | ||
934 | + if (!$r) { | ||
935 | + $this->socketClose(); | ||
936 | + throw new \Exception("request error write"); | ||
937 | + } | ||
938 | + | ||
939 | + // 读取数据 | ||
940 | + $result = []; // 返回数据 | ||
941 | + $status = 'no'; // 状态 | ||
942 | + $i = 1; | ||
943 | + while ($i) { | ||
944 | + $append = false;// 是否追加到上一个元素值里面 | ||
945 | + // 这里不指定长度,读取一行 | ||
946 | + $line = @fgets($this->socket); | ||
947 | + if ($line === false || !mb_strlen($line)) { | ||
948 | + $end = true; | ||
949 | + }else{ | ||
950 | + | ||
951 | + | ||
952 | + // 是否有其他的固定串 | ||
953 | + preg_match("/\{(\d+)\}\r\n$/",$line,$number); | ||
954 | + if($number[1]??0){ | ||
955 | + // 获取到固定字符串 | ||
956 | + $appendLine = fread($this->socket, intval($number[1])); | ||
957 | + // 替换 {123} | ||
958 | + $line = str_replace($number[0],$appendLine,$line); | ||
959 | + } | ||
960 | + | ||
961 | + // 记录日志 | ||
962 | + $this->log($line); | ||
963 | + | ||
964 | + // 是否结束了,到了最后一行 | ||
965 | + if(strpos($line,$tag.' ') === 0){ | ||
966 | + $end = true; | ||
967 | + $status = strtolower(explode(' ',$line)[1]??''); | ||
968 | + // 脚本异常 | ||
969 | + if($status == 'bad'){ | ||
970 | + throw new \Exception('request bad:'.$line); | ||
971 | + } | ||
972 | + }else{ | ||
973 | + if(strpos($line,'* ') !==0 ){ | ||
974 | + $append = true; | ||
975 | + } | ||
976 | + } | ||
977 | + | ||
978 | + // 结果数组 | ||
979 | + if($append){ | ||
980 | + $result[$i-1] .= $line; | ||
981 | + }else{ | ||
982 | + $result[$i] = $line; | ||
983 | + $i++; | ||
984 | + } | ||
985 | + | ||
986 | + } | ||
987 | + // 结束了 | ||
988 | + if(!empty($end)){ | ||
989 | + $i = false; | ||
990 | + } | ||
991 | + } | ||
992 | + | ||
993 | +// print_r($result); | ||
994 | + | ||
995 | + return [$status,$result]; | ||
996 | + | ||
997 | + } | ||
998 | + | ||
999 | + /** | ||
1000 | + * 是否读取结束 | ||
1001 | + * @return bool | ||
1002 | + * @author:dc | ||
1003 | + * @time 2022/11/22 14:14 | ||
1004 | + */ | ||
1005 | + protected function socketEof() | ||
1006 | + { | ||
1007 | + if (!is_resource($this->socket)) { | ||
1008 | + return true; | ||
1009 | + } | ||
1010 | + | ||
1011 | + // If a connection opened by fsockopen() wasn't closed | ||
1012 | + // by the server, feof() will hang. | ||
1013 | + $start = microtime(true); | ||
1014 | + | ||
1015 | + if (feof($this->socket) || | ||
1016 | + ($this->timeout && (microtime(true) - $start > $this->timeout)) | ||
1017 | + ) { | ||
1018 | + $this->socketClose(); | ||
1019 | + return true; | ||
1020 | + } | ||
1021 | + | ||
1022 | + return false; | ||
1023 | + } | ||
1024 | + | ||
1025 | + /** | ||
1026 | + * 关闭socket链接 | ||
1027 | + * @author:dc | ||
1028 | + * @time 2022/11/22 10:45 | ||
1029 | + */ | ||
1030 | + protected function socketClose(){ | ||
1031 | + if(is_resource($this->socket)){ | ||
1032 | + fclose($this->socket); | ||
1033 | + } | ||
1034 | + $this->socket = false; | ||
1035 | + } | ||
1036 | + | ||
1037 | + | ||
1038 | + | ||
1039 | + | ||
1040 | + public function __construct() | ||
1041 | + { | ||
1042 | + } | ||
1043 | + | ||
1044 | + public function __destruct() | ||
1045 | + { | ||
1046 | + if($this->auto_colse){ | ||
1047 | + // echo '关闭'; | ||
1048 | + // TODO: Implement __destruct() method. | ||
1049 | + $this->socketClose(); | ||
1050 | + } | ||
1051 | + | ||
1052 | + } | ||
1053 | + | ||
1054 | + | ||
1055 | + | ||
1056 | +} |
lib/Mail/Mail.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +namespace Lib\Mail; | ||
4 | + | ||
5 | +/** | ||
6 | + * 操作邮件 | ||
7 | + * @author:dc | ||
8 | + * @time 2023/2/5 10:10 | ||
9 | + * Class MailFun | ||
10 | + * @package Helper\Mail | ||
11 | + */ | ||
12 | +class Mail { | ||
13 | + | ||
14 | + /** | ||
15 | + * imap服务器连接实例 | ||
16 | + * @var Imap[] | ||
17 | + */ | ||
18 | + public static array $client = []; | ||
19 | + | ||
20 | + | ||
21 | + /** | ||
22 | + * 登录imap服务器 | ||
23 | + * @param string $email | ||
24 | + * @param string $password | ||
25 | + * @param string $imap | ||
26 | + * @author:dc | ||
27 | + * @time 2023/2/5 10:46 | ||
28 | + */ | ||
29 | + public static function login(string $email,string $password,string $imap) { | ||
30 | + if(!empty(static::$client[$email]) && static::$client[$email] instanceof Imap){ | ||
31 | + if(static::$client[$email]->noop()){ | ||
32 | + return true; | ||
33 | + } | ||
34 | + } | ||
35 | + static::$client[$email] = new Imap(); | ||
36 | +// $imap->debug(); | ||
37 | + // 是否初始成功 | ||
38 | + static::$client[$email]->login("ssl://{$imap}:993",$email,$password); | ||
39 | + return true; | ||
40 | + } | ||
41 | + | ||
42 | + | ||
43 | + /** | ||
44 | + * 同步文件夹 | ||
45 | + * @param $email | ||
46 | + * @param MySQL|null $db | ||
47 | + * @return mixed | ||
48 | + * @author:dc | ||
49 | + * @time 2023/2/5 10:58 | ||
50 | + */ | ||
51 | + public static function syncFolder($email,$db=null){ | ||
52 | + | ||
53 | + // 读取所有文件夹,未解密 | ||
54 | + $folders = static::$client[$email]->getFolder(); | ||
55 | + | ||
56 | + DB::beginTransaction(); | ||
57 | + foreach ($folders as $folder){ | ||
58 | + | ||
59 | + // 处理子父文件夹 | ||
60 | + $folder['id'] = explode('/',$folder['folder']); | ||
61 | + $folder['name'] = explode('/',$folder['parseFolder']); | ||
62 | + $pid = 0; | ||
63 | + foreach ($folder['id'] as $k=>$item){ | ||
64 | + // 插入到数据库 | ||
65 | + $pid = Folder::_insert( | ||
66 | + static::$client[$email]->getId(), | ||
67 | + $folder['name'][$k], | ||
68 | + $item, | ||
69 | + $pid | ||
70 | + ); | ||
71 | + } | ||
72 | + } | ||
73 | + DB::commit(); | ||
74 | + | ||
75 | + } | ||
76 | + | ||
77 | + | ||
78 | + /** | ||
79 | + * 同步邮件 | ||
80 | + * @param $email | ||
81 | + * @param $email_id | ||
82 | + * @param $folder_id | ||
83 | + * @param string $folder | ||
84 | + * @return bool | ||
85 | + * @author:dc | ||
86 | + * @time 2023/2/6 15:04 | ||
87 | + */ | ||
88 | + public static function syncMail($email,$email_id,$folder_id,$folder='INBOX'):bool { | ||
89 | + // 选择文件夹 | ||
90 | + try { | ||
91 | + $status = static::$client[$email]->selectFolder($folder); | ||
92 | + }catch (\Throwable $e){ | ||
93 | + Log::error($email.' 选择文件夹错误:'.$e->getMessage()); | ||
94 | + return false; | ||
95 | + } | ||
96 | + // 是否有邮件 | ||
97 | + if (!isset($status['EXISTS']) || !$status['EXISTS']){ | ||
98 | + return true; | ||
99 | + } | ||
100 | + | ||
101 | + // 更新数量 | ||
102 | + Folder::_updateNum($folder_id,$status['EXISTS'], $status['UNSEEN']??null); | ||
103 | + | ||
104 | + // 最后拉取的时间,如果是第一次 | ||
105 | + $lastMsgno = EList::_lastMsgno($email_id, $folder_id); | ||
106 | + | ||
107 | + $nu = 20; | ||
108 | + | ||
109 | + if(!$lastMsgno){ | ||
110 | + $msgno = range(1,$nu); | ||
111 | + }else{ | ||
112 | + $msgno = range($lastMsgno,$lastMsgno+$nu); | ||
113 | + | ||
114 | + if($lastMsgno > $status['EXISTS']){ | ||
115 | + $msgno = range($status['EXISTS'] > $nu ? $status['EXISTS'] - $nu : 1,$status['EXISTS']); | ||
116 | + } | ||
117 | + // 一样就不拉新的 | ||
118 | + if($lastMsgno == $status['EXISTS']){ | ||
119 | + return true; | ||
120 | + } | ||
121 | + } | ||
122 | + | ||
123 | + | ||
124 | + | ||
125 | + SYNCEMAILLIST: | ||
126 | + // 是否有id | ||
127 | + $dataids = EList::_getIdsByMsgno($email_id,$folder_id,$msgno); | ||
128 | + | ||
129 | + // 循环 | ||
130 | + $results = static::$client[$email]->fetchHeader($msgno); | ||
131 | + | ||
132 | + if($results){ | ||
133 | + DB::beginTransaction(); | ||
134 | + // 批量插入 | ||
135 | + foreach ($results as $key=>$result){ | ||
136 | + if($key == $status['EXISTS']){ | ||
137 | + $end = true; | ||
138 | + } | ||
139 | + $header = &$result['HEADER.FIELDS']; | ||
140 | + | ||
141 | + foreach ($result['FLAGS'] as $k=>$FLAG){ | ||
142 | + $result['FLAGS'][$k] = strtolower(str_replace('\\','',$FLAG)); | ||
143 | + } | ||
144 | + try { | ||
145 | + | ||
146 | + $file_header = &$result['BODYSTRUCTURE']; | ||
147 | + | ||
148 | + // 没有收件人 | ||
149 | + if(!empty($header['To'])){ | ||
150 | + $header['To'] = MailFun::toOrFrom($header['To']); | ||
151 | + }else{ | ||
152 | + $header['To'] = []; | ||
153 | + } | ||
154 | + | ||
155 | + | ||
156 | + $header['From'] = MailFun::toOrFrom($header['From']); | ||
157 | + | ||
158 | + $data = [ | ||
159 | + 'id' => $dataids[$key]??0, | ||
160 | + 'msgno' => $key, | ||
161 | + 'uid' => $result['UID'], | ||
162 | + 'subject' => $header['Subject'], | ||
163 | + 'cc' => $header['Cc']??'', | ||
164 | + 'bcc' => $header['Bcc']??'', | ||
165 | + 'from' => $header['From'][0]['email']??'', | ||
166 | + 'from_name' => $header['From'][0]['name']??'', | ||
167 | + 'to' => $header['To']?implode(',',array_column($header['To'],'email')):'', | ||
168 | + 'to_name' => json_encode($header['To']), | ||
169 | + 'date' => isset($header['Date'])&&$header['Date'] ? strtotime(is_array($header['Date']) ? $header['Date'][0] : $header['Date']) : strtotime($result['INTERNALDATE']), | ||
170 | + 'message_id' => $header['Message-ID']??'', | ||
171 | + 'udate' => strtotime($result['INTERNALDATE']), | ||
172 | +// 'size' => $result['RFC822.SIZE'], | ||
173 | + 'recent' => in_array('recent',$result['FLAGS']), | ||
174 | + 'seen' => in_array('seen',$result['FLAGS']), | ||
175 | + 'draft' => in_array('draft',$result['FLAGS']), | ||
176 | + 'flagged' => in_array('flagged',$result['FLAGS']), | ||
177 | + 'answered' => in_array('answered',$result['FLAGS']), | ||
178 | + 'folder_id' => $folder_id, | ||
179 | + 'email_id' => $email_id, | ||
180 | + 'uuid' => $email_id.$folder_id.$result['UID'], | ||
181 | + 'is_file' => MailFun::isFile($file_header[$key]['BODYSTRUCTURE']??[]) //是否附件 | ||
182 | + ]; | ||
183 | + }catch (\Throwable $e){ | ||
184 | + Log::error('邮件解析失败:'.$e->getMessage().print_r($result,true)); | ||
185 | + unset($results[$key]); | ||
186 | + continue; | ||
187 | + } | ||
188 | + | ||
189 | + $results[$key] = $data; | ||
190 | + } | ||
191 | + EList::_insertAll(array_values($results)); | ||
192 | + // 提交 | ||
193 | + DB::commit(); | ||
194 | + } | ||
195 | + | ||
196 | + | ||
197 | + // 再次调用 | ||
198 | + Mail::syncMail($email,$email_id,$folder_id,$folder); | ||
199 | + | ||
200 | + return true; | ||
201 | + | ||
202 | + | ||
203 | + } | ||
204 | + | ||
205 | + | ||
206 | + /** | ||
207 | + * 同步 邮件 内容 body | ||
208 | + * @param $id | ||
209 | + * @param $msgno | ||
210 | + * @param $email_id | ||
211 | + * @param $folder_name | ||
212 | + * @param $email | ||
213 | + * @return bool | ||
214 | + * @throws \Exception | ||
215 | + * @author:dc | ||
216 | + * @time 2023/2/9 10:29 | ||
217 | + */ | ||
218 | + public static function syncBody($id,$msgno, $email_id,$folder_name,$email):bool { | ||
219 | + | ||
220 | + // 选择文件夹 | ||
221 | + static::$client[$email]->selectFolder($folder_name); | ||
222 | + | ||
223 | + $body = static::$client[$email]->fetchBody([$msgno],storage_path('email/'.$email_id)); | ||
224 | + | ||
225 | + if(!empty($body[$msgno]['RFC822.TEXT'])){ | ||
226 | + \App\Models\Body::_insert($id,$body[$msgno]['RFC822.TEXT']); | ||
227 | + } | ||
228 | + | ||
229 | + return true; | ||
230 | + | ||
231 | + } | ||
232 | + | ||
233 | + | ||
234 | + | ||
235 | +} |
lib/Mail/MailFun.php
0 → 100644
1 | +<?php | ||
2 | +namespace Helper\Mail; | ||
3 | + | ||
4 | + | ||
5 | +use Illuminate\Support\Facades\Storage; | ||
6 | +use PHPMailer\PHPMailer\PHPMailer; | ||
7 | +use PHPMailer\PHPMailer\SMTP; | ||
8 | + | ||
9 | +/** | ||
10 | + * 函数 | ||
11 | + * @time 2022/8/1 16:02 | ||
12 | + * Class MailFun | ||
13 | + * @package App\Mail\lib | ||
14 | + */ | ||
15 | +class MailFun { | ||
16 | + | ||
17 | + | ||
18 | + /** | ||
19 | + * json encode | ||
20 | + * @param $data | ||
21 | + * @param int $option | ||
22 | + * @return false|string | ||
23 | + * @time 2022/8/2 15:57 | ||
24 | + */ | ||
25 | + public static function json_en($data,$option=\JSON_UNESCAPED_UNICODE){ | ||
26 | + return \json_encode($data,$option); | ||
27 | + } | ||
28 | + | ||
29 | + | ||
30 | + /** | ||
31 | + * 解码 | ||
32 | + * @param $string | ||
33 | + * @param string $charset | ||
34 | + * @return string | ||
35 | + * @time 2022/8/15 9:31 | ||
36 | + */ | ||
37 | + public static function decodeMimeStr($string, $charset = 'utf-8') { | ||
38 | + $newString = ''; | ||
39 | + $elements = imap_mime_header_decode($string); | ||
40 | +// print_r($elements); | ||
41 | + for($i = 0; $i < count($elements); $i++) { | ||
42 | + if($elements[$i]->charset == 'default') { | ||
43 | + $elements[$i]->charset = 'iso-8859-1'; | ||
44 | + } | ||
45 | + $newString .= self::convertStringEncoding($elements[$i]->text, $elements[$i]->charset, $charset); | ||
46 | + } | ||
47 | + return $newString; | ||
48 | + } | ||
49 | + | ||
50 | + public static function convertStringEncoding($string, $fromEncoding, $toEncoding) { | ||
51 | + $convertedString = null; | ||
52 | + if($string && $fromEncoding != $toEncoding) { | ||
53 | + $convertedString = @iconv($fromEncoding, $toEncoding . '//IGNORE', $string); | ||
54 | + if(!$convertedString && extension_loaded('mbstring')) { | ||
55 | + $convertedString = @mb_convert_encoding($string, $toEncoding, $fromEncoding); | ||
56 | + } | ||
57 | + } | ||
58 | + return $convertedString ?: $string; | ||
59 | + } | ||
60 | + | ||
61 | + | ||
62 | + /** | ||
63 | + * 验证是否有附件 BODYSTRUCTURE值 | ||
64 | + * @param array $BODYSTRUCTURE | ||
65 | + * @return int | ||
66 | + * @author:dc | ||
67 | + * @time 2022/11/1 10:57 | ||
68 | + */ | ||
69 | + public static function isFile(array $BODYSTRUCTURE):int { | ||
70 | +// foreach ($BODYSTRUCTURE as $item){ | ||
71 | +// if($item[0] === 'APPLICATION'){ | ||
72 | +// return 1; | ||
73 | +// } | ||
74 | +// } | ||
75 | +// return 0; | ||
76 | + $json = json_encode($BODYSTRUCTURE); | ||
77 | + return strpos($json,'"attachment"')!==false; | ||
78 | + } | ||
79 | + | ||
80 | + | ||
81 | + /** | ||
82 | + * 邮件收件人/发件人 | ||
83 | + * @param $str | ||
84 | + * @return array | ||
85 | + * @author:dc | ||
86 | + * @time 2022/11/8 9:36 | ||
87 | + */ | ||
88 | + public static function toOrFrom($str){ | ||
89 | + | ||
90 | + $strs = explode(',',$str); | ||
91 | + foreach ($strs as $k=>$s){ | ||
92 | + preg_match('/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/',$s,$email); | ||
93 | + if(empty($email[0])){ | ||
94 | + $s = [ | ||
95 | + 'email' => '', | ||
96 | + 'name' => $s | ||
97 | + ]; | ||
98 | + }else{ | ||
99 | + $s = str_replace([$email[0],'"','<','>','>','<'],'',$s); | ||
100 | + $s = trim($s); | ||
101 | + $s = [ | ||
102 | + 'email' => $email[0], | ||
103 | + 'name' => $s | ||
104 | + ]; | ||
105 | + } | ||
106 | + if(empty($s['name'])){ | ||
107 | + $s['name'] = explode('@',$s['email'])[0]??''; | ||
108 | + } | ||
109 | + | ||
110 | + if(!empty($s['email'])){ | ||
111 | + $strs[$k] = $s; | ||
112 | + }else{ | ||
113 | + unset($strs[$k]); | ||
114 | + } | ||
115 | + | ||
116 | + } | ||
117 | + | ||
118 | + return $strs; | ||
119 | + | ||
120 | + | ||
121 | + } | ||
122 | + | ||
123 | + | ||
124 | + /** | ||
125 | + * @param string $smtp smtp服务器地址 | ||
126 | + * @param string $username 发件人 | ||
127 | + * @param string $password 发件人密码 | ||
128 | + * @param string $nickname 昵称 | ||
129 | + * @param string|array $to_email 收件人,邮件或['email'=>'','name'=>''] | ||
130 | + * @param string $subject 标题,主题 | ||
131 | + * @param string $body 文本内容 | ||
132 | + * @param array $files 文件 ['origin_name'=>'','path'=>''] | ||
133 | + * @param false $receipt 是否回执 | ||
134 | + * @param int $priority 是否紧急 1紧急 3正常 5慢 | ||
135 | + * @return bool | ||
136 | + * @throws \PHPMailer\PHPMailer\Exception | ||
137 | + * @author:dc | ||
138 | + * @time 2022/11/11 14:26 | ||
139 | + */ | ||
140 | + public static function sendEmail(string $smtp,string $username,string $password,string $nickname,$to_email,string $subject,string $body,$files=[],$receipt=false,$priority=3){ | ||
141 | + | ||
142 | + // 邮件对象 | ||
143 | + $mail = new PHPMailer(true); | ||
144 | + //Server settings | ||
145 | + $mail->SMTPDebug = SMTP::DEBUG_CLIENT;//调试输出 SMTP::DEBUG_SERVER; //Enable verbose debug output | ||
146 | + $mail->isSMTP(); //Send using SMTP | ||
147 | + $mail->Host = $smtp; //Set the SMTP server to send through | ||
148 | + $mail->SMTPAuth = true; //Enable SMTP authentication | ||
149 | + $mail->Username = $username; //SMTP username | ||
150 | + $mail->Password = $password; //SMTP password | ||
151 | + $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption | ||
152 | + $mail->Port = 465; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS` | ||
153 | + $mail->CharSet = 'utf-8'; | ||
154 | + $mail->Encoding = PHPMailer::ENCODING_QUOTED_PRINTABLE; | ||
155 | + | ||
156 | + //Recipients,设置发件人 | ||
157 | + $mail->setFrom($username, $nickname);// 显示邮件来自谁 | ||
158 | + // //Add a recipient,设置收件人 这里必须是一对一发送 | ||
159 | + if(is_array($to_email)){ | ||
160 | + $mail->addAddress($to_email['email'], $to_email['name']); | ||
161 | + }else{ | ||
162 | + $mail->addAddress($to_email, ''); | ||
163 | + } | ||
164 | + | ||
165 | +// //回复到那个邮件 | ||
166 | +// $mail->addAddress($reply_to['email'], $reply_to['name']); //Add a recipient | ||
167 | +// // 抄送 | ||
168 | +// $mail->addCC($cc['email'],$cc['name']);// | ||
169 | +// // 密送 | ||
170 | +// $mail->addBCC($bcc['email'],$bcc['name']); | ||
171 | + | ||
172 | + | ||
173 | + //Attachments 附件 | ||
174 | + if($files){ | ||
175 | + foreach ($files as $file){ | ||
176 | + // 添加到邮箱中 | ||
177 | + $mail->addAttachment($file['path'], $file['origin_name']); //Add attachments | ||
178 | + } | ||
179 | + } | ||
180 | + | ||
181 | + // 回执,阅读后收回执的邮箱 | ||
182 | + if($receipt){ | ||
183 | + $mail->ConfirmReadingTo = $receipt; | ||
184 | + } | ||
185 | + // 是否紧急邮件 | ||
186 | +// Options: null (default), 1 = High, 3 = Normal, 5 = low. | ||
187 | + $mail->Priority = $priority; | ||
188 | + | ||
189 | + //Content 主题,标题 | ||
190 | + $mail->Subject = $subject; | ||
191 | + | ||
192 | + $mail->isHTML(true); //Set email format to HTML | ||
193 | + $mail->Body = $body;// html格式的内容 | ||
194 | + | ||
195 | + // 发送 | ||
196 | + if($mail->send()){ | ||
197 | + return true; | ||
198 | + } | ||
199 | + | ||
200 | + throw new \Exception($mail->ErrorInfo,500); | ||
201 | + | ||
202 | + } | ||
203 | + | ||
204 | + | ||
205 | +} |
lib/Mail/mime.types
0 → 100644
1 | +# This file maps Internet media types to unique file extension(s). | ||
2 | +# Although created for httpd, this file is used by many software systems | ||
3 | +# and has been placed in the public domain for unlimited redisribution. | ||
4 | +# | ||
5 | +# The table below contains both registered and (common) unregistered types. | ||
6 | +# A type that has no unique extension can be ignored -- they are listed | ||
7 | +# here to guide configurations toward known types and to make it easier to | ||
8 | +# identify "new" types. File extensions are also commonly used to indicate | ||
9 | +# content languages and encodings, so choose them carefully. | ||
10 | +# | ||
11 | +# Internet media types should be registered as described in RFC 4288. | ||
12 | +# The registry is at <http://www.iana.org/assignments/media-types/>. | ||
13 | +# | ||
14 | +# MIME type (lowercased) Extensions | ||
15 | +# ============================================ ========== | ||
16 | +# application/1d-interleaved-parityfec | ||
17 | +# application/3gpdash-qoe-report+xml | ||
18 | +# application/3gpp-ims+xml | ||
19 | +# application/a2l | ||
20 | +# application/activemessage | ||
21 | +# application/alto-costmap+json | ||
22 | +# application/alto-costmapfilter+json | ||
23 | +# application/alto-directory+json | ||
24 | +# application/alto-endpointcost+json | ||
25 | +# application/alto-endpointcostparams+json | ||
26 | +# application/alto-endpointprop+json | ||
27 | +# application/alto-endpointpropparams+json | ||
28 | +# application/alto-error+json | ||
29 | +# application/alto-networkmap+json | ||
30 | +# application/alto-networkmapfilter+json | ||
31 | +# application/aml | ||
32 | +application/andrew-inset ez | ||
33 | +# application/applefile | ||
34 | +application/applixware aw | ||
35 | +# application/atf | ||
36 | +# application/atfx | ||
37 | +application/atom+xml atom | ||
38 | +application/atomcat+xml atomcat | ||
39 | +# application/atomdeleted+xml | ||
40 | +# application/atomicmail | ||
41 | +application/atomsvc+xml atomsvc | ||
42 | +# application/atxml | ||
43 | +# application/auth-policy+xml | ||
44 | +# application/bacnet-xdd+zip | ||
45 | +# application/batch-smtp | ||
46 | +# application/beep+xml | ||
47 | +# application/calendar+json | ||
48 | +# application/calendar+xml | ||
49 | +# application/call-completion | ||
50 | +# application/cals-1840 | ||
51 | +# application/cbor | ||
52 | +# application/ccmp+xml | ||
53 | +application/ccxml+xml ccxml | ||
54 | +# application/cdfx+xml | ||
55 | +application/cdmi-capability cdmia | ||
56 | +application/cdmi-container cdmic | ||
57 | +application/cdmi-domain cdmid | ||
58 | +application/cdmi-object cdmio | ||
59 | +application/cdmi-queue cdmiq | ||
60 | +# application/cdni | ||
61 | +# application/cea | ||
62 | +# application/cea-2018+xml | ||
63 | +# application/cellml+xml | ||
64 | +# application/cfw | ||
65 | +# application/cms | ||
66 | +# application/cnrp+xml | ||
67 | +# application/coap-group+json | ||
68 | +# application/commonground | ||
69 | +# application/conference-info+xml | ||
70 | +# application/cpl+xml | ||
71 | +# application/csrattrs | ||
72 | +# application/csta+xml | ||
73 | +# application/cstadata+xml | ||
74 | +# application/csvm+json | ||
75 | +application/cu-seeme cu | ||
76 | +# application/cybercash | ||
77 | +# application/dash+xml | ||
78 | +# application/dashdelta | ||
79 | +application/davmount+xml davmount | ||
80 | +# application/dca-rft | ||
81 | +# application/dcd | ||
82 | +# application/dec-dx | ||
83 | +# application/dialog-info+xml | ||
84 | +# application/dicom | ||
85 | +# application/dii | ||
86 | +# application/dit | ||
87 | +# application/dns | ||
88 | +application/docbook+xml dbk | ||
89 | +# application/dskpp+xml | ||
90 | +application/dssc+der dssc | ||
91 | +application/dssc+xml xdssc | ||
92 | +# application/dvcs | ||
93 | +application/ecmascript ecma | ||
94 | +# application/edi-consent | ||
95 | +# application/edi-x12 | ||
96 | +# application/edifact | ||
97 | +# application/efi | ||
98 | +# application/emergencycalldata.comment+xml | ||
99 | +# application/emergencycalldata.deviceinfo+xml | ||
100 | +# application/emergencycalldata.providerinfo+xml | ||
101 | +# application/emergencycalldata.serviceinfo+xml | ||
102 | +# application/emergencycalldata.subscriberinfo+xml | ||
103 | +application/emma+xml emma | ||
104 | +# application/emotionml+xml | ||
105 | +# application/encaprtp | ||
106 | +# application/epp+xml | ||
107 | +application/epub+zip epub | ||
108 | +# application/eshop | ||
109 | +# application/example | ||
110 | +application/exi exi | ||
111 | +# application/fastinfoset | ||
112 | +# application/fastsoap | ||
113 | +# application/fdt+xml | ||
114 | +# application/fits | ||
115 | +application/font-tdpfr pfr | ||
116 | +# application/framework-attributes+xml | ||
117 | +# application/geo+json | ||
118 | +application/gml+xml gml | ||
119 | +application/gpx+xml gpx | ||
120 | +application/gxf gxf | ||
121 | +# application/gzip | ||
122 | +# application/h224 | ||
123 | +# application/held+xml | ||
124 | +# application/http | ||
125 | +application/hyperstudio stk | ||
126 | +# application/ibe-key-request+xml | ||
127 | +# application/ibe-pkg-reply+xml | ||
128 | +# application/ibe-pp-data | ||
129 | +# application/iges | ||
130 | +# application/im-iscomposing+xml | ||
131 | +# application/index | ||
132 | +# application/index.cmd | ||
133 | +# application/index.obj | ||
134 | +# application/index.response | ||
135 | +# application/index.vnd | ||
136 | +application/inkml+xml ink inkml | ||
137 | +# application/iotp | ||
138 | +application/ipfix ipfix | ||
139 | +# application/ipp | ||
140 | +# application/isup | ||
141 | +# application/its+xml | ||
142 | +application/java-archive jar | ||
143 | +application/java-serialized-object ser | ||
144 | +application/java-vm class | ||
145 | +# application/javascript | ||
146 | +# application/jose | ||
147 | +# application/jose+json | ||
148 | +# application/jrd+json | ||
149 | +application/json json | ||
150 | +# application/json-patch+json | ||
151 | +# application/json-seq | ||
152 | +application/jsonml+json jsonml | ||
153 | +# application/jwk+json | ||
154 | +# application/jwk-set+json | ||
155 | +# application/jwt | ||
156 | +# application/kpml-request+xml | ||
157 | +# application/kpml-response+xml | ||
158 | +# application/ld+json | ||
159 | +# application/lgr+xml | ||
160 | +# application/link-format | ||
161 | +# application/load-control+xml | ||
162 | +application/lost+xml lostxml | ||
163 | +# application/lostsync+xml | ||
164 | +# application/lxf | ||
165 | +application/mac-binhex40 hqx | ||
166 | +application/mac-compactpro cpt | ||
167 | +# application/macwriteii | ||
168 | +application/mads+xml mads | ||
169 | +application/marc mrc | ||
170 | +application/marcxml+xml mrcx | ||
171 | +application/mathematica ma nb mb | ||
172 | +application/mathml+xml mathml | ||
173 | +# application/mathml-content+xml | ||
174 | +# application/mathml-presentation+xml | ||
175 | +# application/mbms-associated-procedure-description+xml | ||
176 | +# application/mbms-deregister+xml | ||
177 | +# application/mbms-envelope+xml | ||
178 | +# application/mbms-msk+xml | ||
179 | +# application/mbms-msk-response+xml | ||
180 | +# application/mbms-protection-description+xml | ||
181 | +# application/mbms-reception-report+xml | ||
182 | +# application/mbms-register+xml | ||
183 | +# application/mbms-register-response+xml | ||
184 | +# application/mbms-schedule+xml | ||
185 | +# application/mbms-user-service-description+xml | ||
186 | +application/mbox mbox | ||
187 | +# application/media-policy-dataset+xml | ||
188 | +# application/media_control+xml | ||
189 | +application/mediaservercontrol+xml mscml | ||
190 | +# application/merge-patch+json | ||
191 | +application/metalink+xml metalink | ||
192 | +application/metalink4+xml meta4 | ||
193 | +application/mets+xml mets | ||
194 | +# application/mf4 | ||
195 | +# application/mikey | ||
196 | +application/mods+xml mods | ||
197 | +# application/moss-keys | ||
198 | +# application/moss-signature | ||
199 | +# application/mosskey-data | ||
200 | +# application/mosskey-request | ||
201 | +application/mp21 m21 mp21 | ||
202 | +application/mp4 mp4s | ||
203 | +# application/mpeg4-generic | ||
204 | +# application/mpeg4-iod | ||
205 | +# application/mpeg4-iod-xmt | ||
206 | +# application/mrb-consumer+xml | ||
207 | +# application/mrb-publish+xml | ||
208 | +# application/msc-ivr+xml | ||
209 | +# application/msc-mixer+xml | ||
210 | +application/msword doc dot | ||
211 | +application/mxf mxf | ||
212 | +# application/nasdata | ||
213 | +# application/news-checkgroups | ||
214 | +# application/news-groupinfo | ||
215 | +# application/news-transmission | ||
216 | +# application/nlsml+xml | ||
217 | +# application/nss | ||
218 | +# application/ocsp-request | ||
219 | +# application/ocsp-response | ||
220 | +application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy | ||
221 | +application/oda oda | ||
222 | +# application/odx | ||
223 | +application/oebps-package+xml opf | ||
224 | +application/ogg ogx | ||
225 | +application/omdoc+xml omdoc | ||
226 | +application/onenote onetoc onetoc2 onetmp onepkg | ||
227 | +application/oxps oxps | ||
228 | +# application/p2p-overlay+xml | ||
229 | +# application/parityfec | ||
230 | +application/patch-ops-error+xml xer | ||
231 | +application/pdf pdf | ||
232 | +# application/pdx | ||
233 | +application/pgp-encrypted pgp | ||
234 | +# application/pgp-keys | ||
235 | +application/pgp-signature asc sig | ||
236 | +application/pics-rules prf | ||
237 | +# application/pidf+xml | ||
238 | +# application/pidf-diff+xml | ||
239 | +application/pkcs10 p10 | ||
240 | +# application/pkcs12 | ||
241 | +application/pkcs7-mime p7m p7c | ||
242 | +application/pkcs7-signature p7s | ||
243 | +application/pkcs8 p8 | ||
244 | +application/pkix-attr-cert ac | ||
245 | +application/pkix-cert cer | ||
246 | +application/pkix-crl crl | ||
247 | +application/pkix-pkipath pkipath | ||
248 | +application/pkixcmp pki | ||
249 | +application/pls+xml pls | ||
250 | +# application/poc-settings+xml | ||
251 | +application/postscript ai eps ps | ||
252 | +# application/ppsp-tracker+json | ||
253 | +# application/problem+json | ||
254 | +# application/problem+xml | ||
255 | +# application/provenance+xml | ||
256 | +# application/prs.alvestrand.titrax-sheet | ||
257 | +application/prs.cww cww | ||
258 | +# application/prs.hpub+zip | ||
259 | +# application/prs.nprend | ||
260 | +# application/prs.plucker | ||
261 | +# application/prs.rdf-xml-crypt | ||
262 | +# application/prs.xsf+xml | ||
263 | +application/pskc+xml pskcxml | ||
264 | +# application/qsig | ||
265 | +# application/raptorfec | ||
266 | +# application/rdap+json | ||
267 | +application/rdf+xml rdf | ||
268 | +application/reginfo+xml rif | ||
269 | +application/relax-ng-compact-syntax rnc | ||
270 | +# application/remote-printing | ||
271 | +# application/reputon+json | ||
272 | +application/resource-lists+xml rl | ||
273 | +application/resource-lists-diff+xml rld | ||
274 | +# application/rfc+xml | ||
275 | +# application/riscos | ||
276 | +# application/rlmi+xml | ||
277 | +application/rls-services+xml rs | ||
278 | +application/rpki-ghostbusters gbr | ||
279 | +application/rpki-manifest mft | ||
280 | +application/rpki-roa roa | ||
281 | +# application/rpki-updown | ||
282 | +application/rsd+xml rsd | ||
283 | +application/rss+xml rss | ||
284 | +application/rtf rtf | ||
285 | +# application/rtploopback | ||
286 | +# application/rtx | ||
287 | +# application/samlassertion+xml | ||
288 | +# application/samlmetadata+xml | ||
289 | +application/sbml+xml sbml | ||
290 | +# application/scaip+xml | ||
291 | +# application/scim+json | ||
292 | +application/scvp-cv-request scq | ||
293 | +application/scvp-cv-response scs | ||
294 | +application/scvp-vp-request spq | ||
295 | +application/scvp-vp-response spp | ||
296 | +application/sdp sdp | ||
297 | +# application/sep+xml | ||
298 | +# application/sep-exi | ||
299 | +# application/session-info | ||
300 | +# application/set-payment | ||
301 | +application/set-payment-initiation setpay | ||
302 | +# application/set-registration | ||
303 | +application/set-registration-initiation setreg | ||
304 | +# application/sgml | ||
305 | +# application/sgml-open-catalog | ||
306 | +application/shf+xml shf | ||
307 | +# application/sieve | ||
308 | +# application/simple-filter+xml | ||
309 | +# application/simple-message-summary | ||
310 | +# application/simplesymbolcontainer | ||
311 | +# application/slate | ||
312 | +# application/smil | ||
313 | +application/smil+xml smi smil | ||
314 | +# application/smpte336m | ||
315 | +# application/soap+fastinfoset | ||
316 | +# application/soap+xml | ||
317 | +application/sparql-query rq | ||
318 | +application/sparql-results+xml srx | ||
319 | +# application/spirits-event+xml | ||
320 | +# application/sql | ||
321 | +application/srgs gram | ||
322 | +application/srgs+xml grxml | ||
323 | +application/sru+xml sru | ||
324 | +application/ssdl+xml ssdl | ||
325 | +application/ssml+xml ssml | ||
326 | +# application/tamp-apex-update | ||
327 | +# application/tamp-apex-update-confirm | ||
328 | +# application/tamp-community-update | ||
329 | +# application/tamp-community-update-confirm | ||
330 | +# application/tamp-error | ||
331 | +# application/tamp-sequence-adjust | ||
332 | +# application/tamp-sequence-adjust-confirm | ||
333 | +# application/tamp-status-query | ||
334 | +# application/tamp-status-response | ||
335 | +# application/tamp-update | ||
336 | +# application/tamp-update-confirm | ||
337 | +application/tei+xml tei teicorpus | ||
338 | +application/thraud+xml tfi | ||
339 | +# application/timestamp-query | ||
340 | +# application/timestamp-reply | ||
341 | +application/timestamped-data tsd | ||
342 | +# application/ttml+xml | ||
343 | +# application/tve-trigger | ||
344 | +# application/ulpfec | ||
345 | +# application/urc-grpsheet+xml | ||
346 | +# application/urc-ressheet+xml | ||
347 | +# application/urc-targetdesc+xml | ||
348 | +# application/urc-uisocketdesc+xml | ||
349 | +# application/vcard+json | ||
350 | +# application/vcard+xml | ||
351 | +# application/vemmi | ||
352 | +# application/vividence.scriptfile | ||
353 | +# application/vnd.3gpp-prose+xml | ||
354 | +# application/vnd.3gpp-prose-pc3ch+xml | ||
355 | +# application/vnd.3gpp.access-transfer-events+xml | ||
356 | +# application/vnd.3gpp.bsf+xml | ||
357 | +# application/vnd.3gpp.mid-call+xml | ||
358 | +application/vnd.3gpp.pic-bw-large plb | ||
359 | +application/vnd.3gpp.pic-bw-small psb | ||
360 | +application/vnd.3gpp.pic-bw-var pvb | ||
361 | +# application/vnd.3gpp.sms | ||
362 | +# application/vnd.3gpp.sms+xml | ||
363 | +# application/vnd.3gpp.srvcc-ext+xml | ||
364 | +# application/vnd.3gpp.srvcc-info+xml | ||
365 | +# application/vnd.3gpp.state-and-event-info+xml | ||
366 | +# application/vnd.3gpp.ussd+xml | ||
367 | +# application/vnd.3gpp2.bcmcsinfo+xml | ||
368 | +# application/vnd.3gpp2.sms | ||
369 | +application/vnd.3gpp2.tcap tcap | ||
370 | +# application/vnd.3lightssoftware.imagescal | ||
371 | +application/vnd.3m.post-it-notes pwn | ||
372 | +application/vnd.accpac.simply.aso aso | ||
373 | +application/vnd.accpac.simply.imp imp | ||
374 | +application/vnd.acucobol acu | ||
375 | +application/vnd.acucorp atc acutc | ||
376 | +application/vnd.adobe.air-application-installer-package+zip air | ||
377 | +# application/vnd.adobe.flash.movie | ||
378 | +application/vnd.adobe.formscentral.fcdt fcdt | ||
379 | +application/vnd.adobe.fxp fxp fxpl | ||
380 | +# application/vnd.adobe.partial-upload | ||
381 | +application/vnd.adobe.xdp+xml xdp | ||
382 | +application/vnd.adobe.xfdf xfdf | ||
383 | +# application/vnd.aether.imp | ||
384 | +# application/vnd.ah-barcode | ||
385 | +application/vnd.ahead.space ahead | ||
386 | +application/vnd.airzip.filesecure.azf azf | ||
387 | +application/vnd.airzip.filesecure.azs azs | ||
388 | +application/vnd.amazon.ebook azw | ||
389 | +# application/vnd.amazon.mobi8-ebook | ||
390 | +application/vnd.americandynamics.acc acc | ||
391 | +application/vnd.amiga.ami ami | ||
392 | +# application/vnd.amundsen.maze+xml | ||
393 | +application/vnd.android.package-archive apk | ||
394 | +# application/vnd.anki | ||
395 | +application/vnd.anser-web-certificate-issue-initiation cii | ||
396 | +application/vnd.anser-web-funds-transfer-initiation fti | ||
397 | +application/vnd.antix.game-component atx | ||
398 | +# application/vnd.apache.thrift.binary | ||
399 | +# application/vnd.apache.thrift.compact | ||
400 | +# application/vnd.apache.thrift.json | ||
401 | +# application/vnd.api+json | ||
402 | +application/vnd.apple.installer+xml mpkg | ||
403 | +application/vnd.apple.mpegurl m3u8 | ||
404 | +# application/vnd.arastra.swi | ||
405 | +application/vnd.aristanetworks.swi swi | ||
406 | +# application/vnd.artsquare | ||
407 | +application/vnd.astraea-software.iota iota | ||
408 | +application/vnd.audiograph aep | ||
409 | +# application/vnd.autopackage | ||
410 | +# application/vnd.avistar+xml | ||
411 | +# application/vnd.balsamiq.bmml+xml | ||
412 | +# application/vnd.balsamiq.bmpr | ||
413 | +# application/vnd.bekitzur-stech+json | ||
414 | +# application/vnd.biopax.rdf+xml | ||
415 | +application/vnd.blueice.multipass mpm | ||
416 | +# application/vnd.bluetooth.ep.oob | ||
417 | +# application/vnd.bluetooth.le.oob | ||
418 | +application/vnd.bmi bmi | ||
419 | +application/vnd.businessobjects rep | ||
420 | +# application/vnd.cab-jscript | ||
421 | +# application/vnd.canon-cpdl | ||
422 | +# application/vnd.canon-lips | ||
423 | +# application/vnd.cendio.thinlinc.clientconf | ||
424 | +# application/vnd.century-systems.tcp_stream | ||
425 | +application/vnd.chemdraw+xml cdxml | ||
426 | +# application/vnd.chess-pgn | ||
427 | +application/vnd.chipnuts.karaoke-mmd mmd | ||
428 | +application/vnd.cinderella cdy | ||
429 | +# application/vnd.cirpack.isdn-ext | ||
430 | +# application/vnd.citationstyles.style+xml | ||
431 | +application/vnd.claymore cla | ||
432 | +application/vnd.cloanto.rp9 rp9 | ||
433 | +application/vnd.clonk.c4group c4g c4d c4f c4p c4u | ||
434 | +application/vnd.cluetrust.cartomobile-config c11amc | ||
435 | +application/vnd.cluetrust.cartomobile-config-pkg c11amz | ||
436 | +# application/vnd.coffeescript | ||
437 | +# application/vnd.collection+json | ||
438 | +# application/vnd.collection.doc+json | ||
439 | +# application/vnd.collection.next+json | ||
440 | +# application/vnd.comicbook+zip | ||
441 | +# application/vnd.commerce-battelle | ||
442 | +application/vnd.commonspace csp | ||
443 | +application/vnd.contact.cmsg cdbcmsg | ||
444 | +# application/vnd.coreos.ignition+json | ||
445 | +application/vnd.cosmocaller cmc | ||
446 | +application/vnd.crick.clicker clkx | ||
447 | +application/vnd.crick.clicker.keyboard clkk | ||
448 | +application/vnd.crick.clicker.palette clkp | ||
449 | +application/vnd.crick.clicker.template clkt | ||
450 | +application/vnd.crick.clicker.wordbank clkw | ||
451 | +application/vnd.criticaltools.wbs+xml wbs | ||
452 | +application/vnd.ctc-posml pml | ||
453 | +# application/vnd.ctct.ws+xml | ||
454 | +# application/vnd.cups-pdf | ||
455 | +# application/vnd.cups-postscript | ||
456 | +application/vnd.cups-ppd ppd | ||
457 | +# application/vnd.cups-raster | ||
458 | +# application/vnd.cups-raw | ||
459 | +# application/vnd.curl | ||
460 | +application/vnd.curl.car car | ||
461 | +application/vnd.curl.pcurl pcurl | ||
462 | +# application/vnd.cyan.dean.root+xml | ||
463 | +# application/vnd.cybank | ||
464 | +application/vnd.dart dart | ||
465 | +application/vnd.data-vision.rdz rdz | ||
466 | +# application/vnd.debian.binary-package | ||
467 | +application/vnd.dece.data uvf uvvf uvd uvvd | ||
468 | +application/vnd.dece.ttml+xml uvt uvvt | ||
469 | +application/vnd.dece.unspecified uvx uvvx | ||
470 | +application/vnd.dece.zip uvz uvvz | ||
471 | +application/vnd.denovo.fcselayout-link fe_launch | ||
472 | +# application/vnd.desmume.movie | ||
473 | +# application/vnd.dir-bi.plate-dl-nosuffix | ||
474 | +# application/vnd.dm.delegation+xml | ||
475 | +application/vnd.dna dna | ||
476 | +# application/vnd.document+json | ||
477 | +application/vnd.dolby.mlp mlp | ||
478 | +# application/vnd.dolby.mobile.1 | ||
479 | +# application/vnd.dolby.mobile.2 | ||
480 | +# application/vnd.doremir.scorecloud-binary-document | ||
481 | +application/vnd.dpgraph dpg | ||
482 | +application/vnd.dreamfactory dfac | ||
483 | +# application/vnd.drive+json | ||
484 | +application/vnd.ds-keypoint kpxx | ||
485 | +# application/vnd.dtg.local | ||
486 | +# application/vnd.dtg.local.flash | ||
487 | +# application/vnd.dtg.local.html | ||
488 | +application/vnd.dvb.ait ait | ||
489 | +# application/vnd.dvb.dvbj | ||
490 | +# application/vnd.dvb.esgcontainer | ||
491 | +# application/vnd.dvb.ipdcdftnotifaccess | ||
492 | +# application/vnd.dvb.ipdcesgaccess | ||
493 | +# application/vnd.dvb.ipdcesgaccess2 | ||
494 | +# application/vnd.dvb.ipdcesgpdd | ||
495 | +# application/vnd.dvb.ipdcroaming | ||
496 | +# application/vnd.dvb.iptv.alfec-base | ||
497 | +# application/vnd.dvb.iptv.alfec-enhancement | ||
498 | +# application/vnd.dvb.notif-aggregate-root+xml | ||
499 | +# application/vnd.dvb.notif-container+xml | ||
500 | +# application/vnd.dvb.notif-generic+xml | ||
501 | +# application/vnd.dvb.notif-ia-msglist+xml | ||
502 | +# application/vnd.dvb.notif-ia-registration-request+xml | ||
503 | +# application/vnd.dvb.notif-ia-registration-response+xml | ||
504 | +# application/vnd.dvb.notif-init+xml | ||
505 | +# application/vnd.dvb.pfr | ||
506 | +application/vnd.dvb.service svc | ||
507 | +# application/vnd.dxr | ||
508 | +application/vnd.dynageo geo | ||
509 | +# application/vnd.dzr | ||
510 | +# application/vnd.easykaraoke.cdgdownload | ||
511 | +# application/vnd.ecdis-update | ||
512 | +application/vnd.ecowin.chart mag | ||
513 | +# application/vnd.ecowin.filerequest | ||
514 | +# application/vnd.ecowin.fileupdate | ||
515 | +# application/vnd.ecowin.series | ||
516 | +# application/vnd.ecowin.seriesrequest | ||
517 | +# application/vnd.ecowin.seriesupdate | ||
518 | +# application/vnd.emclient.accessrequest+xml | ||
519 | +application/vnd.enliven nml | ||
520 | +# application/vnd.enphase.envoy | ||
521 | +# application/vnd.eprints.data+xml | ||
522 | +application/vnd.epson.esf esf | ||
523 | +application/vnd.epson.msf msf | ||
524 | +application/vnd.epson.quickanime qam | ||
525 | +application/vnd.epson.salt slt | ||
526 | +application/vnd.epson.ssf ssf | ||
527 | +# application/vnd.ericsson.quickcall | ||
528 | +application/vnd.eszigno3+xml es3 et3 | ||
529 | +# application/vnd.etsi.aoc+xml | ||
530 | +# application/vnd.etsi.asic-e+zip | ||
531 | +# application/vnd.etsi.asic-s+zip | ||
532 | +# application/vnd.etsi.cug+xml | ||
533 | +# application/vnd.etsi.iptvcommand+xml | ||
534 | +# application/vnd.etsi.iptvdiscovery+xml | ||
535 | +# application/vnd.etsi.iptvprofile+xml | ||
536 | +# application/vnd.etsi.iptvsad-bc+xml | ||
537 | +# application/vnd.etsi.iptvsad-cod+xml | ||
538 | +# application/vnd.etsi.iptvsad-npvr+xml | ||
539 | +# application/vnd.etsi.iptvservice+xml | ||
540 | +# application/vnd.etsi.iptvsync+xml | ||
541 | +# application/vnd.etsi.iptvueprofile+xml | ||
542 | +# application/vnd.etsi.mcid+xml | ||
543 | +# application/vnd.etsi.mheg5 | ||
544 | +# application/vnd.etsi.overload-control-policy-dataset+xml | ||
545 | +# application/vnd.etsi.pstn+xml | ||
546 | +# application/vnd.etsi.sci+xml | ||
547 | +# application/vnd.etsi.simservs+xml | ||
548 | +# application/vnd.etsi.timestamp-token | ||
549 | +# application/vnd.etsi.tsl+xml | ||
550 | +# application/vnd.etsi.tsl.der | ||
551 | +# application/vnd.eudora.data | ||
552 | +application/vnd.ezpix-album ez2 | ||
553 | +application/vnd.ezpix-package ez3 | ||
554 | +# application/vnd.f-secure.mobile | ||
555 | +# application/vnd.fastcopy-disk-image | ||
556 | +application/vnd.fdf fdf | ||
557 | +application/vnd.fdsn.mseed mseed | ||
558 | +application/vnd.fdsn.seed seed dataless | ||
559 | +# application/vnd.ffsns | ||
560 | +# application/vnd.filmit.zfc | ||
561 | +# application/vnd.fints | ||
562 | +# application/vnd.firemonkeys.cloudcell | ||
563 | +application/vnd.flographit gph | ||
564 | +application/vnd.fluxtime.clip ftc | ||
565 | +# application/vnd.font-fontforge-sfd | ||
566 | +application/vnd.framemaker fm frame maker book | ||
567 | +application/vnd.frogans.fnc fnc | ||
568 | +application/vnd.frogans.ltf ltf | ||
569 | +application/vnd.fsc.weblaunch fsc | ||
570 | +application/vnd.fujitsu.oasys oas | ||
571 | +application/vnd.fujitsu.oasys2 oa2 | ||
572 | +application/vnd.fujitsu.oasys3 oa3 | ||
573 | +application/vnd.fujitsu.oasysgp fg5 | ||
574 | +application/vnd.fujitsu.oasysprs bh2 | ||
575 | +# application/vnd.fujixerox.art-ex | ||
576 | +# application/vnd.fujixerox.art4 | ||
577 | +application/vnd.fujixerox.ddd ddd | ||
578 | +application/vnd.fujixerox.docuworks xdw | ||
579 | +application/vnd.fujixerox.docuworks.binder xbd | ||
580 | +# application/vnd.fujixerox.docuworks.container | ||
581 | +# application/vnd.fujixerox.hbpl | ||
582 | +# application/vnd.fut-misnet | ||
583 | +application/vnd.fuzzysheet fzs | ||
584 | +application/vnd.genomatix.tuxedo txd | ||
585 | +# application/vnd.geo+json | ||
586 | +# application/vnd.geocube+xml | ||
587 | +application/vnd.geogebra.file ggb | ||
588 | +application/vnd.geogebra.tool ggt | ||
589 | +application/vnd.geometry-explorer gex gre | ||
590 | +application/vnd.geonext gxt | ||
591 | +application/vnd.geoplan g2w | ||
592 | +application/vnd.geospace g3w | ||
593 | +# application/vnd.gerber | ||
594 | +# application/vnd.globalplatform.card-content-mgt | ||
595 | +# application/vnd.globalplatform.card-content-mgt-response | ||
596 | +application/vnd.gmx gmx | ||
597 | +application/vnd.google-earth.kml+xml kml | ||
598 | +application/vnd.google-earth.kmz kmz | ||
599 | +# application/vnd.gov.sk.e-form+xml | ||
600 | +# application/vnd.gov.sk.e-form+zip | ||
601 | +# application/vnd.gov.sk.xmldatacontainer+xml | ||
602 | +application/vnd.grafeq gqf gqs | ||
603 | +# application/vnd.gridmp | ||
604 | +application/vnd.groove-account gac | ||
605 | +application/vnd.groove-help ghf | ||
606 | +application/vnd.groove-identity-message gim | ||
607 | +application/vnd.groove-injector grv | ||
608 | +application/vnd.groove-tool-message gtm | ||
609 | +application/vnd.groove-tool-template tpl | ||
610 | +application/vnd.groove-vcard vcg | ||
611 | +# application/vnd.hal+json | ||
612 | +application/vnd.hal+xml hal | ||
613 | +application/vnd.handheld-entertainment+xml zmm | ||
614 | +application/vnd.hbci hbci | ||
615 | +# application/vnd.hcl-bireports | ||
616 | +# application/vnd.hdt | ||
617 | +# application/vnd.heroku+json | ||
618 | +application/vnd.hhe.lesson-player les | ||
619 | +application/vnd.hp-hpgl hpgl | ||
620 | +application/vnd.hp-hpid hpid | ||
621 | +application/vnd.hp-hps hps | ||
622 | +application/vnd.hp-jlyt jlt | ||
623 | +application/vnd.hp-pcl pcl | ||
624 | +application/vnd.hp-pclxl pclxl | ||
625 | +# application/vnd.httphone | ||
626 | +application/vnd.hydrostatix.sof-data sfd-hdstx | ||
627 | +# application/vnd.hyperdrive+json | ||
628 | +# application/vnd.hzn-3d-crossword | ||
629 | +# application/vnd.ibm.afplinedata | ||
630 | +# application/vnd.ibm.electronic-media | ||
631 | +application/vnd.ibm.minipay mpy | ||
632 | +application/vnd.ibm.modcap afp listafp list3820 | ||
633 | +application/vnd.ibm.rights-management irm | ||
634 | +application/vnd.ibm.secure-container sc | ||
635 | +application/vnd.iccprofile icc icm | ||
636 | +# application/vnd.ieee.1905 | ||
637 | +application/vnd.igloader igl | ||
638 | +application/vnd.immervision-ivp ivp | ||
639 | +application/vnd.immervision-ivu ivu | ||
640 | +# application/vnd.ims.imsccv1p1 | ||
641 | +# application/vnd.ims.imsccv1p2 | ||
642 | +# application/vnd.ims.imsccv1p3 | ||
643 | +# application/vnd.ims.lis.v2.result+json | ||
644 | +# application/vnd.ims.lti.v2.toolconsumerprofile+json | ||
645 | +# application/vnd.ims.lti.v2.toolproxy+json | ||
646 | +# application/vnd.ims.lti.v2.toolproxy.id+json | ||
647 | +# application/vnd.ims.lti.v2.toolsettings+json | ||
648 | +# application/vnd.ims.lti.v2.toolsettings.simple+json | ||
649 | +# application/vnd.informedcontrol.rms+xml | ||
650 | +# application/vnd.informix-visionary | ||
651 | +# application/vnd.infotech.project | ||
652 | +# application/vnd.infotech.project+xml | ||
653 | +# application/vnd.innopath.wamp.notification | ||
654 | +application/vnd.insors.igm igm | ||
655 | +application/vnd.intercon.formnet xpw xpx | ||
656 | +application/vnd.intergeo i2g | ||
657 | +# application/vnd.intertrust.digibox | ||
658 | +# application/vnd.intertrust.nncp | ||
659 | +application/vnd.intu.qbo qbo | ||
660 | +application/vnd.intu.qfx qfx | ||
661 | +# application/vnd.iptc.g2.catalogitem+xml | ||
662 | +# application/vnd.iptc.g2.conceptitem+xml | ||
663 | +# application/vnd.iptc.g2.knowledgeitem+xml | ||
664 | +# application/vnd.iptc.g2.newsitem+xml | ||
665 | +# application/vnd.iptc.g2.newsmessage+xml | ||
666 | +# application/vnd.iptc.g2.packageitem+xml | ||
667 | +# application/vnd.iptc.g2.planningitem+xml | ||
668 | +application/vnd.ipunplugged.rcprofile rcprofile | ||
669 | +application/vnd.irepository.package+xml irp | ||
670 | +application/vnd.is-xpr xpr | ||
671 | +application/vnd.isac.fcs fcs | ||
672 | +application/vnd.jam jam | ||
673 | +# application/vnd.japannet-directory-service | ||
674 | +# application/vnd.japannet-jpnstore-wakeup | ||
675 | +# application/vnd.japannet-payment-wakeup | ||
676 | +# application/vnd.japannet-registration | ||
677 | +# application/vnd.japannet-registration-wakeup | ||
678 | +# application/vnd.japannet-setstore-wakeup | ||
679 | +# application/vnd.japannet-verification | ||
680 | +# application/vnd.japannet-verification-wakeup | ||
681 | +application/vnd.jcp.javame.midlet-rms rms | ||
682 | +application/vnd.jisp jisp | ||
683 | +application/vnd.joost.joda-archive joda | ||
684 | +# application/vnd.jsk.isdn-ngn | ||
685 | +application/vnd.kahootz ktz ktr | ||
686 | +application/vnd.kde.karbon karbon | ||
687 | +application/vnd.kde.kchart chrt | ||
688 | +application/vnd.kde.kformula kfo | ||
689 | +application/vnd.kde.kivio flw | ||
690 | +application/vnd.kde.kontour kon | ||
691 | +application/vnd.kde.kpresenter kpr kpt | ||
692 | +application/vnd.kde.kspread ksp | ||
693 | +application/vnd.kde.kword kwd kwt | ||
694 | +application/vnd.kenameaapp htke | ||
695 | +application/vnd.kidspiration kia | ||
696 | +application/vnd.kinar kne knp | ||
697 | +application/vnd.koan skp skd skt skm | ||
698 | +application/vnd.kodak-descriptor sse | ||
699 | +application/vnd.las.las+xml lasxml | ||
700 | +# application/vnd.liberty-request+xml | ||
701 | +application/vnd.llamagraphics.life-balance.desktop lbd | ||
702 | +application/vnd.llamagraphics.life-balance.exchange+xml lbe | ||
703 | +application/vnd.lotus-1-2-3 123 | ||
704 | +application/vnd.lotus-approach apr | ||
705 | +application/vnd.lotus-freelance pre | ||
706 | +application/vnd.lotus-notes nsf | ||
707 | +application/vnd.lotus-organizer org | ||
708 | +application/vnd.lotus-screencam scm | ||
709 | +application/vnd.lotus-wordpro lwp | ||
710 | +application/vnd.macports.portpkg portpkg | ||
711 | +# application/vnd.mapbox-vector-tile | ||
712 | +# application/vnd.marlin.drm.actiontoken+xml | ||
713 | +# application/vnd.marlin.drm.conftoken+xml | ||
714 | +# application/vnd.marlin.drm.license+xml | ||
715 | +# application/vnd.marlin.drm.mdcf | ||
716 | +# application/vnd.mason+json | ||
717 | +# application/vnd.maxmind.maxmind-db | ||
718 | +application/vnd.mcd mcd | ||
719 | +application/vnd.medcalcdata mc1 | ||
720 | +application/vnd.mediastation.cdkey cdkey | ||
721 | +# application/vnd.meridian-slingshot | ||
722 | +application/vnd.mfer mwf | ||
723 | +application/vnd.mfmp mfm | ||
724 | +# application/vnd.micro+json | ||
725 | +application/vnd.micrografx.flo flo | ||
726 | +application/vnd.micrografx.igx igx | ||
727 | +# application/vnd.microsoft.portable-executable | ||
728 | +# application/vnd.miele+json | ||
729 | +application/vnd.mif mif | ||
730 | +# application/vnd.minisoft-hp3000-save | ||
731 | +# application/vnd.mitsubishi.misty-guard.trustweb | ||
732 | +application/vnd.mobius.daf daf | ||
733 | +application/vnd.mobius.dis dis | ||
734 | +application/vnd.mobius.mbk mbk | ||
735 | +application/vnd.mobius.mqy mqy | ||
736 | +application/vnd.mobius.msl msl | ||
737 | +application/vnd.mobius.plc plc | ||
738 | +application/vnd.mobius.txf txf | ||
739 | +application/vnd.mophun.application mpn | ||
740 | +application/vnd.mophun.certificate mpc | ||
741 | +# application/vnd.motorola.flexsuite | ||
742 | +# application/vnd.motorola.flexsuite.adsi | ||
743 | +# application/vnd.motorola.flexsuite.fis | ||
744 | +# application/vnd.motorola.flexsuite.gotap | ||
745 | +# application/vnd.motorola.flexsuite.kmr | ||
746 | +# application/vnd.motorola.flexsuite.ttc | ||
747 | +# application/vnd.motorola.flexsuite.wem | ||
748 | +# application/vnd.motorola.iprm | ||
749 | +application/vnd.mozilla.xul+xml xul | ||
750 | +# application/vnd.ms-3mfdocument | ||
751 | +application/vnd.ms-artgalry cil | ||
752 | +# application/vnd.ms-asf | ||
753 | +application/vnd.ms-cab-compressed cab | ||
754 | +# application/vnd.ms-color.iccprofile | ||
755 | +application/vnd.ms-excel xls xlm xla xlc xlt xlw | ||
756 | +application/vnd.ms-excel.addin.macroenabled.12 xlam | ||
757 | +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb | ||
758 | +application/vnd.ms-excel.sheet.macroenabled.12 xlsm | ||
759 | +application/vnd.ms-excel.template.macroenabled.12 xltm | ||
760 | +application/vnd.ms-fontobject eot | ||
761 | +application/vnd.ms-htmlhelp chm | ||
762 | +application/vnd.ms-ims ims | ||
763 | +application/vnd.ms-lrm lrm | ||
764 | +# application/vnd.ms-office.activex+xml | ||
765 | +application/vnd.ms-officetheme thmx | ||
766 | +# application/vnd.ms-opentype | ||
767 | +# application/vnd.ms-package.obfuscated-opentype | ||
768 | +application/vnd.ms-pki.seccat cat | ||
769 | +application/vnd.ms-pki.stl stl | ||
770 | +# application/vnd.ms-playready.initiator+xml | ||
771 | +application/vnd.ms-powerpoint ppt pps pot | ||
772 | +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam | ||
773 | +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm | ||
774 | +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm | ||
775 | +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm | ||
776 | +application/vnd.ms-powerpoint.template.macroenabled.12 potm | ||
777 | +# application/vnd.ms-printdevicecapabilities+xml | ||
778 | +# application/vnd.ms-printing.printticket+xml | ||
779 | +# application/vnd.ms-printschematicket+xml | ||
780 | +application/vnd.ms-project mpp mpt | ||
781 | +# application/vnd.ms-tnef | ||
782 | +# application/vnd.ms-windows.devicepairing | ||
783 | +# application/vnd.ms-windows.nwprinting.oob | ||
784 | +# application/vnd.ms-windows.printerpairing | ||
785 | +# application/vnd.ms-windows.wsd.oob | ||
786 | +# application/vnd.ms-wmdrm.lic-chlg-req | ||
787 | +# application/vnd.ms-wmdrm.lic-resp | ||
788 | +# application/vnd.ms-wmdrm.meter-chlg-req | ||
789 | +# application/vnd.ms-wmdrm.meter-resp | ||
790 | +application/vnd.ms-word.document.macroenabled.12 docm | ||
791 | +application/vnd.ms-word.template.macroenabled.12 dotm | ||
792 | +application/vnd.ms-works wps wks wcm wdb | ||
793 | +application/vnd.ms-wpl wpl | ||
794 | +application/vnd.ms-xpsdocument xps | ||
795 | +# application/vnd.msa-disk-image | ||
796 | +application/vnd.mseq mseq | ||
797 | +# application/vnd.msign | ||
798 | +# application/vnd.multiad.creator | ||
799 | +# application/vnd.multiad.creator.cif | ||
800 | +# application/vnd.music-niff | ||
801 | +application/vnd.musician mus | ||
802 | +application/vnd.muvee.style msty | ||
803 | +application/vnd.mynfc taglet | ||
804 | +# application/vnd.ncd.control | ||
805 | +# application/vnd.ncd.reference | ||
806 | +# application/vnd.nervana | ||
807 | +# application/vnd.netfpx | ||
808 | +application/vnd.neurolanguage.nlu nlu | ||
809 | +# application/vnd.nintendo.nitro.rom | ||
810 | +# application/vnd.nintendo.snes.rom | ||
811 | +application/vnd.nitf ntf nitf | ||
812 | +application/vnd.noblenet-directory nnd | ||
813 | +application/vnd.noblenet-sealer nns | ||
814 | +application/vnd.noblenet-web nnw | ||
815 | +# application/vnd.nokia.catalogs | ||
816 | +# application/vnd.nokia.conml+wbxml | ||
817 | +# application/vnd.nokia.conml+xml | ||
818 | +# application/vnd.nokia.iptv.config+xml | ||
819 | +# application/vnd.nokia.isds-radio-presets | ||
820 | +# application/vnd.nokia.landmark+wbxml | ||
821 | +# application/vnd.nokia.landmark+xml | ||
822 | +# application/vnd.nokia.landmarkcollection+xml | ||
823 | +# application/vnd.nokia.n-gage.ac+xml | ||
824 | +application/vnd.nokia.n-gage.data ngdat | ||
825 | +application/vnd.nokia.n-gage.symbian.install n-gage | ||
826 | +# application/vnd.nokia.ncd | ||
827 | +# application/vnd.nokia.pcd+wbxml | ||
828 | +# application/vnd.nokia.pcd+xml | ||
829 | +application/vnd.nokia.radio-preset rpst | ||
830 | +application/vnd.nokia.radio-presets rpss | ||
831 | +application/vnd.novadigm.edm edm | ||
832 | +application/vnd.novadigm.edx edx | ||
833 | +application/vnd.novadigm.ext ext | ||
834 | +# application/vnd.ntt-local.content-share | ||
835 | +# application/vnd.ntt-local.file-transfer | ||
836 | +# application/vnd.ntt-local.ogw_remote-access | ||
837 | +# application/vnd.ntt-local.sip-ta_remote | ||
838 | +# application/vnd.ntt-local.sip-ta_tcp_stream | ||
839 | +application/vnd.oasis.opendocument.chart odc | ||
840 | +application/vnd.oasis.opendocument.chart-template otc | ||
841 | +application/vnd.oasis.opendocument.database odb | ||
842 | +application/vnd.oasis.opendocument.formula odf | ||
843 | +application/vnd.oasis.opendocument.formula-template odft | ||
844 | +application/vnd.oasis.opendocument.graphics odg | ||
845 | +application/vnd.oasis.opendocument.graphics-template otg | ||
846 | +application/vnd.oasis.opendocument.image odi | ||
847 | +application/vnd.oasis.opendocument.image-template oti | ||
848 | +application/vnd.oasis.opendocument.presentation odp | ||
849 | +application/vnd.oasis.opendocument.presentation-template otp | ||
850 | +application/vnd.oasis.opendocument.spreadsheet ods | ||
851 | +application/vnd.oasis.opendocument.spreadsheet-template ots | ||
852 | +application/vnd.oasis.opendocument.text odt | ||
853 | +application/vnd.oasis.opendocument.text-master odm | ||
854 | +application/vnd.oasis.opendocument.text-template ott | ||
855 | +application/vnd.oasis.opendocument.text-web oth | ||
856 | +# application/vnd.obn | ||
857 | +# application/vnd.oftn.l10n+json | ||
858 | +# application/vnd.oipf.contentaccessdownload+xml | ||
859 | +# application/vnd.oipf.contentaccessstreaming+xml | ||
860 | +# application/vnd.oipf.cspg-hexbinary | ||
861 | +# application/vnd.oipf.dae.svg+xml | ||
862 | +# application/vnd.oipf.dae.xhtml+xml | ||
863 | +# application/vnd.oipf.mippvcontrolmessage+xml | ||
864 | +# application/vnd.oipf.pae.gem | ||
865 | +# application/vnd.oipf.spdiscovery+xml | ||
866 | +# application/vnd.oipf.spdlist+xml | ||
867 | +# application/vnd.oipf.ueprofile+xml | ||
868 | +# application/vnd.oipf.userprofile+xml | ||
869 | +application/vnd.olpc-sugar xo | ||
870 | +# application/vnd.oma-scws-config | ||
871 | +# application/vnd.oma-scws-http-request | ||
872 | +# application/vnd.oma-scws-http-response | ||
873 | +# application/vnd.oma.bcast.associated-procedure-parameter+xml | ||
874 | +# application/vnd.oma.bcast.drm-trigger+xml | ||
875 | +# application/vnd.oma.bcast.imd+xml | ||
876 | +# application/vnd.oma.bcast.ltkm | ||
877 | +# application/vnd.oma.bcast.notification+xml | ||
878 | +# application/vnd.oma.bcast.provisioningtrigger | ||
879 | +# application/vnd.oma.bcast.sgboot | ||
880 | +# application/vnd.oma.bcast.sgdd+xml | ||
881 | +# application/vnd.oma.bcast.sgdu | ||
882 | +# application/vnd.oma.bcast.simple-symbol-container | ||
883 | +# application/vnd.oma.bcast.smartcard-trigger+xml | ||
884 | +# application/vnd.oma.bcast.sprov+xml | ||
885 | +# application/vnd.oma.bcast.stkm | ||
886 | +# application/vnd.oma.cab-address-book+xml | ||
887 | +# application/vnd.oma.cab-feature-handler+xml | ||
888 | +# application/vnd.oma.cab-pcc+xml | ||
889 | +# application/vnd.oma.cab-subs-invite+xml | ||
890 | +# application/vnd.oma.cab-user-prefs+xml | ||
891 | +# application/vnd.oma.dcd | ||
892 | +# application/vnd.oma.dcdc | ||
893 | +application/vnd.oma.dd2+xml dd2 | ||
894 | +# application/vnd.oma.drm.risd+xml | ||
895 | +# application/vnd.oma.group-usage-list+xml | ||
896 | +# application/vnd.oma.lwm2m+json | ||
897 | +# application/vnd.oma.lwm2m+tlv | ||
898 | +# application/vnd.oma.pal+xml | ||
899 | +# application/vnd.oma.poc.detailed-progress-report+xml | ||
900 | +# application/vnd.oma.poc.final-report+xml | ||
901 | +# application/vnd.oma.poc.groups+xml | ||
902 | +# application/vnd.oma.poc.invocation-descriptor+xml | ||
903 | +# application/vnd.oma.poc.optimized-progress-report+xml | ||
904 | +# application/vnd.oma.push | ||
905 | +# application/vnd.oma.scidm.messages+xml | ||
906 | +# application/vnd.oma.xcap-directory+xml | ||
907 | +# application/vnd.omads-email+xml | ||
908 | +# application/vnd.omads-file+xml | ||
909 | +# application/vnd.omads-folder+xml | ||
910 | +# application/vnd.omaloc-supl-init | ||
911 | +# application/vnd.onepager | ||
912 | +# application/vnd.openblox.game+xml | ||
913 | +# application/vnd.openblox.game-binary | ||
914 | +# application/vnd.openeye.oeb | ||
915 | +application/vnd.openofficeorg.extension oxt | ||
916 | +# application/vnd.openxmlformats-officedocument.custom-properties+xml | ||
917 | +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml | ||
918 | +# application/vnd.openxmlformats-officedocument.drawing+xml | ||
919 | +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml | ||
920 | +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml | ||
921 | +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml | ||
922 | +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml | ||
923 | +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml | ||
924 | +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml | ||
925 | +# application/vnd.openxmlformats-officedocument.extended-properties+xml | ||
926 | +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml | ||
927 | +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml | ||
928 | +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml | ||
929 | +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml | ||
930 | +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml | ||
931 | +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx | ||
932 | +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml | ||
933 | +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml | ||
934 | +application/vnd.openxmlformats-officedocument.presentationml.slide sldx | ||
935 | +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml | ||
936 | +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml | ||
937 | +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml | ||
938 | +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx | ||
939 | +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml | ||
940 | +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml | ||
941 | +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml | ||
942 | +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml | ||
943 | +application/vnd.openxmlformats-officedocument.presentationml.template potx | ||
944 | +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml | ||
945 | +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml | ||
946 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml | ||
947 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml | ||
948 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml | ||
949 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml | ||
950 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml | ||
951 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml | ||
952 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml | ||
953 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml | ||
954 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml | ||
955 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml | ||
956 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml | ||
957 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml | ||
958 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml | ||
959 | +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx | ||
960 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml | ||
961 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml | ||
962 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml | ||
963 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml | ||
964 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml | ||
965 | +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx | ||
966 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml | ||
967 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml | ||
968 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml | ||
969 | +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml | ||
970 | +# application/vnd.openxmlformats-officedocument.theme+xml | ||
971 | +# application/vnd.openxmlformats-officedocument.themeoverride+xml | ||
972 | +# application/vnd.openxmlformats-officedocument.vmldrawing | ||
973 | +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml | ||
974 | +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx | ||
975 | +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml | ||
976 | +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml | ||
977 | +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml | ||
978 | +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml | ||
979 | +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml | ||
980 | +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml | ||
981 | +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml | ||
982 | +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml | ||
983 | +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml | ||
984 | +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx | ||
985 | +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml | ||
986 | +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml | ||
987 | +# application/vnd.openxmlformats-package.core-properties+xml | ||
988 | +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml | ||
989 | +# application/vnd.openxmlformats-package.relationships+xml | ||
990 | +# application/vnd.oracle.resource+json | ||
991 | +# application/vnd.orange.indata | ||
992 | +# application/vnd.osa.netdeploy | ||
993 | +application/vnd.osgeo.mapguide.package mgp | ||
994 | +# application/vnd.osgi.bundle | ||
995 | +application/vnd.osgi.dp dp | ||
996 | +application/vnd.osgi.subsystem esa | ||
997 | +# application/vnd.otps.ct-kip+xml | ||
998 | +# application/vnd.oxli.countgraph | ||
999 | +# application/vnd.pagerduty+json | ||
1000 | +application/vnd.palm pdb pqa oprc | ||
1001 | +# application/vnd.panoply | ||
1002 | +# application/vnd.paos.xml | ||
1003 | +application/vnd.pawaafile paw | ||
1004 | +# application/vnd.pcos | ||
1005 | +application/vnd.pg.format str | ||
1006 | +application/vnd.pg.osasli ei6 | ||
1007 | +# application/vnd.piaccess.application-licence | ||
1008 | +application/vnd.picsel efif | ||
1009 | +application/vnd.pmi.widget wg | ||
1010 | +# application/vnd.poc.group-advertisement+xml | ||
1011 | +application/vnd.pocketlearn plf | ||
1012 | +application/vnd.powerbuilder6 pbd | ||
1013 | +# application/vnd.powerbuilder6-s | ||
1014 | +# application/vnd.powerbuilder7 | ||
1015 | +# application/vnd.powerbuilder7-s | ||
1016 | +# application/vnd.powerbuilder75 | ||
1017 | +# application/vnd.powerbuilder75-s | ||
1018 | +# application/vnd.preminet | ||
1019 | +application/vnd.previewsystems.box box | ||
1020 | +application/vnd.proteus.magazine mgz | ||
1021 | +application/vnd.publishare-delta-tree qps | ||
1022 | +application/vnd.pvi.ptid1 ptid | ||
1023 | +# application/vnd.pwg-multiplexed | ||
1024 | +# application/vnd.pwg-xhtml-print+xml | ||
1025 | +# application/vnd.qualcomm.brew-app-res | ||
1026 | +# application/vnd.quarantainenet | ||
1027 | +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb | ||
1028 | +# application/vnd.quobject-quoxdocument | ||
1029 | +# application/vnd.radisys.moml+xml | ||
1030 | +# application/vnd.radisys.msml+xml | ||
1031 | +# application/vnd.radisys.msml-audit+xml | ||
1032 | +# application/vnd.radisys.msml-audit-conf+xml | ||
1033 | +# application/vnd.radisys.msml-audit-conn+xml | ||
1034 | +# application/vnd.radisys.msml-audit-dialog+xml | ||
1035 | +# application/vnd.radisys.msml-audit-stream+xml | ||
1036 | +# application/vnd.radisys.msml-conf+xml | ||
1037 | +# application/vnd.radisys.msml-dialog+xml | ||
1038 | +# application/vnd.radisys.msml-dialog-base+xml | ||
1039 | +# application/vnd.radisys.msml-dialog-fax-detect+xml | ||
1040 | +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml | ||
1041 | +# application/vnd.radisys.msml-dialog-group+xml | ||
1042 | +# application/vnd.radisys.msml-dialog-speech+xml | ||
1043 | +# application/vnd.radisys.msml-dialog-transform+xml | ||
1044 | +# application/vnd.rainstor.data | ||
1045 | +# application/vnd.rapid | ||
1046 | +# application/vnd.rar | ||
1047 | +application/vnd.realvnc.bed bed | ||
1048 | +application/vnd.recordare.musicxml mxl | ||
1049 | +application/vnd.recordare.musicxml+xml musicxml | ||
1050 | +# application/vnd.renlearn.rlprint | ||
1051 | +application/vnd.rig.cryptonote cryptonote | ||
1052 | +application/vnd.rim.cod cod | ||
1053 | +application/vnd.rn-realmedia rm | ||
1054 | +application/vnd.rn-realmedia-vbr rmvb | ||
1055 | +application/vnd.route66.link66+xml link66 | ||
1056 | +# application/vnd.rs-274x | ||
1057 | +# application/vnd.ruckus.download | ||
1058 | +# application/vnd.s3sms | ||
1059 | +application/vnd.sailingtracker.track st | ||
1060 | +# application/vnd.sbm.cid | ||
1061 | +# application/vnd.sbm.mid2 | ||
1062 | +# application/vnd.scribus | ||
1063 | +# application/vnd.sealed.3df | ||
1064 | +# application/vnd.sealed.csf | ||
1065 | +# application/vnd.sealed.doc | ||
1066 | +# application/vnd.sealed.eml | ||
1067 | +# application/vnd.sealed.mht | ||
1068 | +# application/vnd.sealed.net | ||
1069 | +# application/vnd.sealed.ppt | ||
1070 | +# application/vnd.sealed.tiff | ||
1071 | +# application/vnd.sealed.xls | ||
1072 | +# application/vnd.sealedmedia.softseal.html | ||
1073 | +# application/vnd.sealedmedia.softseal.pdf | ||
1074 | +application/vnd.seemail see | ||
1075 | +application/vnd.sema sema | ||
1076 | +application/vnd.semd semd | ||
1077 | +application/vnd.semf semf | ||
1078 | +application/vnd.shana.informed.formdata ifm | ||
1079 | +application/vnd.shana.informed.formtemplate itp | ||
1080 | +application/vnd.shana.informed.interchange iif | ||
1081 | +application/vnd.shana.informed.package ipk | ||
1082 | +application/vnd.simtech-mindmapper twd twds | ||
1083 | +# application/vnd.siren+json | ||
1084 | +application/vnd.smaf mmf | ||
1085 | +# application/vnd.smart.notebook | ||
1086 | +application/vnd.smart.teacher teacher | ||
1087 | +# application/vnd.software602.filler.form+xml | ||
1088 | +# application/vnd.software602.filler.form-xml-zip | ||
1089 | +application/vnd.solent.sdkm+xml sdkm sdkd | ||
1090 | +application/vnd.spotfire.dxp dxp | ||
1091 | +application/vnd.spotfire.sfs sfs | ||
1092 | +# application/vnd.sss-cod | ||
1093 | +# application/vnd.sss-dtf | ||
1094 | +# application/vnd.sss-ntf | ||
1095 | +application/vnd.stardivision.calc sdc | ||
1096 | +application/vnd.stardivision.draw sda | ||
1097 | +application/vnd.stardivision.impress sdd | ||
1098 | +application/vnd.stardivision.math smf | ||
1099 | +application/vnd.stardivision.writer sdw vor | ||
1100 | +application/vnd.stardivision.writer-global sgl | ||
1101 | +application/vnd.stepmania.package smzip | ||
1102 | +application/vnd.stepmania.stepchart sm | ||
1103 | +# application/vnd.street-stream | ||
1104 | +# application/vnd.sun.wadl+xml | ||
1105 | +application/vnd.sun.xml.calc sxc | ||
1106 | +application/vnd.sun.xml.calc.template stc | ||
1107 | +application/vnd.sun.xml.draw sxd | ||
1108 | +application/vnd.sun.xml.draw.template std | ||
1109 | +application/vnd.sun.xml.impress sxi | ||
1110 | +application/vnd.sun.xml.impress.template sti | ||
1111 | +application/vnd.sun.xml.math sxm | ||
1112 | +application/vnd.sun.xml.writer sxw | ||
1113 | +application/vnd.sun.xml.writer.global sxg | ||
1114 | +application/vnd.sun.xml.writer.template stw | ||
1115 | +application/vnd.sus-calendar sus susp | ||
1116 | +application/vnd.svd svd | ||
1117 | +# application/vnd.swiftview-ics | ||
1118 | +application/vnd.symbian.install sis sisx | ||
1119 | +application/vnd.syncml+xml xsm | ||
1120 | +application/vnd.syncml.dm+wbxml bdm | ||
1121 | +application/vnd.syncml.dm+xml xdm | ||
1122 | +# application/vnd.syncml.dm.notification | ||
1123 | +# application/vnd.syncml.dmddf+wbxml | ||
1124 | +# application/vnd.syncml.dmddf+xml | ||
1125 | +# application/vnd.syncml.dmtnds+wbxml | ||
1126 | +# application/vnd.syncml.dmtnds+xml | ||
1127 | +# application/vnd.syncml.ds.notification | ||
1128 | +application/vnd.tao.intent-module-archive tao | ||
1129 | +application/vnd.tcpdump.pcap pcap cap dmp | ||
1130 | +# application/vnd.tmd.mediaflex.api+xml | ||
1131 | +# application/vnd.tml | ||
1132 | +application/vnd.tmobile-livetv tmo | ||
1133 | +application/vnd.trid.tpt tpt | ||
1134 | +application/vnd.triscape.mxs mxs | ||
1135 | +application/vnd.trueapp tra | ||
1136 | +# application/vnd.truedoc | ||
1137 | +# application/vnd.ubisoft.webplayer | ||
1138 | +application/vnd.ufdl ufd ufdl | ||
1139 | +application/vnd.uiq.theme utz | ||
1140 | +application/vnd.umajin umj | ||
1141 | +application/vnd.unity unityweb | ||
1142 | +application/vnd.uoml+xml uoml | ||
1143 | +# application/vnd.uplanet.alert | ||
1144 | +# application/vnd.uplanet.alert-wbxml | ||
1145 | +# application/vnd.uplanet.bearer-choice | ||
1146 | +# application/vnd.uplanet.bearer-choice-wbxml | ||
1147 | +# application/vnd.uplanet.cacheop | ||
1148 | +# application/vnd.uplanet.cacheop-wbxml | ||
1149 | +# application/vnd.uplanet.channel | ||
1150 | +# application/vnd.uplanet.channel-wbxml | ||
1151 | +# application/vnd.uplanet.list | ||
1152 | +# application/vnd.uplanet.list-wbxml | ||
1153 | +# application/vnd.uplanet.listcmd | ||
1154 | +# application/vnd.uplanet.listcmd-wbxml | ||
1155 | +# application/vnd.uplanet.signal | ||
1156 | +# application/vnd.uri-map | ||
1157 | +# application/vnd.valve.source.material | ||
1158 | +application/vnd.vcx vcx | ||
1159 | +# application/vnd.vd-study | ||
1160 | +# application/vnd.vectorworks | ||
1161 | +# application/vnd.vel+json | ||
1162 | +# application/vnd.verimatrix.vcas | ||
1163 | +# application/vnd.vidsoft.vidconference | ||
1164 | +application/vnd.visio vsd vst vss vsw | ||
1165 | +application/vnd.visionary vis | ||
1166 | +# application/vnd.vividence.scriptfile | ||
1167 | +application/vnd.vsf vsf | ||
1168 | +# application/vnd.wap.sic | ||
1169 | +# application/vnd.wap.slc | ||
1170 | +application/vnd.wap.wbxml wbxml | ||
1171 | +application/vnd.wap.wmlc wmlc | ||
1172 | +application/vnd.wap.wmlscriptc wmlsc | ||
1173 | +application/vnd.webturbo wtb | ||
1174 | +# application/vnd.wfa.p2p | ||
1175 | +# application/vnd.wfa.wsc | ||
1176 | +# application/vnd.windows.devicepairing | ||
1177 | +# application/vnd.wmc | ||
1178 | +# application/vnd.wmf.bootstrap | ||
1179 | +# application/vnd.wolfram.mathematica | ||
1180 | +# application/vnd.wolfram.mathematica.package | ||
1181 | +application/vnd.wolfram.player nbp | ||
1182 | +application/vnd.wordperfect wpd | ||
1183 | +application/vnd.wqd wqd | ||
1184 | +# application/vnd.wrq-hp3000-labelled | ||
1185 | +application/vnd.wt.stf stf | ||
1186 | +# application/vnd.wv.csp+wbxml | ||
1187 | +# application/vnd.wv.csp+xml | ||
1188 | +# application/vnd.wv.ssp+xml | ||
1189 | +# application/vnd.xacml+json | ||
1190 | +application/vnd.xara xar | ||
1191 | +application/vnd.xfdl xfdl | ||
1192 | +# application/vnd.xfdl.webform | ||
1193 | +# application/vnd.xmi+xml | ||
1194 | +# application/vnd.xmpie.cpkg | ||
1195 | +# application/vnd.xmpie.dpkg | ||
1196 | +# application/vnd.xmpie.plan | ||
1197 | +# application/vnd.xmpie.ppkg | ||
1198 | +# application/vnd.xmpie.xlim | ||
1199 | +application/vnd.yamaha.hv-dic hvd | ||
1200 | +application/vnd.yamaha.hv-script hvs | ||
1201 | +application/vnd.yamaha.hv-voice hvp | ||
1202 | +application/vnd.yamaha.openscoreformat osf | ||
1203 | +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg | ||
1204 | +# application/vnd.yamaha.remote-setup | ||
1205 | +application/vnd.yamaha.smaf-audio saf | ||
1206 | +application/vnd.yamaha.smaf-phrase spf | ||
1207 | +# application/vnd.yamaha.through-ngn | ||
1208 | +# application/vnd.yamaha.tunnel-udpencap | ||
1209 | +# application/vnd.yaoweme | ||
1210 | +application/vnd.yellowriver-custom-menu cmp | ||
1211 | +application/vnd.zul zir zirz | ||
1212 | +application/vnd.zzazz.deck+xml zaz | ||
1213 | +application/voicexml+xml vxml | ||
1214 | +# application/vq-rtcpxr | ||
1215 | +# application/watcherinfo+xml | ||
1216 | +# application/whoispp-query | ||
1217 | +# application/whoispp-response | ||
1218 | +application/widget wgt | ||
1219 | +application/winhlp hlp | ||
1220 | +# application/wita | ||
1221 | +# application/wordperfect5.1 | ||
1222 | +application/wsdl+xml wsdl | ||
1223 | +application/wspolicy+xml wspolicy | ||
1224 | +application/x-7z-compressed 7z | ||
1225 | +application/x-abiword abw | ||
1226 | +application/x-ace-compressed ace | ||
1227 | +# application/x-amf | ||
1228 | +application/x-apple-diskimage dmg | ||
1229 | +application/x-authorware-bin aab x32 u32 vox | ||
1230 | +application/x-authorware-map aam | ||
1231 | +application/x-authorware-seg aas | ||
1232 | +application/x-bcpio bcpio | ||
1233 | +application/x-bittorrent torrent | ||
1234 | +application/x-blorb blb blorb | ||
1235 | +application/x-bzip bz | ||
1236 | +application/x-bzip2 bz2 boz | ||
1237 | +application/x-cbr cbr cba cbt cbz cb7 | ||
1238 | +application/x-cdlink vcd | ||
1239 | +application/x-cfs-compressed cfs | ||
1240 | +application/x-chat chat | ||
1241 | +application/x-chess-pgn pgn | ||
1242 | +# application/x-compress | ||
1243 | +application/x-conference nsc | ||
1244 | +application/x-cpio cpio | ||
1245 | +application/x-csh csh | ||
1246 | +application/x-debian-package deb udeb | ||
1247 | +application/x-dgc-compressed dgc | ||
1248 | +application/x-director dir dcr dxr cst cct cxt w3d fgd swa | ||
1249 | +application/x-doom wad | ||
1250 | +application/x-dtbncx+xml ncx | ||
1251 | +application/x-dtbook+xml dtb | ||
1252 | +application/x-dtbresource+xml res | ||
1253 | +application/x-dvi dvi | ||
1254 | +application/x-envoy evy | ||
1255 | +application/x-eva eva | ||
1256 | +application/x-font-bdf bdf | ||
1257 | +# application/x-font-dos | ||
1258 | +# application/x-font-framemaker | ||
1259 | +application/x-font-ghostscript gsf | ||
1260 | +# application/x-font-libgrx | ||
1261 | +application/x-font-linux-psf psf | ||
1262 | +application/x-font-pcf pcf | ||
1263 | +application/x-font-snf snf | ||
1264 | +# application/x-font-speedo | ||
1265 | +# application/x-font-sunos-news | ||
1266 | +application/x-font-type1 pfa pfb pfm afm | ||
1267 | +# application/x-font-vfont | ||
1268 | +application/x-freearc arc | ||
1269 | +application/x-futuresplash spl | ||
1270 | +application/x-gca-compressed gca | ||
1271 | +application/x-glulx ulx | ||
1272 | +application/x-gnumeric gnumeric | ||
1273 | +application/x-gramps-xml gramps | ||
1274 | +application/x-gtar gtar | ||
1275 | +# application/x-gzip | ||
1276 | +application/x-hdf hdf | ||
1277 | +application/x-install-instructions install | ||
1278 | +application/x-iso9660-image iso | ||
1279 | +application/x-java-jnlp-file jnlp | ||
1280 | +application/x-latex latex | ||
1281 | +application/x-lzh-compressed lzh lha | ||
1282 | +application/x-mie mie | ||
1283 | +application/x-mobipocket-ebook prc mobi | ||
1284 | +application/x-ms-application application | ||
1285 | +application/x-ms-shortcut lnk | ||
1286 | +application/x-ms-wmd wmd | ||
1287 | +application/x-ms-wmz wmz | ||
1288 | +application/x-ms-xbap xbap | ||
1289 | +application/x-msaccess mdb | ||
1290 | +application/x-msbinder obd | ||
1291 | +application/x-mscardfile crd | ||
1292 | +application/x-msclip clp | ||
1293 | +application/x-msdownload exe dll com bat msi | ||
1294 | +application/x-msmediaview mvb m13 m14 | ||
1295 | +application/x-msmetafile wmf wmz emf emz | ||
1296 | +application/x-msmoney mny | ||
1297 | +application/x-mspublisher pub | ||
1298 | +application/x-msschedule scd | ||
1299 | +application/x-msterminal trm | ||
1300 | +application/x-mswrite wri | ||
1301 | +application/x-netcdf nc cdf | ||
1302 | +application/x-nzb nzb | ||
1303 | +application/x-pkcs12 p12 pfx | ||
1304 | +application/x-pkcs7-certificates p7b spc | ||
1305 | +application/x-pkcs7-certreqresp p7r | ||
1306 | +application/x-rar-compressed rar | ||
1307 | +application/x-research-info-systems ris | ||
1308 | +application/x-sh sh | ||
1309 | +application/x-shar shar | ||
1310 | +application/x-shockwave-flash swf | ||
1311 | +application/x-silverlight-app xap | ||
1312 | +application/x-sql sql | ||
1313 | +application/x-stuffit sit | ||
1314 | +application/x-stuffitx sitx | ||
1315 | +application/x-subrip srt | ||
1316 | +application/x-sv4cpio sv4cpio | ||
1317 | +application/x-sv4crc sv4crc | ||
1318 | +application/x-t3vm-image t3 | ||
1319 | +application/x-tads gam | ||
1320 | +application/x-tar tar | ||
1321 | +application/x-tcl tcl | ||
1322 | +application/x-tex tex | ||
1323 | +application/x-tex-tfm tfm | ||
1324 | +application/x-texinfo texinfo texi | ||
1325 | +application/x-tgif obj | ||
1326 | +application/x-ustar ustar | ||
1327 | +application/x-wais-source src | ||
1328 | +# application/x-www-form-urlencoded | ||
1329 | +application/x-x509-ca-cert der crt | ||
1330 | +application/x-xfig fig | ||
1331 | +application/x-xliff+xml xlf | ||
1332 | +application/x-xpinstall xpi | ||
1333 | +application/x-xz xz | ||
1334 | +application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8 | ||
1335 | +# application/x400-bp | ||
1336 | +# application/xacml+xml | ||
1337 | +application/xaml+xml xaml | ||
1338 | +# application/xcap-att+xml | ||
1339 | +# application/xcap-caps+xml | ||
1340 | +application/xcap-diff+xml xdf | ||
1341 | +# application/xcap-el+xml | ||
1342 | +# application/xcap-error+xml | ||
1343 | +# application/xcap-ns+xml | ||
1344 | +# application/xcon-conference-info+xml | ||
1345 | +# application/xcon-conference-info-diff+xml | ||
1346 | +application/xenc+xml xenc | ||
1347 | +application/xhtml+xml xhtml xht | ||
1348 | +# application/xhtml-voice+xml | ||
1349 | +application/xml xml xsl | ||
1350 | +application/xml-dtd dtd | ||
1351 | +# application/xml-external-parsed-entity | ||
1352 | +# application/xml-patch+xml | ||
1353 | +# application/xmpp+xml | ||
1354 | +application/xop+xml xop | ||
1355 | +application/xproc+xml xpl | ||
1356 | +application/xslt+xml xslt | ||
1357 | +application/xspf+xml xspf | ||
1358 | +application/xv+xml mxml xhvml xvml xvm | ||
1359 | +application/yang yang | ||
1360 | +application/yin+xml yin | ||
1361 | +application/zip zip | ||
1362 | +# application/zlib | ||
1363 | +# audio/1d-interleaved-parityfec | ||
1364 | +# audio/32kadpcm | ||
1365 | +# audio/3gpp | ||
1366 | +# audio/3gpp2 | ||
1367 | +# audio/ac3 | ||
1368 | +audio/adpcm adp | ||
1369 | +# audio/amr | ||
1370 | +# audio/amr-wb | ||
1371 | +# audio/amr-wb+ | ||
1372 | +# audio/aptx | ||
1373 | +# audio/asc | ||
1374 | +# audio/atrac-advanced-lossless | ||
1375 | +# audio/atrac-x | ||
1376 | +# audio/atrac3 | ||
1377 | +audio/basic au snd | ||
1378 | +# audio/bv16 | ||
1379 | +# audio/bv32 | ||
1380 | +# audio/clearmode | ||
1381 | +# audio/cn | ||
1382 | +# audio/dat12 | ||
1383 | +# audio/dls | ||
1384 | +# audio/dsr-es201108 | ||
1385 | +# audio/dsr-es202050 | ||
1386 | +# audio/dsr-es202211 | ||
1387 | +# audio/dsr-es202212 | ||
1388 | +# audio/dv | ||
1389 | +# audio/dvi4 | ||
1390 | +# audio/eac3 | ||
1391 | +# audio/encaprtp | ||
1392 | +# audio/evrc | ||
1393 | +# audio/evrc-qcp | ||
1394 | +# audio/evrc0 | ||
1395 | +# audio/evrc1 | ||
1396 | +# audio/evrcb | ||
1397 | +# audio/evrcb0 | ||
1398 | +# audio/evrcb1 | ||
1399 | +# audio/evrcnw | ||
1400 | +# audio/evrcnw0 | ||
1401 | +# audio/evrcnw1 | ||
1402 | +# audio/evrcwb | ||
1403 | +# audio/evrcwb0 | ||
1404 | +# audio/evrcwb1 | ||
1405 | +# audio/evs | ||
1406 | +# audio/example | ||
1407 | +# audio/fwdred | ||
1408 | +# audio/g711-0 | ||
1409 | +# audio/g719 | ||
1410 | +# audio/g722 | ||
1411 | +# audio/g7221 | ||
1412 | +# audio/g723 | ||
1413 | +# audio/g726-16 | ||
1414 | +# audio/g726-24 | ||
1415 | +# audio/g726-32 | ||
1416 | +# audio/g726-40 | ||
1417 | +# audio/g728 | ||
1418 | +# audio/g729 | ||
1419 | +# audio/g7291 | ||
1420 | +# audio/g729d | ||
1421 | +# audio/g729e | ||
1422 | +# audio/gsm | ||
1423 | +# audio/gsm-efr | ||
1424 | +# audio/gsm-hr-08 | ||
1425 | +# audio/ilbc | ||
1426 | +# audio/ip-mr_v2.5 | ||
1427 | +# audio/isac | ||
1428 | +# audio/l16 | ||
1429 | +# audio/l20 | ||
1430 | +# audio/l24 | ||
1431 | +# audio/l8 | ||
1432 | +# audio/lpc | ||
1433 | +audio/midi mid midi kar rmi | ||
1434 | +# audio/mobile-xmf | ||
1435 | +audio/mp4 m4a mp4a | ||
1436 | +# audio/mp4a-latm | ||
1437 | +# audio/mpa | ||
1438 | +# audio/mpa-robust | ||
1439 | +audio/mpeg mpga mp2 mp2a mp3 m2a m3a | ||
1440 | +# audio/mpeg4-generic | ||
1441 | +# audio/musepack | ||
1442 | +audio/ogg oga ogg spx opus | ||
1443 | +# audio/opus | ||
1444 | +# audio/parityfec | ||
1445 | +# audio/pcma | ||
1446 | +# audio/pcma-wb | ||
1447 | +# audio/pcmu | ||
1448 | +# audio/pcmu-wb | ||
1449 | +# audio/prs.sid | ||
1450 | +# audio/qcelp | ||
1451 | +# audio/raptorfec | ||
1452 | +# audio/red | ||
1453 | +# audio/rtp-enc-aescm128 | ||
1454 | +# audio/rtp-midi | ||
1455 | +# audio/rtploopback | ||
1456 | +# audio/rtx | ||
1457 | +audio/s3m s3m | ||
1458 | +audio/silk sil | ||
1459 | +# audio/smv | ||
1460 | +# audio/smv-qcp | ||
1461 | +# audio/smv0 | ||
1462 | +# audio/sp-midi | ||
1463 | +# audio/speex | ||
1464 | +# audio/t140c | ||
1465 | +# audio/t38 | ||
1466 | +# audio/telephone-event | ||
1467 | +# audio/tone | ||
1468 | +# audio/uemclip | ||
1469 | +# audio/ulpfec | ||
1470 | +# audio/vdvi | ||
1471 | +# audio/vmr-wb | ||
1472 | +# audio/vnd.3gpp.iufp | ||
1473 | +# audio/vnd.4sb | ||
1474 | +# audio/vnd.audiokoz | ||
1475 | +# audio/vnd.celp | ||
1476 | +# audio/vnd.cisco.nse | ||
1477 | +# audio/vnd.cmles.radio-events | ||
1478 | +# audio/vnd.cns.anp1 | ||
1479 | +# audio/vnd.cns.inf1 | ||
1480 | +audio/vnd.dece.audio uva uvva | ||
1481 | +audio/vnd.digital-winds eol | ||
1482 | +# audio/vnd.dlna.adts | ||
1483 | +# audio/vnd.dolby.heaac.1 | ||
1484 | +# audio/vnd.dolby.heaac.2 | ||
1485 | +# audio/vnd.dolby.mlp | ||
1486 | +# audio/vnd.dolby.mps | ||
1487 | +# audio/vnd.dolby.pl2 | ||
1488 | +# audio/vnd.dolby.pl2x | ||
1489 | +# audio/vnd.dolby.pl2z | ||
1490 | +# audio/vnd.dolby.pulse.1 | ||
1491 | +audio/vnd.dra dra | ||
1492 | +audio/vnd.dts dts | ||
1493 | +audio/vnd.dts.hd dtshd | ||
1494 | +# audio/vnd.dvb.file | ||
1495 | +# audio/vnd.everad.plj | ||
1496 | +# audio/vnd.hns.audio | ||
1497 | +audio/vnd.lucent.voice lvp | ||
1498 | +audio/vnd.ms-playready.media.pya pya | ||
1499 | +# audio/vnd.nokia.mobile-xmf | ||
1500 | +# audio/vnd.nortel.vbk | ||
1501 | +audio/vnd.nuera.ecelp4800 ecelp4800 | ||
1502 | +audio/vnd.nuera.ecelp7470 ecelp7470 | ||
1503 | +audio/vnd.nuera.ecelp9600 ecelp9600 | ||
1504 | +# audio/vnd.octel.sbc | ||
1505 | +# audio/vnd.qcelp | ||
1506 | +# audio/vnd.rhetorex.32kadpcm | ||
1507 | +audio/vnd.rip rip | ||
1508 | +# audio/vnd.sealedmedia.softseal.mpeg | ||
1509 | +# audio/vnd.vmx.cvsd | ||
1510 | +# audio/vorbis | ||
1511 | +# audio/vorbis-config | ||
1512 | +audio/webm weba | ||
1513 | +audio/x-aac aac | ||
1514 | +audio/x-aiff aif aiff aifc | ||
1515 | +audio/x-caf caf | ||
1516 | +audio/x-flac flac | ||
1517 | +audio/x-matroska mka | ||
1518 | +audio/x-mpegurl m3u | ||
1519 | +audio/x-ms-wax wax | ||
1520 | +audio/x-ms-wma wma | ||
1521 | +audio/x-pn-realaudio ram ra | ||
1522 | +audio/x-pn-realaudio-plugin rmp | ||
1523 | +# audio/x-tta | ||
1524 | +audio/x-wav wav | ||
1525 | +audio/xm xm | ||
1526 | +chemical/x-cdx cdx | ||
1527 | +chemical/x-cif cif | ||
1528 | +chemical/x-cmdf cmdf | ||
1529 | +chemical/x-cml cml | ||
1530 | +chemical/x-csml csml | ||
1531 | +# chemical/x-pdb | ||
1532 | +chemical/x-xyz xyz | ||
1533 | +font/collection ttc | ||
1534 | +font/otf otf | ||
1535 | +# font/sfnt | ||
1536 | +font/ttf ttf | ||
1537 | +font/woff woff | ||
1538 | +font/woff2 woff2 | ||
1539 | +image/bmp bmp | ||
1540 | +image/cgm cgm | ||
1541 | +# image/dicom-rle | ||
1542 | +# image/emf | ||
1543 | +# image/example | ||
1544 | +# image/fits | ||
1545 | +image/g3fax g3 | ||
1546 | +image/gif gif | ||
1547 | +image/ief ief | ||
1548 | +# image/jls | ||
1549 | +# image/jp2 | ||
1550 | +image/jpeg jpeg jpg jpe | ||
1551 | +# image/jpm | ||
1552 | +# image/jpx | ||
1553 | +image/ktx ktx | ||
1554 | +# image/naplps | ||
1555 | +image/png png | ||
1556 | +image/prs.btif btif | ||
1557 | +# image/prs.pti | ||
1558 | +# image/pwg-raster | ||
1559 | +image/sgi sgi | ||
1560 | +image/svg+xml svg svgz | ||
1561 | +# image/t38 | ||
1562 | +image/tiff tiff tif | ||
1563 | +# image/tiff-fx | ||
1564 | +image/vnd.adobe.photoshop psd | ||
1565 | +# image/vnd.airzip.accelerator.azv | ||
1566 | +# image/vnd.cns.inf2 | ||
1567 | +image/vnd.dece.graphic uvi uvvi uvg uvvg | ||
1568 | +image/vnd.djvu djvu djv | ||
1569 | +image/vnd.dvb.subtitle sub | ||
1570 | +image/vnd.dwg dwg | ||
1571 | +image/vnd.dxf dxf | ||
1572 | +image/vnd.fastbidsheet fbs | ||
1573 | +image/vnd.fpx fpx | ||
1574 | +image/vnd.fst fst | ||
1575 | +image/vnd.fujixerox.edmics-mmr mmr | ||
1576 | +image/vnd.fujixerox.edmics-rlc rlc | ||
1577 | +# image/vnd.globalgraphics.pgb | ||
1578 | +# image/vnd.microsoft.icon | ||
1579 | +# image/vnd.mix | ||
1580 | +# image/vnd.mozilla.apng | ||
1581 | +image/vnd.ms-modi mdi | ||
1582 | +image/vnd.ms-photo wdp | ||
1583 | +image/vnd.net-fpx npx | ||
1584 | +# image/vnd.radiance | ||
1585 | +# image/vnd.sealed.png | ||
1586 | +# image/vnd.sealedmedia.softseal.gif | ||
1587 | +# image/vnd.sealedmedia.softseal.jpg | ||
1588 | +# image/vnd.svf | ||
1589 | +# image/vnd.tencent.tap | ||
1590 | +# image/vnd.valve.source.texture | ||
1591 | +image/vnd.wap.wbmp wbmp | ||
1592 | +image/vnd.xiff xif | ||
1593 | +# image/vnd.zbrush.pcx | ||
1594 | +image/webp webp | ||
1595 | +# image/wmf | ||
1596 | +image/x-3ds 3ds | ||
1597 | +image/x-cmu-raster ras | ||
1598 | +image/x-cmx cmx | ||
1599 | +image/x-freehand fh fhc fh4 fh5 fh7 | ||
1600 | +image/x-icon ico | ||
1601 | +image/x-mrsid-image sid | ||
1602 | +image/x-pcx pcx | ||
1603 | +image/x-pict pic pct | ||
1604 | +image/x-portable-anymap pnm | ||
1605 | +image/x-portable-bitmap pbm | ||
1606 | +image/x-portable-graymap pgm | ||
1607 | +image/x-portable-pixmap ppm | ||
1608 | +image/x-rgb rgb | ||
1609 | +image/x-tga tga | ||
1610 | +image/x-xbitmap xbm | ||
1611 | +image/x-xpixmap xpm | ||
1612 | +image/x-xwindowdump xwd | ||
1613 | +# message/cpim | ||
1614 | +# message/delivery-status | ||
1615 | +# message/disposition-notification | ||
1616 | +# message/example | ||
1617 | +# message/external-body | ||
1618 | +# message/feedback-report | ||
1619 | +# message/global | ||
1620 | +# message/global-delivery-status | ||
1621 | +# message/global-disposition-notification | ||
1622 | +# message/global-headers | ||
1623 | +# message/http | ||
1624 | +# message/imdn+xml | ||
1625 | +# message/news | ||
1626 | +# message/partial | ||
1627 | +message/rfc822 eml mime | ||
1628 | +# message/s-http | ||
1629 | +# message/sip | ||
1630 | +# message/sipfrag | ||
1631 | +# message/tracking-status | ||
1632 | +# message/vnd.si.simp | ||
1633 | +# message/vnd.wfa.wsc | ||
1634 | +# model/example | ||
1635 | +# model/gltf+json | ||
1636 | +model/iges igs iges | ||
1637 | +model/mesh msh mesh silo | ||
1638 | +model/vnd.collada+xml dae | ||
1639 | +model/vnd.dwf dwf | ||
1640 | +# model/vnd.flatland.3dml | ||
1641 | +model/vnd.gdl gdl | ||
1642 | +# model/vnd.gs-gdl | ||
1643 | +# model/vnd.gs.gdl | ||
1644 | +model/vnd.gtw gtw | ||
1645 | +# model/vnd.moml+xml | ||
1646 | +model/vnd.mts mts | ||
1647 | +# model/vnd.opengex | ||
1648 | +# model/vnd.parasolid.transmit.binary | ||
1649 | +# model/vnd.parasolid.transmit.text | ||
1650 | +# model/vnd.rosette.annotated-data-model | ||
1651 | +# model/vnd.valve.source.compiled-map | ||
1652 | +model/vnd.vtu vtu | ||
1653 | +model/vrml wrl vrml | ||
1654 | +model/x3d+binary x3db x3dbz | ||
1655 | +# model/x3d+fastinfoset | ||
1656 | +model/x3d+vrml x3dv x3dvz | ||
1657 | +model/x3d+xml x3d x3dz | ||
1658 | +# model/x3d-vrml | ||
1659 | +# multipart/alternative | ||
1660 | +# multipart/appledouble | ||
1661 | +# multipart/byteranges | ||
1662 | +# multipart/digest | ||
1663 | +# multipart/encrypted | ||
1664 | +# multipart/example | ||
1665 | +# multipart/form-data | ||
1666 | +# multipart/header-set | ||
1667 | +# multipart/mixed | ||
1668 | +# multipart/parallel | ||
1669 | +# multipart/related | ||
1670 | +# multipart/report | ||
1671 | +# multipart/signed | ||
1672 | +# multipart/voice-message | ||
1673 | +# multipart/x-mixed-replace | ||
1674 | +# text/1d-interleaved-parityfec | ||
1675 | +text/cache-manifest appcache | ||
1676 | +text/calendar ics ifb | ||
1677 | +text/css css | ||
1678 | +text/csv csv | ||
1679 | +# text/csv-schema | ||
1680 | +# text/directory | ||
1681 | +# text/dns | ||
1682 | +# text/ecmascript | ||
1683 | +# text/encaprtp | ||
1684 | +# text/enriched | ||
1685 | +# text/example | ||
1686 | +# text/fwdred | ||
1687 | +# text/grammar-ref-list | ||
1688 | +text/html html htm | ||
1689 | +text/javascript js mjs | ||
1690 | +# text/jcr-cnd | ||
1691 | +# text/markdown | ||
1692 | +# text/mizar | ||
1693 | +text/n3 n3 | ||
1694 | +# text/parameters | ||
1695 | +# text/parityfec | ||
1696 | +text/plain txt text conf def list log in | ||
1697 | +# text/provenance-notation | ||
1698 | +# text/prs.fallenstein.rst | ||
1699 | +text/prs.lines.tag dsc | ||
1700 | +# text/prs.prop.logic | ||
1701 | +# text/raptorfec | ||
1702 | +# text/red | ||
1703 | +# text/rfc822-headers | ||
1704 | +text/richtext rtx | ||
1705 | +# text/rtf | ||
1706 | +# text/rtp-enc-aescm128 | ||
1707 | +# text/rtploopback | ||
1708 | +# text/rtx | ||
1709 | +text/sgml sgml sgm | ||
1710 | +# text/t140 | ||
1711 | +text/tab-separated-values tsv | ||
1712 | +text/troff t tr roff man me ms | ||
1713 | +text/turtle ttl | ||
1714 | +# text/ulpfec | ||
1715 | +text/uri-list uri uris urls | ||
1716 | +text/vcard vcard | ||
1717 | +# text/vnd.a | ||
1718 | +# text/vnd.abc | ||
1719 | +text/vnd.curl curl | ||
1720 | +text/vnd.curl.dcurl dcurl | ||
1721 | +text/vnd.curl.mcurl mcurl | ||
1722 | +text/vnd.curl.scurl scurl | ||
1723 | +# text/vnd.debian.copyright | ||
1724 | +# text/vnd.dmclientscript | ||
1725 | +text/vnd.dvb.subtitle sub | ||
1726 | +# text/vnd.esmertec.theme-descriptor | ||
1727 | +text/vnd.fly fly | ||
1728 | +text/vnd.fmi.flexstor flx | ||
1729 | +text/vnd.graphviz gv | ||
1730 | +text/vnd.in3d.3dml 3dml | ||
1731 | +text/vnd.in3d.spot spot | ||
1732 | +# text/vnd.iptc.newsml | ||
1733 | +# text/vnd.iptc.nitf | ||
1734 | +# text/vnd.latex-z | ||
1735 | +# text/vnd.motorola.reflex | ||
1736 | +# text/vnd.ms-mediapackage | ||
1737 | +# text/vnd.net2phone.commcenter.command | ||
1738 | +# text/vnd.radisys.msml-basic-layout | ||
1739 | +# text/vnd.si.uricatalogue | ||
1740 | +text/vnd.sun.j2me.app-descriptor jad | ||
1741 | +# text/vnd.trolltech.linguist | ||
1742 | +# text/vnd.wap.si | ||
1743 | +# text/vnd.wap.sl | ||
1744 | +text/vnd.wap.wml wml | ||
1745 | +text/vnd.wap.wmlscript wmls | ||
1746 | +text/x-asm s asm | ||
1747 | +text/x-c c cc cxx cpp h hh dic | ||
1748 | +text/x-fortran f for f77 f90 | ||
1749 | +text/x-java-source java | ||
1750 | +text/x-nfo nfo | ||
1751 | +text/x-opml opml | ||
1752 | +text/x-pascal p pas | ||
1753 | +text/x-setext etx | ||
1754 | +text/x-sfv sfv | ||
1755 | +text/x-uuencode uu | ||
1756 | +text/x-vcalendar vcs | ||
1757 | +text/x-vcard vcf | ||
1758 | +# text/xml | ||
1759 | +# text/xml-external-parsed-entity | ||
1760 | +# video/1d-interleaved-parityfec | ||
1761 | +video/3gpp 3gp | ||
1762 | +# video/3gpp-tt | ||
1763 | +video/3gpp2 3g2 | ||
1764 | +# video/bmpeg | ||
1765 | +# video/bt656 | ||
1766 | +# video/celb | ||
1767 | +# video/dv | ||
1768 | +# video/encaprtp | ||
1769 | +# video/example | ||
1770 | +video/h261 h261 | ||
1771 | +video/h263 h263 | ||
1772 | +# video/h263-1998 | ||
1773 | +# video/h263-2000 | ||
1774 | +video/h264 h264 | ||
1775 | +# video/h264-rcdo | ||
1776 | +# video/h264-svc | ||
1777 | +# video/h265 | ||
1778 | +# video/iso.segment | ||
1779 | +video/jpeg jpgv | ||
1780 | +# video/jpeg2000 | ||
1781 | +video/jpm jpm jpgm | ||
1782 | +video/mj2 mj2 mjp2 | ||
1783 | +# video/mp1s | ||
1784 | +# video/mp2p | ||
1785 | +# video/mp2t | ||
1786 | +video/mp4 mp4 mp4v mpg4 | ||
1787 | +# video/mp4v-es | ||
1788 | +video/mpeg mpeg mpg mpe m1v m2v | ||
1789 | +# video/mpeg4-generic | ||
1790 | +# video/mpv | ||
1791 | +# video/nv | ||
1792 | +video/ogg ogv | ||
1793 | +# video/parityfec | ||
1794 | +# video/pointer | ||
1795 | +video/quicktime qt mov | ||
1796 | +# video/raptorfec | ||
1797 | +# video/raw | ||
1798 | +# video/rtp-enc-aescm128 | ||
1799 | +# video/rtploopback | ||
1800 | +# video/rtx | ||
1801 | +# video/smpte292m | ||
1802 | +# video/ulpfec | ||
1803 | +# video/vc1 | ||
1804 | +# video/vnd.cctv | ||
1805 | +video/vnd.dece.hd uvh uvvh | ||
1806 | +video/vnd.dece.mobile uvm uvvm | ||
1807 | +# video/vnd.dece.mp4 | ||
1808 | +video/vnd.dece.pd uvp uvvp | ||
1809 | +video/vnd.dece.sd uvs uvvs | ||
1810 | +video/vnd.dece.video uvv uvvv | ||
1811 | +# video/vnd.directv.mpeg | ||
1812 | +# video/vnd.directv.mpeg-tts | ||
1813 | +# video/vnd.dlna.mpeg-tts | ||
1814 | +video/vnd.dvb.file dvb | ||
1815 | +video/vnd.fvt fvt | ||
1816 | +# video/vnd.hns.video | ||
1817 | +# video/vnd.iptvforum.1dparityfec-1010 | ||
1818 | +# video/vnd.iptvforum.1dparityfec-2005 | ||
1819 | +# video/vnd.iptvforum.2dparityfec-1010 | ||
1820 | +# video/vnd.iptvforum.2dparityfec-2005 | ||
1821 | +# video/vnd.iptvforum.ttsavc | ||
1822 | +# video/vnd.iptvforum.ttsmpeg2 | ||
1823 | +# video/vnd.motorola.video | ||
1824 | +# video/vnd.motorola.videop | ||
1825 | +video/vnd.mpegurl mxu m4u | ||
1826 | +video/vnd.ms-playready.media.pyv pyv | ||
1827 | +# video/vnd.nokia.interleaved-multimedia | ||
1828 | +# video/vnd.nokia.videovoip | ||
1829 | +# video/vnd.objectvideo | ||
1830 | +# video/vnd.radgamettools.bink | ||
1831 | +# video/vnd.radgamettools.smacker | ||
1832 | +# video/vnd.sealed.mpeg1 | ||
1833 | +# video/vnd.sealed.mpeg4 | ||
1834 | +# video/vnd.sealed.swf | ||
1835 | +# video/vnd.sealedmedia.softseal.mov | ||
1836 | +video/vnd.uvvu.mp4 uvu uvvu | ||
1837 | +video/vnd.vivo viv | ||
1838 | +# video/vp8 | ||
1839 | +video/webm webm | ||
1840 | +video/x-f4v f4v | ||
1841 | +video/x-fli fli | ||
1842 | +video/x-flv flv | ||
1843 | +video/x-m4v m4v | ||
1844 | +video/x-matroska mkv mk3d mks | ||
1845 | +video/x-mng mng | ||
1846 | +video/x-ms-asf asf asx | ||
1847 | +video/x-ms-vob vob | ||
1848 | +video/x-ms-wm wm | ||
1849 | +video/x-ms-wmv wmv | ||
1850 | +video/x-ms-wmx wmx | ||
1851 | +video/x-ms-wvx wvx | ||
1852 | +video/x-msvideo avi | ||
1853 | +video/x-sgi-movie movie | ||
1854 | +video/x-smv smv | ||
1855 | +x-conference/x-cooltalk ice |
lib/Mail/rfc3501协议.html
0 → 100644
此 diff 太大无法显示。
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | namespace Lib; | 3 | namespace Lib; |
4 | 4 | ||
5 | /** | 5 | /** |
6 | - * redis 链接池 | 6 | + * redis 链接池 swoole内置了链接池,自能在协程中使用,所以单独写出来 |
7 | * @author:dc | 7 | * @author:dc |
8 | * @time 2023/2/10 17:04 | 8 | * @time 2023/2/10 17:04 |
9 | * Class RedisPool | 9 | * Class RedisPool |
@@ -25,7 +25,7 @@ class RedisPool { | @@ -25,7 +25,7 @@ class RedisPool { | ||
25 | { | 25 | { |
26 | $this->client = new \Redis(); | 26 | $this->client = new \Redis(); |
27 | 27 | ||
28 | - $this->client->connect(REDIS_HOST,REDIS_PORT); | 28 | + $this->client->connect(REDIS_HOST,REDIS_PORT,1); |
29 | // 密码 | 29 | // 密码 |
30 | REDIS_PASSWORD && $this->client->auth(REDIS_PASSWORD); | 30 | REDIS_PASSWORD && $this->client->auth(REDIS_PASSWORD); |
31 | // 用库4 | 31 | // 用库4 |
@@ -136,6 +136,18 @@ class RedisPool { | @@ -136,6 +136,18 @@ class RedisPool { | ||
136 | } | 136 | } |
137 | 137 | ||
138 | 138 | ||
139 | + /** | ||
140 | + * 删除 | ||
141 | + * @param $key | ||
142 | + * @return int | ||
143 | + * @author:dc | ||
144 | + * @time 2023/2/14 14:04 | ||
145 | + */ | ||
146 | + public function delete($key):int { | ||
147 | + return $this->client->del($key); | ||
148 | + } | ||
149 | + | ||
150 | + | ||
139 | 151 | ||
140 | /** | 152 | /** |
141 | * @param $val | 153 | * @param $val |
@@ -163,7 +175,12 @@ class RedisPool { | @@ -163,7 +175,12 @@ class RedisPool { | ||
163 | public function __destruct() | 175 | public function __destruct() |
164 | { | 176 | { |
165 | // TODO: Implement __destruct() method. | 177 | // TODO: Implement __destruct() method. |
166 | - $this->client->close(); | 178 | + try { |
179 | + if($this->client->ping()){ | ||
180 | + $this->client->close(); | ||
181 | + } | ||
182 | + }catch (\RedisException $e){} | ||
183 | + | ||
167 | $this->client = null; | 184 | $this->client = null; |
168 | } | 185 | } |
169 | 186 | ||
@@ -178,6 +195,13 @@ class RedisPool { | @@ -178,6 +195,13 @@ class RedisPool { | ||
178 | if(empty(static::$instance[$cid])){ | 195 | if(empty(static::$instance[$cid])){ |
179 | static::$instance[$cid] = new \Lib\RedisPool(); | 196 | static::$instance[$cid] = new \Lib\RedisPool(); |
180 | } | 197 | } |
198 | + // ping失败了说明连接炸了 | ||
199 | + try { | ||
200 | + static::$instance[$cid]->client->ping(); | ||
201 | + }catch (\RedisException $e){ | ||
202 | + static::$instance[$cid] = new \Lib\RedisPool(); | ||
203 | + } | ||
204 | + | ||
181 | return static::$instance[$cid]; | 205 | return static::$instance[$cid]; |
182 | } | 206 | } |
183 | 207 |
@@ -17,7 +17,7 @@ class email { | @@ -17,7 +17,7 @@ class email { | ||
17 | * @author:dc | 17 | * @author:dc |
18 | * @time 2023/2/13 14:50 | 18 | * @time 2023/2/13 14:50 |
19 | */ | 19 | */ |
20 | - public static function first($email){ | 20 | + public static function first($email):array { |
21 | return [ | 21 | return [ |
22 | "select * from `emails` where `email` = ? limit 1", | 22 | "select * from `emails` where `email` = ? limit 1", |
23 | [ | 23 | [ |
@@ -26,5 +26,15 @@ class email { | @@ -26,5 +26,15 @@ class email { | ||
26 | ]; | 26 | ]; |
27 | } | 27 | } |
28 | 28 | ||
29 | + /** | ||
30 | + * 统计邮箱的数量 | ||
31 | + * @return string | ||
32 | + * @author:dc | ||
33 | + * @time 2023/2/14 16:16 | ||
34 | + */ | ||
35 | + public static function count():string { | ||
36 | + return "select count(*) from `emails` limit 1"; | ||
37 | + } | ||
38 | + | ||
29 | 39 | ||
30 | } | 40 | } |
-
请 注册 或 登录 后发表评论