| ... | ... | @@ -57,18 +57,70 @@ class Body { | 
|  |  | // 是否是多段 | 
|  |  | $boundary = $this->msg->header->getBoundary(); | 
|  |  | if($boundary){ | 
|  |  | // 切割成块 | 
|  |  | $items = explode($boundary,$this->raw); | 
|  |  | // 切割成块 boundary 的结束符号 前后都会多2个-- | 
|  |  | $items = explode($boundary, | 
|  |  | str_replace('--'.$boundary.'--',$boundary,$this->raw) | 
|  |  | ); | 
|  |  | // 第一个块和最后一块 是没用的块 | 
|  |  | array_shift($items);array_pop($items); | 
|  |  | foreach ($items as $item){ | 
|  |  | $this->items[] = $this->parseItem($item); | 
|  |  | } | 
|  |  | } | 
|  |  | // 不是多块级 | 
|  |  | if(stripos($this->msg->header->get('content-type'),'text/')===0){ | 
|  |  | $this->parseRawHtml(); | 
|  |  | } | 
|  |  |  | 
|  |  |  | 
|  |  | } | 
|  |  |  | 
|  |  | /** | 
|  |  | * 解析 不是多块级的邮件体 直接就是html或者text的 | 
|  |  | * @author:dc | 
|  |  | * @time 2024/9/21 11:37 | 
|  |  | */ | 
|  |  | private function parseRawHtml() { | 
|  |  |  | 
|  |  | $data = $this->parseMimeHeader('Content-Type: '.$this->msg->header->get('content-type')); | 
|  |  |  | 
|  |  | // 设置编码规则 | 
|  |  | if($this->msg->header->get('Content-Transfer-Encoding')){ | 
|  |  | $data->set('Content-Transfer-Encoding',$this->msg->header->get('Content-Transfer-Encoding')); | 
|  |  | } | 
|  |  |  | 
|  |  | // 是否是item fetch | 
|  |  | if(preg_match('/^\* \d+ FETCH \(/',$this->raw)){ | 
|  |  | $body = mb_substr(trim($this->raw),strpos($this->raw,'(')+1,-1); | 
|  |  | // 打散成数组 | 
|  |  | $body = explode("\r\n",trim($body)); | 
|  |  | /***************** start 第一行处理 **************/ | 
|  |  | // 第一行 UID 1568602721 RFC822.TEXT {589} | 
|  |  | $first = explode(' ',$body[0]); | 
|  |  | while (1){ if(str_starts_with(array_shift($first), 'RFC822.')) break; } | 
|  |  | $first = array_values($first); | 
|  |  | $first[0] = preg_replace("/^\{\d+\}/",'',$first[0]); | 
|  |  | // 第一行的结果就是 踢出 UID 1568602721 RFC822.TEXT {589} | 
|  |  | $body[0] = implode("\r\n",$first); | 
|  |  | /***************** end 第一行处理 **************/ | 
|  |  | //            ----------------------------------------------------------- | 
|  |  | /***************** start 最后一行处理 **************/ | 
|  |  | // 最后一行可能是 UID 1568602721 微软的就是 | 
|  |  | $end  = trim(end($body)); | 
|  |  | $end = preg_replace("/(UID \d+)|(FLAGS \([\\a-z* ]*\))/",'',$end); | 
|  |  | if(!trim($end)){ array_pop($body); } | 
|  |  | /***************** end 最后一行处理 **************/ | 
|  |  |  | 
|  |  | // 再次组装成字符串 | 
|  |  | $data->body = trim(implode("\r\n",$body)); | 
|  |  |  | 
|  |  | $this->items[] = $this->bodyDeCode($data); | 
|  |  |  | 
|  |  | } | 
|  |  |  | 
|  |  | } | 
|  |  |  | 
|  |  |  | 
|  |  | /** | 
|  |  | * 解析每个 块 | 
|  |  | * @param string $body 块字符串 | 
| ... | ... | @@ -79,25 +131,35 @@ class Body { | 
|  |  | protected function parseItem(string $body):DataArray { | 
|  |  | list($mime_header,$text) = explode("\r\n\r\n",$body,2); | 
|  |  |  | 
|  |  | // 解析头部 | 
|  |  | $data = $this->parseMimeHeader($mime_header); | 
|  |  |  | 
|  |  | $data->body = $text; | 
|  |  |  | 
|  |  | return $this->bodyDeCode($data); | 
|  |  |  | 
|  |  | } | 
|  |  |  | 
|  |  | /** | 
|  |  | * @param DataArray $data | 
|  |  | * @return DataArray | 
|  |  | * @author:dc | 
|  |  | * @time 2024/9/21 11:39 | 
|  |  | */ | 
|  |  | private function bodyDeCode(DataArray $data):DataArray { | 
|  |  | // 处理body体 的编码 | 
|  |  | switch ($data->get('Content-Transfer-Encoding')){ | 
|  |  | case 'quoted-printable':{ | 
|  |  | $text = quoted_printable_decode($text);break; | 
|  |  | $data->body = quoted_printable_decode($data->body);break; | 
|  |  | } | 
|  |  | case 'base64':{ | 
|  |  | $text = base64_decode($text);break; | 
|  |  | $data->body = base64_decode($data->body);break; | 
|  |  | } | 
|  |  | } | 
|  |  |  | 
|  |  | $data->body = $text; | 
|  |  |  | 
|  |  | return $data; | 
|  |  |  | 
|  |  | } | 
|  |  |  | 
|  |  |  | 
|  |  | /** | 
|  |  | * 解析邮件体里面的每个块 头部 | 
|  |  | * @param string $header | 
| ... | ... | @@ -126,11 +188,13 @@ class Body { | 
|  |  | $contentType = explode(' ',trim(str_replace(';',' ',$data->get('Content-Type')))); | 
|  |  | foreach ($contentType as $ct){ | 
|  |  | $ct = trim($ct); | 
|  |  | // 这个才是真的类型 | 
|  |  | if(str_contains($ct,'/')){ | 
|  |  | $data->set('Content-Type',$ct); | 
|  |  | }elseif (str_contains($ct,'=')){ | 
|  |  | // 这里包含了其他 | 
|  |  | list($name,$val) = explode('=',$ct); | 
|  |  | $data->set($name,trim($val)); | 
|  |  | $data->set($name,trim(str_replace('"','',$val))); | 
|  |  | } | 
|  |  | } | 
|  |  | } | 
| ... | ... | @@ -168,9 +232,10 @@ class Body { | 
|  |  | public function getHtml():string { | 
|  |  | foreach ($this->items as $item){ | 
|  |  | if($item->eq('content-type','text/html')){ | 
|  |  | return $item->body; | 
|  |  | return $item->body ? : ''; | 
|  |  | } | 
|  |  | } | 
|  |  | return ''; | 
|  |  | } | 
|  |  |  | 
|  |  | /** | 
... | ... |  |