正在显示
13 个修改的文件
包含
311 行增加
和
362 行删除
| @@ -210,7 +210,7 @@ class Home extends Base { | @@ -210,7 +210,7 @@ class Home extends Base { | ||
| 210 | if(!empty($v['to_name'][0]['email'])){ | 210 | if(!empty($v['to_name'][0]['email'])){ |
| 211 | $v['to'] = $v['to_name'][0]['email']; | 211 | $v['to'] = $v['to_name'][0]['email']; |
| 212 | } | 212 | } |
| 213 | - $v['to_name'] = $v['to_name'][0]['name']??''; | 213 | + $v['to_name'] = MailFun::mb_coding($v['to_name'][0]['name']??''); |
| 214 | } | 214 | } |
| 215 | if(is_array($v['to_name'])){ | 215 | if(is_array($v['to_name'])){ |
| 216 | $v['to_name'] = ''; | 216 | $v['to_name'] = ''; |
| @@ -840,6 +840,13 @@ class Home extends Base { | @@ -840,6 +840,13 @@ class Home extends Base { | ||
| 840 | $data['cc'] = $data['cc'] ? json_decode($data['cc'],true) : []; | 840 | $data['cc'] = $data['cc'] ? json_decode($data['cc'],true) : []; |
| 841 | $data['bcc'] = $data['bcc'] ? json_decode($data['bcc'],true) : []; | 841 | $data['bcc'] = $data['bcc'] ? json_decode($data['bcc'],true) : []; |
| 842 | 842 | ||
| 843 | + $data['to_name'] = array_map(function ($t){ | ||
| 844 | + if(empty($t['name'])){ | ||
| 845 | + $t['name'] = MailFun::mb_coding($t['name']); | ||
| 846 | + } | ||
| 847 | + return $t; | ||
| 848 | + },$data['to_name']); | ||
| 849 | + | ||
| 843 | // 是否再次 重新获取 | 850 | // 是否再次 重新获取 |
| 844 | $reload = app()->request('reload',0,'intval'); | 851 | $reload = app()->request('reload',0,'intval'); |
| 845 | if($reload){ | 852 | if($reload){ |
| @@ -5,6 +5,7 @@ namespace Controller\fob_ai; | @@ -5,6 +5,7 @@ namespace Controller\fob_ai; | ||
| 5 | 5 | ||
| 6 | 6 | ||
| 7 | use Controller\Base; | 7 | use Controller\Base; |
| 8 | +use Lib\Mail\MailFun; | ||
| 8 | use Lib\Verify; | 9 | use Lib\Verify; |
| 9 | use Model\folderSql; | 10 | use Model\folderSql; |
| 10 | use function Swoole\Coroutine\Http\request; | 11 | use function Swoole\Coroutine\Http\request; |
| @@ -246,7 +247,7 @@ class MailListV2 extends Base { | @@ -246,7 +247,7 @@ class MailListV2 extends Base { | ||
| 246 | if(!empty($v['to_name'][0]['email'])){ | 247 | if(!empty($v['to_name'][0]['email'])){ |
| 247 | $v['to'] = $v['to_name'][0]['email']; | 248 | $v['to'] = $v['to_name'][0]['email']; |
| 248 | } | 249 | } |
| 249 | - $v['to_name'] = $v['to_name'][0]['name']??''; | 250 | + $v['to_name'] = MailFun::mb_coding($v['to_name'][0]['name']??''); |
| 250 | } | 251 | } |
| 251 | if(is_array($v['to_name'])){ | 252 | if(is_array($v['to_name'])){ |
| 252 | $v['to_name'] = ''; | 253 | $v['to_name'] = ''; |
lib/Imap/DataArray.php
0 → 100644
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace Lib\Imap; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * 数据 | ||
| 7 | + * @author:dc | ||
| 8 | + * @time 2024/9/21 9:27 | ||
| 9 | + * Class DataArray | ||
| 10 | + * @package Lib\Imap | ||
| 11 | + */ | ||
| 12 | +class DataArray { | ||
| 13 | + | ||
| 14 | + /** | ||
| 15 | + * 存储的数据 | ||
| 16 | + * @var array | ||
| 17 | + */ | ||
| 18 | + private array $attribute = []; | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * @param string $name | ||
| 22 | + * @param mixed $val | ||
| 23 | + * @param bool $append | ||
| 24 | + * @author:dc | ||
| 25 | + * @time 2024/9/21 9:33 | ||
| 26 | + */ | ||
| 27 | + public function set(string $name, mixed $val, bool $append = false): void | ||
| 28 | + { | ||
| 29 | + $name = strtolower($name); | ||
| 30 | + if($append && is_string($val) && $this->get($name)!==null ){ | ||
| 31 | + $this->attribute[$name] .= $val; | ||
| 32 | + }else{ | ||
| 33 | + $this->attribute[$name] = $val; | ||
| 34 | + } | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + | ||
| 38 | + /** | ||
| 39 | + * @param string $name | ||
| 40 | + * @return mixed | ||
| 41 | + * @author:dc | ||
| 42 | + * @time 2024/9/21 9:34 | ||
| 43 | + */ | ||
| 44 | + public function get(string $name): mixed | ||
| 45 | + { | ||
| 46 | + if(isset($this->attribute[$name])){ | ||
| 47 | + return $this->attribute[$name]; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + foreach ($this->attribute as $key=>$value){ | ||
| 51 | + // 不区分大小写对比 | ||
| 52 | + if(strcasecmp($key,$name)===0){ | ||
| 53 | + return $value; | ||
| 54 | + } | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + return null; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + /** | ||
| 61 | + * 不区分大小写比较字符串 | ||
| 62 | + * @param string $name | ||
| 63 | + * @param mixed $value | ||
| 64 | + * @return bool | ||
| 65 | + * @author:dc | ||
| 66 | + * @time 2024/9/21 9:57 | ||
| 67 | + */ | ||
| 68 | + public function eq(string $name,mixed $value):bool { | ||
| 69 | + return strcasecmp($this->get($name),$value) === 0; | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + | ||
| 73 | + public function __get(string $name): mixed | ||
| 74 | + { | ||
| 75 | + return $this->get($name); | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + | ||
| 79 | + public function __set(string $name, $value): void | ||
| 80 | + { | ||
| 81 | + $this->set($name,$value); | ||
| 82 | + } | ||
| 83 | + | ||
| 84 | + | ||
| 85 | + | ||
| 86 | +} |
| @@ -2,6 +2,8 @@ | @@ -2,6 +2,8 @@ | ||
| 2 | 2 | ||
| 3 | namespace Lib\Imap\Parse; | 3 | namespace Lib\Imap\Parse; |
| 4 | 4 | ||
| 5 | +use Lib\Imap\DataArray; | ||
| 6 | + | ||
| 5 | /** | 7 | /** |
| 6 | * 邮件内容 | 8 | * 邮件内容 |
| 7 | * @author:dc | 9 | * @author:dc |
| @@ -18,18 +20,28 @@ class Body { | @@ -18,18 +20,28 @@ class Body { | ||
| 18 | protected string $raw = ''; | 20 | protected string $raw = ''; |
| 19 | 21 | ||
| 20 | /** | 22 | /** |
| 21 | - * 解析后的数据 | ||
| 22 | - * @var array | 23 | + * 消息结构,解析后的邮件体 header |
| 24 | + * @var MessageItem | ||
| 23 | */ | 25 | */ |
| 24 | - protected array $item = []; | 26 | + protected MessageItem $msg; |
| 27 | + | ||
| 25 | 28 | ||
| 29 | + /** | ||
| 30 | + * 解析后的body数据 | ||
| 31 | + * @var DataArray[] | ||
| 32 | + */ | ||
| 33 | + private array $items = []; | ||
| 26 | 34 | ||
| 27 | - public function __construct(string $result) | 35 | + /** |
| 36 | + * Body constructor. | ||
| 37 | + * @param string $result | ||
| 38 | + * @param MessageItem $msg | ||
| 39 | + */ | ||
| 40 | + public function __construct(string $result, MessageItem $msg) | ||
| 28 | { | 41 | { |
| 29 | - // 匹配出id和数据 | ||
| 30 | - if(preg_match("/\* (\d+) FETCH \(/",$result)){ | 42 | + $this->raw = $result; |
| 31 | 43 | ||
| 32 | - } | 44 | + $this->msg = $msg; |
| 33 | 45 | ||
| 34 | $this->parse(); | 46 | $this->parse(); |
| 35 | } | 47 | } |
| @@ -42,11 +54,146 @@ class Body { | @@ -42,11 +54,146 @@ class Body { | ||
| 42 | * @time 2024/9/14 17:35 | 54 | * @time 2024/9/14 17:35 |
| 43 | */ | 55 | */ |
| 44 | protected function parse(){ | 56 | protected function parse(){ |
| 57 | + // 是否是多段 | ||
| 58 | + $boundary = $this->msg->header->getBoundary(); | ||
| 59 | + if($boundary){ | ||
| 60 | + // 切割成块 | ||
| 61 | + $items = explode($boundary,$this->raw); | ||
| 62 | + // 第一个块和最后一块 是没用的块 | ||
| 63 | + array_shift($items);array_pop($items); | ||
| 64 | + foreach ($items as $item){ | ||
| 65 | + $this->items[] = $this->parseItem($item); | ||
| 66 | + } | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + /** | ||
| 73 | + * 解析每个 块 | ||
| 74 | + * @param string $body 块字符串 | ||
| 75 | + * @return DataArray | ||
| 76 | + * @author:dc | ||
| 77 | + * @time 2024/9/21 9:51 | ||
| 78 | + */ | ||
| 79 | + protected function parseItem(string $body):DataArray { | ||
| 80 | + list($mime_header,$text) = explode("\r\n\r\n",$body,2); | ||
| 81 | + | ||
| 82 | + $data = $this->parseMimeHeader($mime_header); | ||
| 45 | 83 | ||
| 46 | 84 | ||
| 85 | + // 处理body体 的编码 | ||
| 86 | + switch ($data->get('Content-Transfer-Encoding')){ | ||
| 87 | + case 'quoted-printable':{ | ||
| 88 | + $text = quoted_printable_decode($text);break; | ||
| 89 | + } | ||
| 90 | + case 'base64':{ | ||
| 91 | + $text = base64_decode($text);break; | ||
| 92 | + } | ||
| 93 | + } | ||
| 94 | + | ||
| 95 | + $data->body = $text; | ||
| 96 | + | ||
| 97 | + return $data; | ||
| 47 | 98 | ||
| 48 | } | 99 | } |
| 49 | 100 | ||
| 101 | + /** | ||
| 102 | + * 解析邮件体里面的每个块 头部 | ||
| 103 | + * @param string $header | ||
| 104 | + * @return DataArray | ||
| 105 | + * @author:dc | ||
| 106 | + * @time 2024/9/21 9:18 | ||
| 107 | + */ | ||
| 108 | + protected function parseMimeHeader(string $header):DataArray { | ||
| 109 | + // 处理 描述信息, | ||
| 110 | + $header = explode("\r\n",trim($header)); | ||
| 111 | + $data = new DataArray(); | ||
| 112 | + $name = ''; | ||
| 113 | + foreach ($header as $head){ | ||
| 114 | + // 判断是否是上一行的 | ||
| 115 | + if(str_starts_with($head,' ') || str_starts_with($head,"\t")){ | ||
| 116 | + $data->set($name,' '.$head,true); | ||
| 117 | + }else{ | ||
| 118 | + list($name,$value) = explode(":",$head,2); | ||
| 119 | + $data->set($name,trim($value)); | ||
| 120 | + } | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + // 处理编码 | ||
| 124 | + if($data->get('Content-Type')){ | ||
| 125 | + // 切割成 每个小块 Content-Type: text/html;charset=utf-8 | ||
| 126 | + $contentType = explode(' ',trim(str_replace(';',' ',$data->get('Content-Type')))); | ||
| 127 | + foreach ($contentType as $ct){ | ||
| 128 | + $ct = trim($ct); | ||
| 129 | + if(str_contains($ct,'/')){ | ||
| 130 | + $data->set('Content-Type',$ct); | ||
| 131 | + }elseif (str_contains($ct,'=')){ | ||
| 132 | + list($name,$val) = explode('=',$ct); | ||
| 133 | + $data->set($name,trim($val)); | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | + } | ||
| 137 | + | ||
| 138 | + // 默认编码 | ||
| 139 | + if(!$data->Charset) $data->Charset = 'utf-8'; | ||
| 140 | + | ||
| 141 | + return $data; | ||
| 142 | + } | ||
| 143 | + | ||
| 144 | + | ||
| 145 | + /** | ||
| 146 | + * 读取纯文本的内容 | ||
| 147 | + * @author:dc | ||
| 148 | + * @time 2024/9/21 9:55 | ||
| 149 | + */ | ||
| 150 | + public function getText():string { | ||
| 151 | + foreach ($this->items as $item){ | ||
| 152 | + if($item->eq('content-type','text/plain')){ | ||
| 153 | + return $item->body; | ||
| 154 | + } | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + // 没找到 text | ||
| 158 | + return strip_tags($this->getHtml()); | ||
| 159 | + | ||
| 160 | + } | ||
| 161 | + | ||
| 162 | + /** | ||
| 163 | + * 读取 html文本 | ||
| 164 | + * @return string | ||
| 165 | + * @author:dc | ||
| 166 | + * @time 2024/9/21 10:02 | ||
| 167 | + */ | ||
| 168 | + public function getHtml():string { | ||
| 169 | + foreach ($this->items as $item){ | ||
| 170 | + if($item->eq('content-type','text/html')){ | ||
| 171 | + return $item->body; | ||
| 172 | + } | ||
| 173 | + } | ||
| 174 | + } | ||
| 175 | + | ||
| 176 | + /** | ||
| 177 | + * 有些邮件里面的图片是通过附件的形式发来的 | ||
| 178 | + * <img src="cid:xxxx" /> 这种就是附件图片,需要替换的 | ||
| 179 | + * @return array | ||
| 180 | + * @author:dc | ||
| 181 | + * @time 2024/9/21 10:53 | ||
| 182 | + */ | ||
| 183 | + public function getHtmlAndImg():array { | ||
| 184 | + $html = $this->getHtml(); | ||
| 185 | + | ||
| 186 | + } | ||
| 187 | + | ||
| 188 | + /** | ||
| 189 | + * 读取附件 | ||
| 190 | + * @return DataArray[] | ||
| 191 | + * @author:dc | ||
| 192 | + * @time 2024/9/21 10:05 | ||
| 193 | + */ | ||
| 194 | + public function getAttachment():array { | ||
| 195 | + | ||
| 196 | + } | ||
| 50 | 197 | ||
| 51 | 198 | ||
| 52 | 199 |
lib/Imap/Parse/Fetch.php
已删除
100644 → 0
| 1 | -<?php | ||
| 2 | - | ||
| 3 | -namespace Lib\Imap\Parse; | ||
| 4 | - | ||
| 5 | - | ||
| 6 | -/** | ||
| 7 | - * 解析邮件 | ||
| 8 | - * @author:dc | ||
| 9 | - * @time 2024/9/10 16:54 | ||
| 10 | - * Class Header | ||
| 11 | - */ | ||
| 12 | -class Fetch{ | ||
| 13 | - | ||
| 14 | - /** | ||
| 15 | - * @var array | ||
| 16 | - */ | ||
| 17 | - private array $attributes = []; | ||
| 18 | - | ||
| 19 | - /** | ||
| 20 | - * 原始头信息 | ||
| 21 | - * @var string | ||
| 22 | - */ | ||
| 23 | - protected string $raw_header; | ||
| 24 | - | ||
| 25 | - /** | ||
| 26 | - * Header constructor. | ||
| 27 | - * @param string $raw_header | ||
| 28 | - */ | ||
| 29 | - public function __construct(string $raw_header) | ||
| 30 | - { | ||
| 31 | - $this->raw_header = $raw_header; | ||
| 32 | - | ||
| 33 | - $this->rfc822_parse_headers(); | ||
| 34 | - } | ||
| 35 | - | ||
| 36 | - | ||
| 37 | - /** | ||
| 38 | - * @param string $name | ||
| 39 | - * @param string $value | ||
| 40 | - * @param bool $append | ||
| 41 | - * @author:dc | ||
| 42 | - * @time 2024/9/11 16:24 | ||
| 43 | - */ | ||
| 44 | - public function setAttribute(string $name, string $value, bool $append = true){ | ||
| 45 | - $name = strtolower($name); | ||
| 46 | - | ||
| 47 | - if(!$append){ | ||
| 48 | - $this->attributes[$name] = $value; | ||
| 49 | - }else{ | ||
| 50 | - if(isset($this->attributes[$name])) | ||
| 51 | - $this->attributes[$name] .= "\r\n".$value; | ||
| 52 | - else | ||
| 53 | - $this->attributes[$name] = $value; | ||
| 54 | - } | ||
| 55 | - } | ||
| 56 | - | ||
| 57 | - | ||
| 58 | - /** | ||
| 59 | - * 解析邮件头部 | ||
| 60 | - * @author:dc | ||
| 61 | - * @time 2024/9/10 16:29 | ||
| 62 | - */ | ||
| 63 | - private function rfc822_parse_headers(){ | ||
| 64 | - $header = explode("\r\n",$this->raw_header); | ||
| 65 | - $name = ''; | ||
| 66 | - foreach ($header as $str){ | ||
| 67 | - // 判断是否是上一行的 | ||
| 68 | - if(str_starts_with($str,' ') || str_starts_with($str,"\t")){ | ||
| 69 | - $this->setAttribute($name,$str); | ||
| 70 | - }else{ | ||
| 71 | - $str = explode(":",$str); | ||
| 72 | - $name = $str[0]; | ||
| 73 | - unset($str[0]); | ||
| 74 | - $this->setAttribute($name,implode(':',$str)); | ||
| 75 | - } | ||
| 76 | - | ||
| 77 | - } | ||
| 78 | - | ||
| 79 | - foreach ($this->attributes as $name => $attribute){ | ||
| 80 | - $attribute = trim($attribute); | ||
| 81 | - $this->attributes[$name] = $attribute; | ||
| 82 | - } | ||
| 83 | - } | ||
| 84 | - | ||
| 85 | - | ||
| 86 | - public function __get(string $name) | ||
| 87 | - { | ||
| 88 | - return $this->get($name); | ||
| 89 | - } | ||
| 90 | - | ||
| 91 | - /** | ||
| 92 | - * 读取字段 | ||
| 93 | - * @param string $name | ||
| 94 | - * @return mixed | ||
| 95 | - * @author:dc | ||
| 96 | - * @time 2024/9/11 15:06 | ||
| 97 | - */ | ||
| 98 | - public function get(string $name):mixed { | ||
| 99 | - $name = strtolower($name); | ||
| 100 | - | ||
| 101 | - $m = 'get'.str_replace(' ','',ucwords(str_replace('-',' ',$name))); | ||
| 102 | - | ||
| 103 | - if(method_exists($this,$m)){ | ||
| 104 | - return $this->{$m}(); | ||
| 105 | - } | ||
| 106 | - | ||
| 107 | - return $this->attributes[$name]??''; | ||
| 108 | - } | ||
| 109 | - | ||
| 110 | - | ||
| 111 | - /** | ||
| 112 | - * 获取收件地址 可能是假地址 | ||
| 113 | - * @param bool $is_obj 是否解析成对象 Address | ||
| 114 | - * @return Address[] | ||
| 115 | - * @author:dc | ||
| 116 | - * @time 2024/9/11 15:03 | ||
| 117 | - */ | ||
| 118 | - public function getTo() { | ||
| 119 | - // 如果有这个字段,就用这个字段 to字段的邮箱可能被伪造 | ||
| 120 | - if(!empty($this->attributes['delivered-to'])){ | ||
| 121 | - $to = $this->attributes['delivered-to']; | ||
| 122 | - }else{ | ||
| 123 | - $to = $this->attributes['to']??''; | ||
| 124 | - } | ||
| 125 | - | ||
| 126 | - return $this->parseAddress($to); | ||
| 127 | - } | ||
| 128 | - | ||
| 129 | - /** | ||
| 130 | - * 解析地址 | ||
| 131 | - * @param string $address | ||
| 132 | - * @return array | ||
| 133 | - * @author:dc | ||
| 134 | - * @time 2024/9/11 15:53 | ||
| 135 | - */ | ||
| 136 | - private function parseAddress(string $address){ | ||
| 137 | - $arr = []; | ||
| 138 | - foreach (explode(',',$address) as $str){ | ||
| 139 | - $arr[] = Address::make($str); | ||
| 140 | - } | ||
| 141 | - return $arr; | ||
| 142 | - } | ||
| 143 | - | ||
| 144 | - /** | ||
| 145 | - * 抄送人 | ||
| 146 | - * @return array | ||
| 147 | - * @author:dc | ||
| 148 | - * @time 2024/9/11 15:53 | ||
| 149 | - */ | ||
| 150 | - public function getCc() | ||
| 151 | - { | ||
| 152 | - return $this->parseAddress($this->attributes['cc']??''); | ||
| 153 | - } | ||
| 154 | - | ||
| 155 | - /** | ||
| 156 | - * 密送人 | ||
| 157 | - * @return array | ||
| 158 | - * @author:dc | ||
| 159 | - * @time 2024/9/11 15:54 | ||
| 160 | - */ | ||
| 161 | - public function getBcc() | ||
| 162 | - { | ||
| 163 | - return $this->parseAddress($this->attributes['bcc']??''); | ||
| 164 | - } | ||
| 165 | - | ||
| 166 | - | ||
| 167 | - | ||
| 168 | - /** | ||
| 169 | - * 发件人 可能是欺炸 发件人 | ||
| 170 | - * @return Address | ||
| 171 | - * @author:dc | ||
| 172 | - * @time 2024/9/11 15:19 | ||
| 173 | - */ | ||
| 174 | - public function getFrom():Address { | ||
| 175 | - return Address::make($this->attributes['from']??''); | ||
| 176 | - } | ||
| 177 | - | ||
| 178 | - /** | ||
| 179 | - * 获取解码后的主题 | ||
| 180 | - * @return string | ||
| 181 | - * @author:dc | ||
| 182 | - * @time 2024/9/11 15:22 | ||
| 183 | - */ | ||
| 184 | - public function getSubject():string { | ||
| 185 | - $subject = explode("\n",$this->attributes['subject']??''); | ||
| 186 | - foreach ($subject as $ak=>$str){ | ||
| 187 | - $subject[$ak] = DeCode::decode($str); | ||
| 188 | - } | ||
| 189 | - | ||
| 190 | - return implode("\n",$subject); | ||
| 191 | - } | ||
| 192 | - | ||
| 193 | - | ||
| 194 | - /** | ||
| 195 | - * Boundary | ||
| 196 | - * @param string $str | ||
| 197 | - * @return string | ||
| 198 | - * @author:dc | ||
| 199 | - * @time 2024/9/11 16:05 | ||
| 200 | - */ | ||
| 201 | - public function getBoundary(string $str = ''): string | ||
| 202 | - { | ||
| 203 | - $pre = "/boundary=(.*?(?=;)|(.*))/i"; | ||
| 204 | - // 在内容类型中读取 大多少情况都在这里面 | ||
| 205 | - $contentType = $str ? $str: ($this->attributes['content-type']??''); | ||
| 206 | - if($contentType){ | ||
| 207 | - preg_match($pre,$contentType,$b); | ||
| 208 | - if(!empty($b[1])){ | ||
| 209 | - return trim(str_replace(['"',';'],'',$b[1])); | ||
| 210 | - } | ||
| 211 | - } | ||
| 212 | - if($this->raw_header && !$str){ | ||
| 213 | - return $this->getBoundary($this->raw_header); | ||
| 214 | - } | ||
| 215 | - | ||
| 216 | - return ''; | ||
| 217 | - } | ||
| 218 | - | ||
| 219 | - /** | ||
| 220 | - * 这个是是否加急 1加急 3普通 5不急 | ||
| 221 | - * @return string | ||
| 222 | - */ | ||
| 223 | - public function getPriority(): string | ||
| 224 | - { | ||
| 225 | - if(!empty($this->attributes['priority'])){ | ||
| 226 | - return $this->attributes['priority']; | ||
| 227 | - } | ||
| 228 | - | ||
| 229 | - if(!empty($this->attributes['x-priority'])){ | ||
| 230 | - return $this->attributes['x-priority']; | ||
| 231 | - } | ||
| 232 | - | ||
| 233 | - return '3'; | ||
| 234 | - } | ||
| 235 | - | ||
| 236 | - | ||
| 237 | - | ||
| 238 | - /** | ||
| 239 | - * @return array | ||
| 240 | - */ | ||
| 241 | - public function getAttributes(): array | ||
| 242 | - { | ||
| 243 | - return $this->attributes; | ||
| 244 | - } | ||
| 245 | - | ||
| 246 | - /** | ||
| 247 | - * @return array | ||
| 248 | - * @author:dc | ||
| 249 | - * @time 2024/9/11 16:15 | ||
| 250 | - */ | ||
| 251 | - public function toArray():array { | ||
| 252 | - $arr = []; | ||
| 253 | - foreach ($this->attributes as $key=>$attr){ | ||
| 254 | - $arr[$key] = $this->get($key); | ||
| 255 | - } | ||
| 256 | - | ||
| 257 | - return $arr; | ||
| 258 | - } | ||
| 259 | - | ||
| 260 | -} |
| @@ -67,11 +67,9 @@ class Header{ | @@ -67,11 +67,9 @@ class Header{ | ||
| 67 | // 判断是否是上一行的 | 67 | // 判断是否是上一行的 |
| 68 | if(str_starts_with($str,' ') || str_starts_with($str,"\t")){ | 68 | if(str_starts_with($str,' ') || str_starts_with($str,"\t")){ |
| 69 | $this->setAttribute($name,$str); | 69 | $this->setAttribute($name,$str); |
| 70 | - }else{ | ||
| 71 | - $str = explode(":",$str); | ||
| 72 | - $name = $str[0]; | ||
| 73 | - unset($str[0]); | ||
| 74 | - $this->setAttribute($name,implode(':',$str)); | 70 | + }elseif(str_contains($str,':')){ |
| 71 | + list($name, $str) = explode(":",$str,2); | ||
| 72 | + $this->setAttribute($name,$str); | ||
| 75 | } | 73 | } |
| 76 | 74 | ||
| 77 | } | 75 | } |
| @@ -146,7 +146,13 @@ class MessageItem { | @@ -146,7 +146,13 @@ class MessageItem { | ||
| 146 | * @time 2024/9/20 15:14 | 146 | * @time 2024/9/20 15:14 |
| 147 | */ | 147 | */ |
| 148 | public function getBody():Body { | 148 | public function getBody():Body { |
| 149 | - return $this->msg->folder->getBody($this->uid,true); | 149 | + if(isset($this->body)){ |
| 150 | + return $this->body; | ||
| 151 | + } | ||
| 152 | + | ||
| 153 | + $this->body = $this->msg->getBody($this); | ||
| 154 | + | ||
| 155 | + return $this->body; | ||
| 150 | } | 156 | } |
| 151 | 157 | ||
| 152 | 158 |
| @@ -154,11 +154,11 @@ class Messager implements \IteratorAggregate { | @@ -154,11 +154,11 @@ class Messager implements \IteratorAggregate { | ||
| 154 | $header = substr($header,strlen($num[0]),strlen($header)); | 154 | $header = substr($header,strlen($num[0]),strlen($header)); |
| 155 | 155 | ||
| 156 | }else{ | 156 | }else{ |
| 157 | - // 以3个\r\n为结束 | ||
| 158 | - $str = explode("\r\n\r\n\r\n",trim($str)); | 157 | + // 以2个\r\n为结束 |
| 158 | + $str = explode("\r\n\r\n",trim($str)); | ||
| 159 | $header = array_shift($str); | 159 | $header = array_shift($str); |
| 160 | // 剩余的字符串 | 160 | // 剩余的字符串 |
| 161 | - $tokens = explode(' ',implode("\r\n\r\n\r\n",$str)); | 161 | + $tokens = explode(' ',implode("\r\n\r\n",$str)); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | $this->item[$msgno]->header = new Header($header); | 164 | $this->item[$msgno]->header = new Header($header); |
| @@ -183,6 +183,22 @@ class Messager implements \IteratorAggregate { | @@ -183,6 +183,22 @@ class Messager implements \IteratorAggregate { | ||
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | 185 | ||
| 186 | + /** | ||
| 187 | + * 获取一条消息 | ||
| 188 | + * @return bool|MessageItem | ||
| 189 | + * @author:dc | ||
| 190 | + * @time 2024/9/20 16:48 | ||
| 191 | + */ | ||
| 192 | + public function first():bool|MessageItem { | ||
| 193 | + if($this->item){ | ||
| 194 | + return $this->item[array_key_first($this->item)]; | ||
| 195 | + } | ||
| 196 | + return false; | ||
| 197 | + } | ||
| 198 | + | ||
| 199 | + | ||
| 200 | + | ||
| 201 | + | ||
| 186 | } | 202 | } |
| 187 | 203 | ||
| 188 | 204 |
lib/Imap/Request/Body.php
已删除
100644 → 0
| 1 | -<?php | ||
| 2 | - | ||
| 3 | - | ||
| 4 | -namespace Lib\Imap\Request; | ||
| 5 | - | ||
| 6 | -use Lib\Imap\Imap; | ||
| 7 | - | ||
| 8 | -use Lib\Imap\Parse\Body as ParseBody; | ||
| 9 | - | ||
| 10 | -/** | ||
| 11 | - * body邮件内容 | ||
| 12 | - * @author:dc | ||
| 13 | - * @time 2024/9/20 14:53 | ||
| 14 | - * Class Body | ||
| 15 | - * @package Lib\Imap\Request | ||
| 16 | - */ | ||
| 17 | -class Body extends Request { | ||
| 18 | - | ||
| 19 | - /** | ||
| 20 | - * @var Folder | ||
| 21 | - */ | ||
| 22 | - protected Folder $folder; | ||
| 23 | - | ||
| 24 | - | ||
| 25 | - | ||
| 26 | - public function __construct(Imap $imap, Folder $folder) | ||
| 27 | - { | ||
| 28 | - parent::__construct($imap); | ||
| 29 | - | ||
| 30 | - $this->folder = $folder; | ||
| 31 | - } | ||
| 32 | - | ||
| 33 | - | ||
| 34 | - public function exec(): static{return $this;} | ||
| 35 | - | ||
| 36 | - | ||
| 37 | - /** | ||
| 38 | - * 读取邮件body | ||
| 39 | - * @param int $num | ||
| 40 | - * @param bool $is_uid | ||
| 41 | - * @return ParseBody | ||
| 42 | - * @author:dc | ||
| 43 | - * @time 2024/9/20 15:40 | ||
| 44 | - */ | ||
| 45 | - public function get(int $num, bool $is_uid = false):ParseBody { | ||
| 46 | - $this->folder->exec(); // 防止在其他文件夹下面 | ||
| 47 | - $this->cmd("%sFETCH %s (RFC822.BODY)", $is_uid ? 'UID ' : '', $num); | ||
| 48 | - | ||
| 49 | - return (new ParseBody($this->result ? $this->result[0] : '')); | ||
| 50 | - } | ||
| 51 | - | ||
| 52 | - | ||
| 53 | - | ||
| 54 | - | ||
| 55 | -} |
| @@ -4,6 +4,7 @@ | @@ -4,6 +4,7 @@ | ||
| 4 | namespace Lib\Imap\Request; | 4 | namespace Lib\Imap\Request; |
| 5 | 5 | ||
| 6 | use Lib\Imap\Imap; | 6 | use Lib\Imap\Imap; |
| 7 | +use Lib\Imap\Parse\MessageItem; | ||
| 7 | 8 | ||
| 8 | /** | 9 | /** |
| 9 | * 登录 | 10 | * 登录 |
| @@ -218,20 +219,5 @@ class Folder extends Request{ | @@ -218,20 +219,5 @@ class Folder extends Request{ | ||
| 218 | } | 219 | } |
| 219 | 220 | ||
| 220 | 221 | ||
| 221 | - /** | ||
| 222 | - * 读取body体 | ||
| 223 | - * @param int $num | ||
| 224 | - * @param false $is_uid | ||
| 225 | - * @return \Lib\Imap\Parse\Body | ||
| 226 | - * @author:dc | ||
| 227 | - * @time 2024/9/20 15:37 | ||
| 228 | - */ | ||
| 229 | - public function getBody(int $num, bool $is_uid = false):\Lib\Imap\Parse\Body{ | ||
| 230 | - $body = (new Body($this->imap,$this)); | ||
| 231 | - return $body->get($num, $is_uid = false); | ||
| 232 | - } | ||
| 233 | - | ||
| 234 | - | ||
| 235 | - | ||
| 236 | 222 | ||
| 237 | } | 223 | } |
| @@ -5,6 +5,8 @@ namespace Lib\Imap\Request; | @@ -5,6 +5,8 @@ namespace Lib\Imap\Request; | ||
| 5 | 5 | ||
| 6 | use Lib\Imap\Imap; | 6 | use Lib\Imap\Imap; |
| 7 | use Lib\Imap\ImapSearch; | 7 | use Lib\Imap\ImapSearch; |
| 8 | +use Lib\Imap\Parse\Body as ParseBody; | ||
| 9 | +use Lib\Imap\Parse\MessageItem; | ||
| 8 | use Lib\Imap\Parse\Messager; | 10 | use Lib\Imap\Parse\Messager; |
| 9 | 11 | ||
| 10 | /** | 12 | /** |
| @@ -62,27 +64,27 @@ class Msg extends Request{ | @@ -62,27 +64,27 @@ class Msg extends Request{ | ||
| 62 | 64 | ||
| 63 | /** | 65 | /** |
| 64 | * 使用uid进行查询 | 66 | * 使用uid进行查询 |
| 65 | - * @param array $uids | 67 | + * @param array|int $uids |
| 66 | * @return $this | 68 | * @return $this |
| 67 | * @author:dc | 69 | * @author:dc |
| 68 | * @time 2024/9/14 14:06 | 70 | * @time 2024/9/14 14:06 |
| 69 | */ | 71 | */ |
| 70 | - public function uid(array $uids):static { | 72 | + public function uid(array|int $uids):static { |
| 71 | $this->isUid = true; | 73 | $this->isUid = true; |
| 72 | - $this->number = $uids; | 74 | + $this->number = is_array($uids) ? $uids : [$uids]; |
| 73 | return $this; | 75 | return $this; |
| 74 | } | 76 | } |
| 75 | 77 | ||
| 76 | /** | 78 | /** |
| 77 | * 使用编号进行查询 | 79 | * 使用编号进行查询 |
| 78 | - * @param array $msgno | 80 | + * @param array|int $msgno |
| 79 | * @return $this | 81 | * @return $this |
| 80 | * @author:dc | 82 | * @author:dc |
| 81 | * @time 2024/9/14 14:06 | 83 | * @time 2024/9/14 14:06 |
| 82 | */ | 84 | */ |
| 83 | - public function msgno(array $msgno):static { | 85 | + public function msgno(array|int $msgno):static { |
| 84 | $this->isUid = false; | 86 | $this->isUid = false; |
| 85 | - $this->number = $msgno; | 87 | + $this->number = is_array($msgno)?$msgno:[$msgno]; |
| 86 | return $this; | 88 | return $this; |
| 87 | } | 89 | } |
| 88 | 90 | ||
| @@ -126,15 +128,20 @@ class Msg extends Request{ | @@ -126,15 +128,20 @@ class Msg extends Request{ | ||
| 126 | } | 128 | } |
| 127 | 129 | ||
| 128 | 130 | ||
| 129 | - public function getBody(){ | 131 | + /** |
| 132 | + * 读取body 体 | ||
| 133 | + * @param MessageItem $msg | ||
| 134 | + * @return ParseBody | ||
| 135 | + * @author:dc | ||
| 136 | + * @time 2024/9/20 17:09 | ||
| 137 | + */ | ||
| 138 | + public function getBody(MessageItem $msg){ | ||
| 130 | $this->folder->exec(); // 防止在其他文件夹下面 | 139 | $this->folder->exec(); // 防止在其他文件夹下面 |
| 131 | - $this->cmd( | ||
| 132 | - "%sFETCH %s (UID FLAGS INTERNALDATE RFC822.SIZE RFC822.HEADER)", | ||
| 133 | - $this->isUid?'UID ':'', | ||
| 134 | - implode(',',$this->number) | ||
| 135 | - ); | ||
| 136 | 140 | ||
| 137 | - return new Messager($this->result, $this); | 141 | + $this->cmd("UID FETCH %s (RFC822.TEXT)", $msg->uid); |
| 142 | + | ||
| 143 | + return (new ParseBody(implode('',$this->result),$msg)); | ||
| 144 | + | ||
| 138 | } | 145 | } |
| 139 | 146 | ||
| 140 | 147 |
| @@ -75,6 +75,16 @@ if($login->isOk()){// 登录成功 | @@ -75,6 +75,16 @@ if($login->isOk()){// 登录成功 | ||
| 75 | // 获取某个字段 | 75 | // 获取某个字段 |
| 76 | $msg->header->get('subject'); | 76 | $msg->header->get('subject'); |
| 77 | 77 | ||
| 78 | + // html内容 | ||
| 79 | + $msg->body->getHtml(); | ||
| 80 | + // 纯文本内容 | ||
| 81 | + $msg->body->getText(); | ||
| 82 | + // 获取附件 | ||
| 83 | + foreach ($msg->body->getAttachment() as $attachment){ | ||
| 84 | + // 存起来 | ||
| 85 | + file_put_contents($attachment->get('filename'),$attachment->get('body')); | ||
| 86 | + } | ||
| 87 | + | ||
| 78 | }); | 88 | }); |
| 79 | 89 | ||
| 80 | 90 |
-
请 注册 或 登录 后发表评论