作者 邓超

m

@@ -54,7 +54,7 @@ class DataArray { @@ -54,7 +54,7 @@ class DataArray {
54 } 54 }
55 } 55 }
56 56
57 - return null; 57 + return '';
58 } 58 }
59 59
60 /** 60 /**
@@ -57,18 +57,70 @@ class Body { @@ -57,18 +57,70 @@ class Body {
57 // 是否是多段 57 // 是否是多段
58 $boundary = $this->msg->header->getBoundary(); 58 $boundary = $this->msg->header->getBoundary();
59 if($boundary){ 59 if($boundary){
60 - // 切割成块  
61 - $items = explode($boundary,$this->raw); 60 + // 切割成块 boundary 的结束符号 前后都会多2个--
  61 + $items = explode($boundary,
  62 + str_replace('--'.$boundary.'--',$boundary,$this->raw)
  63 + );
62 // 第一个块和最后一块 是没用的块 64 // 第一个块和最后一块 是没用的块
63 array_shift($items);array_pop($items); 65 array_shift($items);array_pop($items);
64 foreach ($items as $item){ 66 foreach ($items as $item){
65 $this->items[] = $this->parseItem($item); 67 $this->items[] = $this->parseItem($item);
66 } 68 }
67 } 69 }
  70 + // 不是多块级
  71 + if(stripos($this->msg->header->get('content-type'),'text/')===0){
  72 + $this->parseRawHtml();
  73 + }
  74 +
  75 +
  76 + }
  77 +
  78 + /**
  79 + * 解析 不是多块级的邮件体 直接就是html或者text的
  80 + * @author:dc
  81 + * @time 2024/9/21 11:37
  82 + */
  83 + private function parseRawHtml() {
  84 +
  85 + $data = $this->parseMimeHeader('Content-Type: '.$this->msg->header->get('content-type'));
  86 +
  87 + // 设置编码规则
  88 + if($this->msg->header->get('Content-Transfer-Encoding')){
  89 + $data->set('Content-Transfer-Encoding',$this->msg->header->get('Content-Transfer-Encoding'));
  90 + }
68 91
  92 + // 是否是item fetch
  93 + if(preg_match('/^\* \d+ FETCH \(/',$this->raw)){
  94 + $body = mb_substr(trim($this->raw),strpos($this->raw,'(')+1,-1);
  95 + // 打散成数组
  96 + $body = explode("\r\n",trim($body));
  97 + /***************** start 第一行处理 **************/
  98 + // 第一行 UID 1568602721 RFC822.TEXT {589}
  99 + $first = explode(' ',$body[0]);
  100 + while (1){ if(str_starts_with(array_shift($first), 'RFC822.')) break; }
  101 + $first = array_values($first);
  102 + $first[0] = preg_replace("/^\{\d+\}/",'',$first[0]);
  103 + // 第一行的结果就是 踢出 UID 1568602721 RFC822.TEXT {589}
  104 + $body[0] = implode("\r\n",$first);
  105 + /***************** end 第一行处理 **************/
  106 +// -----------------------------------------------------------
  107 + /***************** start 最后一行处理 **************/
  108 + // 最后一行可能是 UID 1568602721 微软的就是
  109 + $end = trim(end($body));
  110 + $end = preg_replace("/(UID \d+)|(FLAGS \([\\a-z* ]*\))/",'',$end);
  111 + if(!trim($end)){ array_pop($body); }
  112 + /***************** end 最后一行处理 **************/
  113 +
  114 + // 再次组装成字符串
  115 + $data->body = trim(implode("\r\n",$body));
  116 +
  117 + $this->items[] = $this->bodyDeCode($data);
  118 +
  119 + }
69 120
70 } 121 }
71 122
  123 +
72 /** 124 /**
73 * 解析每个 块 125 * 解析每个 块
74 * @param string $body 块字符串 126 * @param string $body 块字符串
@@ -79,25 +131,35 @@ class Body { @@ -79,25 +131,35 @@ class Body {
79 protected function parseItem(string $body):DataArray { 131 protected function parseItem(string $body):DataArray {
80 list($mime_header,$text) = explode("\r\n\r\n",$body,2); 132 list($mime_header,$text) = explode("\r\n\r\n",$body,2);
81 133
  134 + // 解析头部
82 $data = $this->parseMimeHeader($mime_header); 135 $data = $this->parseMimeHeader($mime_header);
83 136
  137 + $data->body = $text;
  138 +
  139 + return $this->bodyDeCode($data);
  140 +
  141 + }
84 142
  143 + /**
  144 + * @param DataArray $data
  145 + * @return DataArray
  146 + * @author:dc
  147 + * @time 2024/9/21 11:39
  148 + */
  149 + private function bodyDeCode(DataArray $data):DataArray {
85 // 处理body体 的编码 150 // 处理body体 的编码
86 switch ($data->get('Content-Transfer-Encoding')){ 151 switch ($data->get('Content-Transfer-Encoding')){
87 case 'quoted-printable':{ 152 case 'quoted-printable':{
88 - $text = quoted_printable_decode($text);break; 153 + $data->body = quoted_printable_decode($data->body);break;
89 } 154 }
90 case 'base64':{ 155 case 'base64':{
91 - $text = base64_decode($text);break; 156 + $data->body = base64_decode($data->body);break;
92 } 157 }
93 } 158 }
94 -  
95 - $data->body = $text;  
96 -  
97 return $data; 159 return $data;
98 -  
99 } 160 }
100 161
  162 +
101 /** 163 /**
102 * 解析邮件体里面的每个块 头部 164 * 解析邮件体里面的每个块 头部
103 * @param string $header 165 * @param string $header
@@ -126,11 +188,13 @@ class Body { @@ -126,11 +188,13 @@ class Body {
126 $contentType = explode(' ',trim(str_replace(';',' ',$data->get('Content-Type')))); 188 $contentType = explode(' ',trim(str_replace(';',' ',$data->get('Content-Type'))));
127 foreach ($contentType as $ct){ 189 foreach ($contentType as $ct){
128 $ct = trim($ct); 190 $ct = trim($ct);
  191 + // 这个才是真的类型
129 if(str_contains($ct,'/')){ 192 if(str_contains($ct,'/')){
130 $data->set('Content-Type',$ct); 193 $data->set('Content-Type',$ct);
131 }elseif (str_contains($ct,'=')){ 194 }elseif (str_contains($ct,'=')){
  195 + // 这里包含了其他
132 list($name,$val) = explode('=',$ct); 196 list($name,$val) = explode('=',$ct);
133 - $data->set($name,trim($val)); 197 + $data->set($name,trim(str_replace('"','',$val)));
134 } 198 }
135 } 199 }
136 } 200 }
@@ -168,9 +232,10 @@ class Body { @@ -168,9 +232,10 @@ class Body {
168 public function getHtml():string { 232 public function getHtml():string {
169 foreach ($this->items as $item){ 233 foreach ($this->items as $item){
170 if($item->eq('content-type','text/html')){ 234 if($item->eq('content-type','text/html')){
171 - return $item->body; 235 + return $item->body ? : '';
172 } 236 }
173 } 237 }
  238 + return '';
174 } 239 }
175 240
176 /** 241 /**