作者 邓超

1

@@ -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})启动成功");
25 - // 协程id集  
26 - $cid = [];  
27 - // 删除停止运行的值  
28 - swoole_redis()->delete(RUNNING_REDIS_KEY);  
29 73
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(); 74 + // 是否停止,这里进行阻塞
  75 + if ($table->get('stop','val')){
  76 + // 某个进程退出了
  77 + $table->set('ps'.$worker_id,['val'=>1]);
36 78
37 - $redis = swoole_redis(); 79 + co::sleep(1);
  80 + return true;
  81 + }
38 82
39 - // 同步操作  
40 - while (true){ 83 + // 协程id集
  84 + $cid = [];
41 85
42 - // 开始同步  
43 - try {  
44 - sync();  
45 - }catch (Throwable $e){  
46 - logs($e->getMessage(),LOG_PATH.'/'.$worker_id.'_'.co::getCid().'.log'); 86 + $i = 0;
  87 + $email_total = $table->get('etotal','val');//邮件总数量
  88 + $isRunMaxCNum = 1; // 允许最大协程数量,如果为0则停止所有协程工作,相当于停止脚本
  89 + // 是否退出进程
  90 + while (true){
  91 + $i++;
  92 + // 每10秒 验证一次邮箱数量,好控制协程的数量
  93 + if($i>=10){
  94 + $email_total = $table->get('etotal','val');
  95 + $i = 0;
47 } 96 }
48 97
49 - // 是否停止  
50 - if($redis->get(RUNNING_REDIS_KEY) == 'stop'){ 98 + if(!$email_total){
51 break; 99 break;
52 } 100 }
53 - // 阻塞1秒  
54 - co::sleep(1);  
55 - }  
56 101
57 - // 协程完成后执行的函数  
58 - co::defer(function () use ($cid){  
59 - _echo('正常关闭协程('.co::getCid().')');  
60 - unset($cid[co::getCid()]);  
61 - });  
62 -  
63 - }); 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 + }
64 } 128 }
65 129
66 -// });  
67 - // 是否退出进程  
68 - while (true){  
69 - if($cid){ 130 + // 这个是检查 cid的如果协程全部退出,则退出进程
70 co::sleep(1); 131 co::sleep(1);
71 - }else{ 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
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 "require": { 6 "require": {
7 "php": "^8.0.2", 7 "php": "^8.0.2",
8 "ext-pdo": "*", 8 "ext-pdo": "*",
  9 + "ext-redis": "*",
9 "phpmailer/phpmailer": "^6.7" 10 "phpmailer/phpmailer": "^6.7"
10 }, 11 },
11 "require-dev": { 12 "require-dev": {
@@ -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 * 查询一条数据
  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 +}
  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 +}
  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 +}
  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 +}
  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],'"','<','>','&gt;','&lt;'],'',$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 +}
  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
此 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.
  178 + try {
  179 + if($this->client->ping()){
166 $this->client->close(); 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 }